diff --git a/.gitignore b/.gitignore index cf7ede8bb..436b4e301 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ dist-*/ sandbox/ .tsbuildinfo -tsconfig.tsbuildinfo +tsconfig.build.tsbuildinfo tsup.config.bundled_* vite.config.js.timestamp-* vite.config.ts.timestamp-* diff --git a/packages/react/.templates/sandbox/player.tsx b/packages/react/.templates/sandbox/player.tsx index 5d4812953..3c7c8adfd 100644 --- a/packages/react/.templates/sandbox/player.tsx +++ b/packages/react/.templates/sandbox/player.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react'; +import * as React from 'react'; import { isHLSProvider, @@ -20,10 +20,10 @@ import { import { textTracks } from './tracks'; export function Player() { - let player = useRef(null), - [src, setSrc] = useState(''); + let player = React.useRef(null), + [src, setSrc] = React.useState(''); - useEffect(() => { + React.useEffect(() => { // Initialize src. changeSource('audio'); diff --git a/packages/react/.templates/sandbox/tracks.ts b/packages/react/.templates/sandbox/tracks.ts index 6554d7e58..66e0ca33b 100644 --- a/packages/react/.templates/sandbox/tracks.ts +++ b/packages/react/.templates/sandbox/tracks.ts @@ -20,4 +20,4 @@ export const textTracks = [ language: 'en-US', default: true, }, -]; +] as const; diff --git a/packages/react/package.json b/packages/react/package.json index 15ce4abf6..6d9d68a50 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -18,11 +18,10 @@ ], "scripts": { "analyze": "maverick analyze \"src/**/*.tsx\" --framework react", - "dev": "pnpm clean && pnpm build:core && pnpm build:icons && pnpm build:types && pnpm watch", + "dev": "pnpm clean && pnpm build:icons && pnpm build:types && pnpm watch", "build": "pnpm build:icons && rollup -c", "build:icons": "node .scripts/build-icons.js", "build:types": "tsc -p tsconfig.build.json", - "build:core": "pnpm -F vidstack build:local && pnpm -F vidstack types", "sandbox": "node ../../.scripts/sandbox.js", "sandbox:build": "vite build sandbox", "types": "pnpm build:types && rollup -c --config-types", diff --git a/packages/react/rollup.config.js b/packages/react/rollup.config.js index 1f740bc53..a06b0eb0b 100644 --- a/packages/react/rollup.config.js +++ b/packages/react/rollup.config.js @@ -2,29 +2,50 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { nodeResolve } from '@rollup/plugin-node-resolve'; +import chokidar from 'chokidar'; import { transformSync } from 'esbuild'; import fs from 'fs-extra'; import { defineConfig } from 'rollup'; import dts from 'rollup-plugin-dts'; import esbuildPlugin from 'rollup-plugin-esbuild'; -const __dirname = path.dirname(fileURLToPath(import.meta.url)), - ROOT_DIR = path.resolve(__dirname, '.'), - STYLES_DIR = path.resolve(ROOT_DIR, 'player/styles'), - VIDSTACK_PKG_DIR = path.resolve(ROOT_DIR, 'node_modules/vidstack'), - VIDSTACK_PKG_PLAYER_STYLES_DIR = path.resolve(VIDSTACK_PKG_DIR, 'player/styles'); - const MODE_WATCH = process.argv.includes('-w'), - MODE_TYPES = process.argv.includes('--config-types'), - EXTERNAL = ['react', 'react-dom', 'media-icons', 'media-captions', 'hls.js', /@radix-ui/], - NPM = [define({ dev: true }), define({ dev: false })]; + MODE_TYPES = process.argv.includes('--config-types'); -// Styles. -copyStyles(); -copyTailwind(); +const DIRNAME = path.dirname(fileURLToPath(import.meta.url)), + ROOT_DIR = path.resolve(DIRNAME, '.'), + STYLES_DIR = path.resolve(ROOT_DIR, 'player/styles'), + VIDSTACK_PKG_DIR = path.resolve(ROOT_DIR, 'node_modules/vidstack'), + VIDSTACK_PKG_PLAYER_STYLES_DIR = path.resolve(VIDSTACK_PKG_DIR, 'player/styles'), + VIDSTACK_LOCAL_PATH = path.resolve('../vidstack/src/index.ts'); + +const EXTERNAL_PACKAGES = [ + 'react', + 'react-dom', + 'media-icons', + 'media-captions', + 'hls.js', + /@radix-ui/, + ], + NPM_BUNDLES = [define({ dev: true }), define({ dev: false })], + TYPES_BUNDLES = [defineTypes()]; + +// Styles +if (!MODE_TYPES) { + copyStyles(); + copyTailwind(); + + if (MODE_WATCH) { + chokidar.watch('player/styles/**').on('all', (_, path) => { + if (path !== 'player/styles/default/theme.css') buildDefaultTheme(); + }); + } else { + buildDefaultTheme(); + } +} export default defineConfig( - MODE_WATCH ? [defineTypes(), ...NPM] : MODE_TYPES ? [defineTypes()] : NPM, + MODE_WATCH ? [...TYPES_BUNDLES, ...NPM_BUNDLES] : MODE_TYPES ? TYPES_BUNDLES : NPM_BUNDLES, ); /** @@ -33,29 +54,30 @@ export default defineConfig( function defineTypes() { return { input: { - index: 'types/index.d.ts', - icons: 'types/icons.d.ts', - 'player/layouts/default': 'types/components/layouts/default/index.d.ts', + index: 'types/react/src/index.d.ts', + icons: 'types/react/src/icons.d.ts', + 'player/layouts/default': 'types/react/src/components/layouts/default/index.d.ts', }, output: { dir: '.', chunkFileNames: 'dist/types/[name].d.ts', manualChunks(id) { - if (id.includes('maverick')) return 'vidstack-framework.d'; - if (id.includes('vidstack')) return 'vidstack.d'; + if (id.includes('react/src')) return 'vidstack-react'; + if (id.includes('maverick')) return 'vidstack-framework'; + if (id.includes('vidstack')) return 'vidstack'; }, }, - external: EXTERNAL, + external: EXTERNAL_PACKAGES, plugins: [ - dts({ respectExternal: true }), { - name: 'cleanup', - closeBundle() { - if (!MODE_WATCH) { - fs.rmSync('types', { recursive: true }); + name: 'resolve-vidstack-types', + resolveId(id) { + if (id === 'vidstack') { + return 'types/vidstack/src/index.d.ts'; } }, }, + dts({ respectExternal: true }), ], }; } @@ -91,7 +113,7 @@ function define({ dev }) { treeshake: true, preserveEntrySignatures: 'allow-extension', maxParallelFileOps: !dev ? 1 : 20, - external: EXTERNAL, + external: EXTERNAL_PACKAGES, output: { format: 'esm', dir: `dist/${alias}`, @@ -101,6 +123,27 @@ function define({ dev }) { }, }, plugins: [ + { + name: 'vidstack-link', + resolveId(id) { + if (id === ':virtual/env') { + return id; + } else if (id === 'vidstack') { + return VIDSTACK_LOCAL_PATH; + } + }, + load(id) { + if (id === ':virtual/env') { + return 'export const IS_SERVER = typeof document === "undefined";'; + } + }, + transform(code) { + if (code.includes('__SERVER__')) { + code = code.replace(/__SERVER__/g, 'IS_SERVER'); + return "import { IS_SERVER } from ':virtual/env';\n" + code; + } + }, + }, nodeResolve({ exportConditions: dev ? ['development', 'production', 'default'] @@ -172,3 +215,16 @@ function copyTailwind() { fs.copyFileSync(tailwindFilePath, path.resolve(ROOT_DIR, 'tailwind.cjs')); fs.copyFileSync(tailwindDTSFilePath, path.resolve(ROOT_DIR, 'tailwind.d.cts')); } + +function buildDefaultTheme() { + // CSS merge. + let defaultStyles = fs.readFileSync('player/styles/base.css', 'utf-8'); + + const themeDir = 'player/styles/default'; + for (const file of fs.readdirSync(themeDir, 'utf-8')) { + if (file === 'theme.css' || file === 'layouts') continue; + defaultStyles += '\n' + fs.readFileSync(`${themeDir}/${file}`, 'utf-8'); + } + + fs.writeFileSync('player/styles/default/theme.css', defaultStyles); +} diff --git a/packages/react/src/components/layouts/default/context.ts b/packages/react/src/components/layouts/default/context.ts index 1dbe9c6c2..b9b9446d0 100644 --- a/packages/react/src/components/layouts/default/context.ts +++ b/packages/react/src/components/layouts/default/context.ts @@ -1,6 +1,6 @@ import * as React from 'react'; -import type { DefaultLayoutTranslations } from 'vidstack/local'; +import type { DefaultLayoutTranslations } from 'vidstack'; import type { DefaultLayoutIcons } from './icons'; diff --git a/packages/react/src/components/layouts/default/icons.tsx b/packages/react/src/components/layouts/default/icons.tsx index 00e615781..f8c2c2761 100644 --- a/packages/react/src/components/layouts/default/icons.tsx +++ b/packages/react/src/components/layouts/default/icons.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import type { PropsWithoutRef, SVGProps } from 'react'; import arrowLeftPaths from 'media-icons/dist/icons/arrow-left.js'; import chaptersIconPaths from 'media-icons/dist/icons/chapters.js'; @@ -73,7 +72,8 @@ export const defaultLayoutIcons: DefaultLayoutIcons = { }, }; -export interface DefaultLayoutIconProps extends PropsWithoutRef> {} +export interface DefaultLayoutIconProps + extends React.PropsWithoutRef> {} export interface DefaultLayoutIcon { (props: DefaultLayoutIconProps): React.ReactNode; diff --git a/packages/react/src/components/layouts/default/shared-layout.tsx b/packages/react/src/components/layouts/default/shared-layout.tsx index ba0177bb5..927f8eadf 100644 --- a/packages/react/src/components/layouts/default/shared-layout.tsx +++ b/packages/react/src/components/layouts/default/shared-layout.tsx @@ -5,7 +5,7 @@ import { isTrackCaptionKind, type DefaultLayoutTranslations, type TooltipPlacement, -} from 'vidstack/local'; +} from 'vidstack'; import { useAudioOptions } from '../../../hooks/options/use-audio-options'; import { useCaptionOptions } from '../../../hooks/options/use-caption-options'; diff --git a/packages/react/src/components/primitives/instances.ts b/packages/react/src/components/primitives/instances.ts index c05efda99..53cf717e4 100644 --- a/packages/react/src/components/primitives/instances.ts +++ b/packages/react/src/components/primitives/instances.ts @@ -34,7 +34,7 @@ import { TooltipContent, TooltipTrigger, VolumeSlider, -} from 'vidstack/local'; +} from 'vidstack'; // Core export class MediaPlayerInstance extends MediaPlayer {} diff --git a/packages/react/src/components/provider.tsx b/packages/react/src/components/provider.tsx index 0de271752..43eac1783 100644 --- a/packages/react/src/components/provider.tsx +++ b/packages/react/src/components/provider.tsx @@ -6,7 +6,7 @@ import { useStateContext, type ReactElementProps, } from 'maverick.js/react'; -import { mediaState } from 'vidstack/local'; +import { mediaState } from 'vidstack'; import { MediaProviderInstance } from './primitives/instances'; diff --git a/packages/react/src/components/ui/buttons/caption-button.tsx b/packages/react/src/components/ui/buttons/caption-button.tsx index 867f0010b..b6efbfae8 100644 --- a/packages/react/src/components/ui/buttons/caption-button.tsx +++ b/packages/react/src/components/ui/buttons/caption-button.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { composeRefs, createReactComponent, type ReactElementProps } from 'maverick.js/react'; -import { CaptionButtonInstance, MuteButtonInstance } from '../../primitives/instances'; +import { CaptionButtonInstance } from '../../primitives/instances'; import { Primitive } from '../../primitives/nodes'; /* ------------------------------------------------------------------------------------------------- @@ -12,7 +12,7 @@ import { Primitive } from '../../primitives/nodes'; const CaptionButtonBridge = createReactComponent(CaptionButtonInstance); export interface CaptionButtonProps - extends ReactElementProps { + extends ReactElementProps { asChild?: boolean; children?: React.ReactNode; ref?: React.Ref; diff --git a/packages/react/src/components/ui/poster.tsx b/packages/react/src/components/ui/poster.tsx index 013b2ee2e..4055dddb7 100644 --- a/packages/react/src/components/ui/poster.tsx +++ b/packages/react/src/components/ui/poster.tsx @@ -7,7 +7,7 @@ import { useStateContext, type ReactElementProps, } from 'maverick.js/react'; -import { mediaState } from 'vidstack/local'; +import { mediaState } from 'vidstack'; import { PosterInstance } from '../primitives/instances'; import { Primitive } from '../primitives/nodes'; diff --git a/packages/react/src/components/ui/radio-group.tsx b/packages/react/src/components/ui/radio-group.tsx index 6a24b8d42..0cb4b4e26 100644 --- a/packages/react/src/components/ui/radio-group.tsx +++ b/packages/react/src/components/ui/radio-group.tsx @@ -2,7 +2,7 @@ * RadioGroup * -----------------------------------------------------------------------------------------------*/ -import React from 'react'; +import * as React from 'react'; import { composeRefs, createReactComponent, type ReactElementProps } from 'maverick.js/react'; diff --git a/packages/react/src/components/ui/sliders/slider-value.tsx b/packages/react/src/components/ui/sliders/slider-value.tsx index adffd540e..e58c12202 100644 --- a/packages/react/src/components/ui/sliders/slider-value.tsx +++ b/packages/react/src/components/ui/sliders/slider-value.tsx @@ -1,3 +1,5 @@ +import * as React from 'react'; + import { createReactComponent, type ReactElementProps } from 'maverick.js/react'; import { SliderValueInstance } from '../../primitives/instances'; diff --git a/packages/react/src/components/ui/sliders/time-slider.tsx b/packages/react/src/components/ui/sliders/time-slider.tsx index 38d696d9f..5db9a2ce2 100644 --- a/packages/react/src/components/ui/sliders/time-slider.tsx +++ b/packages/react/src/components/ui/sliders/time-slider.tsx @@ -9,7 +9,7 @@ import { type ReactElementProps, } from 'maverick.js/react'; import { VTTCue } from 'media-captions'; -import { mediaState } from 'vidstack/local'; +import { mediaState } from 'vidstack'; import { SliderChaptersInstance, diff --git a/packages/react/src/components/ui/thumbnail.tsx b/packages/react/src/components/ui/thumbnail.tsx index 0dd381db6..36385961c 100644 --- a/packages/react/src/components/ui/thumbnail.tsx +++ b/packages/react/src/components/ui/thumbnail.tsx @@ -7,7 +7,7 @@ import { useStateContext, type ReactElementProps, } from 'maverick.js/react'; -import { mediaState } from 'vidstack/local'; +import { mediaState } from 'vidstack'; import { ThumbnailInstance } from '../primitives/instances'; import { Primitive, type PrimitivePropsWithRef } from '../primitives/nodes'; diff --git a/packages/react/src/globals.d.ts b/packages/react/src/globals.d.ts index fdec227a9..19d91a1ac 100644 --- a/packages/react/src/globals.d.ts +++ b/packages/react/src/globals.d.ts @@ -1,5 +1,6 @@ declare global { const __DEV__: boolean; + const __SERVER__: boolean; } export {}; diff --git a/packages/react/src/hooks/create-text-track.ts b/packages/react/src/hooks/create-text-track.ts index 1ba14a5a8..ae8340c19 100644 --- a/packages/react/src/hooks/create-text-track.ts +++ b/packages/react/src/hooks/create-text-track.ts @@ -1,7 +1,7 @@ -import React from 'react'; +import * as React from 'react'; import { useReactContext } from 'maverick.js/react'; -import { mediaContext, TextTrack, type TextTrackInit } from 'vidstack/local'; +import { mediaContext, TextTrack, type TextTrackInit } from 'vidstack'; /** * Creates a new `TextTrack` object and adds it to the player. diff --git a/packages/react/src/hooks/options/use-audio-options.ts b/packages/react/src/hooks/options/use-audio-options.ts index b36a0652e..492a39b23 100644 --- a/packages/react/src/hooks/options/use-audio-options.ts +++ b/packages/react/src/hooks/options/use-audio-options.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { useReactContext, useSignal } from 'maverick.js/react'; -import { mediaContext, type AudioTrack } from 'vidstack/local'; +import { mediaContext, type AudioTrack } from 'vidstack'; /** * @docs {@link https://www.vidstack.io/docs/player/api/hooks/use-audio-options} diff --git a/packages/react/src/hooks/options/use-caption-options.ts b/packages/react/src/hooks/options/use-caption-options.ts index 91f2278a8..545b59c7d 100644 --- a/packages/react/src/hooks/options/use-caption-options.ts +++ b/packages/react/src/hooks/options/use-caption-options.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import { useReactContext, useSignal } from 'maverick.js/react'; import { isString } from 'maverick.js/std'; -import { isTrackCaptionKind, mediaContext, type TextTrack } from 'vidstack/local'; +import { isTrackCaptionKind, mediaContext, type TextTrack } from 'vidstack'; /** * @docs {@link https://www.vidstack.io/docs/player/api/hooks/use-caption-options} diff --git a/packages/react/src/hooks/options/use-chapter-options.ts b/packages/react/src/hooks/options/use-chapter-options.ts index 6b93050e1..036ebc922 100644 --- a/packages/react/src/hooks/options/use-chapter-options.ts +++ b/packages/react/src/hooks/options/use-chapter-options.ts @@ -3,7 +3,7 @@ import * as React from 'react'; import { effect, type StopEffect } from 'maverick.js'; import { useReactContext } from 'maverick.js/react'; import type { VTTCue } from 'media-captions'; -import { formatSpokenTime, formatTime, mediaContext } from 'vidstack/local'; +import { formatSpokenTime, formatTime, mediaContext } from 'vidstack'; import { useActiveTextCues } from '../use-active-text-cues'; import { useActiveTextTrack } from '../use-active-text-track'; diff --git a/packages/react/src/hooks/options/use-playback-rate-options.ts b/packages/react/src/hooks/options/use-playback-rate-options.ts index 0f4ae7516..bef5ece55 100644 --- a/packages/react/src/hooks/options/use-playback-rate-options.ts +++ b/packages/react/src/hooks/options/use-playback-rate-options.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { useReactContext, useSignal } from 'maverick.js/react'; -import { mediaContext } from 'vidstack/local'; +import { mediaContext } from 'vidstack'; const DEFAULT_RATES = [0.25, 0.5, 0.75, { label: 'Normal', rate: 1 }, 1.25, 1.5, 1.75, 2]; diff --git a/packages/react/src/hooks/options/use-video-quality-options.ts b/packages/react/src/hooks/options/use-video-quality-options.ts index 060a60f22..519fd11ec 100644 --- a/packages/react/src/hooks/options/use-video-quality-options.ts +++ b/packages/react/src/hooks/options/use-video-quality-options.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import { useReactContext, useSignal } from 'maverick.js/react'; import { isString } from 'maverick.js/std'; -import { mediaContext, type VideoQuality } from 'vidstack/local'; +import { mediaContext, type VideoQuality } from 'vidstack'; /** * @docs {@link https://www.vidstack.io/docs/player/api/hooks/use-video-quality-options} diff --git a/packages/react/src/hooks/use-active-text-cues.ts b/packages/react/src/hooks/use-active-text-cues.ts index 41cfbac9c..c9fe2c0d7 100644 --- a/packages/react/src/hooks/use-active-text-cues.ts +++ b/packages/react/src/hooks/use-active-text-cues.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import { listenEvent } from 'maverick.js/std'; import type { VTTCue } from 'media-captions'; -import type { TextTrack } from 'vidstack/local'; +import type { TextTrack } from 'vidstack'; /** * @docs {@link https://www.vidstack.io/docs/player/api/hooks/use-active-text-cues} diff --git a/packages/react/src/hooks/use-active-text-track.ts b/packages/react/src/hooks/use-active-text-track.ts index 39a53684e..deedb9e70 100644 --- a/packages/react/src/hooks/use-active-text-track.ts +++ b/packages/react/src/hooks/use-active-text-track.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { useReactContext } from 'maverick.js/react'; -import { mediaContext, observeActiveTextTrack, type TextTrack } from 'vidstack/local'; +import { mediaContext, observeActiveTextTrack, type TextTrack } from 'vidstack'; /** * @docs {@link https://www.vidstack.io/docs/player/api/hooks/use-active-text-track} diff --git a/packages/react/src/hooks/use-media-player.ts b/packages/react/src/hooks/use-media-player.ts index cf98e86d1..18e52c311 100644 --- a/packages/react/src/hooks/use-media-player.ts +++ b/packages/react/src/hooks/use-media-player.ts @@ -1,5 +1,5 @@ import { useReactContext } from 'maverick.js/react'; -import { mediaContext } from 'vidstack/local'; +import { mediaContext } from 'vidstack'; import type { MediaPlayerInstance } from '../components/primitives/instances'; diff --git a/packages/react/src/hooks/use-media-provider.ts b/packages/react/src/hooks/use-media-provider.ts index e34f32b66..628b858b8 100644 --- a/packages/react/src/hooks/use-media-provider.ts +++ b/packages/react/src/hooks/use-media-provider.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import { effect } from 'maverick.js'; import { useReactContext } from 'maverick.js/react'; -import { mediaContext, type MediaProviderAdapter } from 'vidstack/local'; +import { mediaContext, type MediaProviderAdapter } from 'vidstack'; /** * Returns the current parent media provider. diff --git a/packages/react/src/hooks/use-media-remote.ts b/packages/react/src/hooks/use-media-remote.ts index 664f686c5..81eead54d 100644 --- a/packages/react/src/hooks/use-media-remote.ts +++ b/packages/react/src/hooks/use-media-remote.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { useReactContext } from 'maverick.js/react'; -import { mediaContext, MediaRemoteControl } from 'vidstack/local'; +import { mediaContext, MediaRemoteControl } from 'vidstack'; import { MediaPlayerInstance } from '../components/primitives/instances'; diff --git a/packages/react/src/hooks/use-media-state.ts b/packages/react/src/hooks/use-media-state.ts index e876f2a38..15352256a 100644 --- a/packages/react/src/hooks/use-media-state.ts +++ b/packages/react/src/hooks/use-media-state.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { useSignal, useSignalRecord, useStateContext } from 'maverick.js/react'; -import { mediaState, type MediaState } from 'vidstack/local'; +import { mediaState, type MediaState } from 'vidstack'; import { MediaPlayerInstance } from '../components/primitives/instances'; diff --git a/packages/react/src/hooks/use-player-query.ts b/packages/react/src/hooks/use-player-query.ts index 3e3aadb78..3eb155548 100644 --- a/packages/react/src/hooks/use-player-query.ts +++ b/packages/react/src/hooks/use-player-query.ts @@ -3,7 +3,7 @@ import * as React from 'react'; import { scoped } from 'maverick.js'; import { useReactScope } from 'maverick.js/react'; import { listenEvent } from 'maverick.js/std'; -import { PlayerQueryList } from 'vidstack/local'; +import { PlayerQueryList } from 'vidstack'; /** * Creates a new `PlayerQueryList` object that can then be used to determine if the diff --git a/packages/react/src/hooks/use-slider-preview.ts b/packages/react/src/hooks/use-slider-preview.ts index 5b0992997..0b4490da4 100644 --- a/packages/react/src/hooks/use-slider-preview.ts +++ b/packages/react/src/hooks/use-slider-preview.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import { effect, signal } from 'maverick.js'; import { listenEvent } from 'maverick.js/std'; -import { updateSliderPreviewPlacement, type SliderOrientation } from 'vidstack/local'; +import { updateSliderPreviewPlacement, type SliderOrientation } from 'vidstack'; /** * @docs {@link https://www.vidstack.io/docs/player/api/hooks/use-slider-preview} diff --git a/packages/react/src/hooks/use-slider-state.ts b/packages/react/src/hooks/use-slider-state.ts index 5c519f303..baab17931 100644 --- a/packages/react/src/hooks/use-slider-state.ts +++ b/packages/react/src/hooks/use-slider-state.ts @@ -1,7 +1,7 @@ -import type { RefObject } from 'react'; +import * as React from 'react'; import { useSignal, useSignalRecord, useStateContext } from 'maverick.js/react'; -import { sliderState, type SliderState } from 'vidstack/local'; +import { sliderState, type SliderState } from 'vidstack'; import type { SliderInstance, @@ -16,7 +16,7 @@ import type { */ export function useSliderState( prop: T, - ref?: RefObject, + ref?: React.RefObject, ): SliderState[T] { const $state = useStateContext(sliderState); @@ -37,7 +37,7 @@ export function useSliderState( * @docs {@link https://www.vidstack.io/docs/player/api/hooks/use-slider-state#store} */ export function useSliderStore( - ref?: RefObject, + ref?: React.RefObject, ): Readonly { const $state = useStateContext(sliderState); diff --git a/packages/react/src/hooks/use-thumbnails.ts b/packages/react/src/hooks/use-thumbnails.ts index 66a415d9f..54624c520 100644 --- a/packages/react/src/hooks/use-thumbnails.ts +++ b/packages/react/src/hooks/use-thumbnails.ts @@ -3,7 +3,7 @@ import * as React from 'react'; import { scoped, signal } from 'maverick.js'; import { useReactScope, useSignal } from 'maverick.js/react'; import type { VTTCue } from 'media-captions'; -import { findActiveCue, ThumbnailsLoader } from 'vidstack/local'; +import { findActiveCue, ThumbnailsLoader } from 'vidstack'; export interface ThumbnailData { url: string; diff --git a/packages/react/src/icon.ts b/packages/react/src/icon.ts index 519d1469b..03ac0d887 100644 --- a/packages/react/src/icon.ts +++ b/packages/react/src/icon.ts @@ -1,15 +1,8 @@ -import { - createElement, - forwardRef, - type ForwardRefExoticComponent, - type PropsWithoutRef, - type RefAttributes, - type SVGProps, -} from 'react'; +import * as React from 'react'; export interface IconProps - extends PropsWithoutRef>, - RefAttributes { + extends React.PropsWithoutRef>, + React.RefAttributes { /** * The horizontal (width) and vertical (height) length of the underlying `` element. * @@ -22,11 +15,11 @@ export interface IconProps paths?: string; } -export interface IconComponent extends ForwardRefExoticComponent {} +export interface IconComponent extends React.ForwardRefExoticComponent {} -const Icon: IconComponent = /* #__PURE__*/ forwardRef((props, ref) => { +const Icon: IconComponent = /* #__PURE__*/ React.forwardRef((props, ref) => { const { width, height, size = null, paths, ...restProps } = props; - return createElement('svg', { + return React.createElement('svg', { ...restProps, width: width ?? size, height: height ?? size, diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 3f1cd8020..47b260215 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -1,4 +1,4 @@ -export * from 'vidstack/local'; +export * from 'vidstack'; export * from './components/primitives/instances'; // Core diff --git a/packages/react/tsconfig.build.json b/packages/react/tsconfig.build.json index 85721c13b..e3b2c435d 100644 --- a/packages/react/tsconfig.build.json +++ b/packages/react/tsconfig.build.json @@ -3,7 +3,10 @@ "compilerOptions": { "declaration": true, "declarationDir": "types", - "paths": {} + "paths": { + "vidstack": ["../vidstack/src"] + } }, - "exclude": ["src/**/*.test.ts"] + "include": ["src/**/*.ts", "src/**/*.tsx", "../vidstack/src/**/*.ts"], + "exclude": ["src/**/*.test.ts", "../vidstack/src/**/*.test.ts"] } diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json index d9bf5844d..fa092f4e3 100644 --- a/packages/react/tsconfig.json +++ b/packages/react/tsconfig.json @@ -3,9 +3,10 @@ "compilerOptions": { "jsx": "preserve", "paths": { + "vidstack": ["../vidstack/src"], "@vidstack/react": ["./src/index.ts"] }, - "types": ["@types/node"] + "types": ["@types/node", "../vidstack/dom.d.ts"] }, "include": ["src/**/*.ts", "src/**/*.tsx"] } diff --git a/packages/react/vite.config.ts b/packages/react/vite.config.ts index 85dca50a1..8a3bcdc22 100644 --- a/packages/react/vite.config.ts +++ b/packages/react/vite.config.ts @@ -3,7 +3,7 @@ import path from 'node:path'; import react from '@vitejs/plugin-react'; import { defineConfig } from 'vite'; -const localPath = path.resolve('../vidstack/src/index.ts'); +const vidstackSource = path.resolve('../vidstack/src/index.ts'); // https://vitejs.dev/config/ export default defineConfig({ @@ -14,14 +14,13 @@ export default defineConfig({ plugins: [react()], resolve: { alias: { - 'vidstack/local': localPath, + vidstack: vidstackSource, }, }, optimizeDeps: { exclude: [ 'vidstack', - 'vidstack/local', - localPath, + vidstackSource, 'maverick.js', 'maverick.js/react', 'media-icons', diff --git a/packages/vidstack/package.json b/packages/vidstack/package.json index f7b706380..09eb3d958 100644 --- a/packages/vidstack/package.json +++ b/packages/vidstack/package.json @@ -26,10 +26,9 @@ "analyze": "maverick analyze \"src/**/*.ts\"", "dev": "pnpm clean && pnpm build:types && pnpm watch", "build": "rollup -c", - "build:local": "pnpm clean && rollup -c --config-local", "build:types": "tsc -p tsconfig.build.json", "types": "pnpm build:types && rollup -c --config-types", - "clean": "rimraf dist cdn local", + "clean": "rimraf dist cdn", "format": "prettier src --write --loglevel warn", "sandbox": "node ../../.scripts/sandbox.js", "sandbox:build": "vite build sandbox", @@ -100,12 +99,6 @@ "development": "./dist/dev/vidstack.js", "default": "./dist/prod/vidstack.js" }, - "./local": { - "types": "./local.d.ts", - "node": "./local/server/vidstack.js", - "development": "./local/dev/vidstack.js", - "default": "./local/prod/vidstack.js" - }, "./elements": { "types": "./elements.d.ts", "node": "./dist/server/vidstack-elements.js", diff --git a/packages/vidstack/rollup.config.js b/packages/vidstack/rollup.config.js index 64cc57c72..b4409373c 100644 --- a/packages/vidstack/rollup.config.js +++ b/packages/vidstack/rollup.config.js @@ -9,14 +9,15 @@ import dts from 'rollup-plugin-dts'; import esbuildPlugin from 'rollup-plugin-esbuild'; const MODE_WATCH = process.argv.includes('-w'), - MODE_TYPES = process.argv.includes('--config-types'), - MODE_LOCAL = process.argv.includes('--config-local'); + MODE_TYPES = process.argv.includes('--config-types'); -const MAIN_EXTERNAL = ['hls.js', 'media-captions', 'media-icons'], - LOCAL_EXTERNAL = [...MAIN_EXTERNAL, /maverick/]; +const EXTERNAL_PACKAGES = ['hls.js', 'media-captions', 'media-icons'], + NPM_BUNDLES = [define({ type: 'server' }), define({ type: 'dev' }), define({ type: 'prod' })], + CDN_BUNDLES = [defineCDN({ dev: true }), defineCDN(), defineCDN({ layouts: true })], + TYPES_BUNDLES = [defineTypes()]; // Styles -if (!MODE_TYPES || MODE_WATCH) { +if (!MODE_TYPES) { if (MODE_WATCH) { chokidar.watch('player/styles/**').on('all', (_, path) => { if (path !== 'player/styles/default/theme.css') buildDefaultTheme(); @@ -26,47 +27,25 @@ if (!MODE_TYPES || MODE_WATCH) { } } -// Used by other packages (e.g., `@vidstack/react`) to build without duplicate deps. -const LOCAL = [define({ type: 'local-prod' }), define({ type: 'local-dev' })]; -const TYPES = [defineTypes({ local: true }), defineTypes({ local: false })]; -const NPM = [define({ type: 'server' }), define({ type: 'dev' }), define({ type: 'prod' })]; -const CDN = [defineCDN({ dev: true }), defineCDN(), defineCDN({ layouts: true })]; - -/** @type {import('rollup').WarningHandlerWithDefault} */ -function onWarn(warning, defaultHandler) { - defaultHandler(warning); -} - export default defineConfig( MODE_WATCH - ? MODE_LOCAL - ? [...LOCAL, ...TYPES] - : [...NPM, ...TYPES] + ? [...NPM_BUNDLES, ...TYPES_BUNDLES] : MODE_TYPES - ? TYPES - : MODE_LOCAL - ? LOCAL - : [...LOCAL, ...NPM, ...CDN], + ? TYPES_BUNDLES + : [...NPM_BUNDLES, ...CDN_BUNDLES], ); /** - * @param {{ local: boolean }} config * @returns {import('rollup').RollupOptions} * */ -function defineTypes({ local }) { +function defineTypes() { /** @type {Record} */ let input = { - [local ? 'local' : 'index']: 'src/index.ts', + ['index']: 'src/index.ts', + elements: 'src/elements/index.ts', + icons: 'src/elements/bundles/icons.ts', }; - if (!local) { - input = { - ...input, - elements: 'src/elements/index.ts', - icons: 'src/elements/bundles/icons.ts', - }; - } - for (const key of Object.keys(input)) { input[key] = input[key].replace(/^src/, 'types').replace(/\.ts$/, '.d.ts'); } @@ -77,31 +56,20 @@ function defineTypes({ local }) { dir: '.', chunkFileNames: 'dist/types/vidstack-[hash].d.ts', manualChunks(id) { - if (local) return null; if (id.includes('maverick') || id.includes('lit-html') || id.includes('@floating-ui')) { return 'framework.d'; } }, }, - external: local ? LOCAL_EXTERNAL : MAIN_EXTERNAL, - plugins: [ - dts({ respectExternal: true }), - { - name: 'cleanup', - closeBundle() { - if (!local && !MODE_WATCH) { - fs.rmSync('types', { recursive: true }); - } - }, - }, - ], + external: EXTERNAL_PACKAGES, + plugins: [dts({ respectExternal: true })], }; } /** * @typedef {{ * target?: string | null; - * type: 'dev' | 'prod' | 'server' | 'local-dev' | 'local-prod'; + * type: 'dev' | 'prod' | 'server'; * minify?: boolean; * }} BundleOptions */ @@ -114,9 +82,13 @@ function define({ target, type, minify }) { /** @type {Record} */ let input = { vidstack: 'src/index.ts', + 'vidstack-elements': 'src/elements/index.ts', + 'define/vidstack-icons': 'src/elements/bundles/icons.ts', + 'define/vidstack-player': 'src/elements/bundles/player.ts', + 'define/vidstack-player-ui': 'src/elements/bundles/player-ui.ts', + 'define/vidstack-player-layouts': 'src/elements/bundles/player-layouts.ts', }, - isProd = type === 'prod' || type === 'local-prod', - isLocal = type.startsWith('local'), + isProd = type === 'prod', isServer = type === 'server', shouldMangle = type === 'prod', /** @type {Record} */ @@ -130,24 +102,11 @@ function define({ target, type, minify }) { [`providers/vidstack-video`]: 'src/providers/video/provider.ts', [`providers/vidstack-hls`]: 'src/providers/hls/provider.ts', }; - } - - if (!isLocal) { - input = { - ...input, - 'vidstack-elements': 'src/elements/index.ts', - 'define/vidstack-icons': 'src/elements/bundles/icons.ts', - 'define/vidstack-player': 'src/elements/bundles/player.ts', - 'define/vidstack-player-ui': 'src/elements/bundles/player-ui.ts', - 'define/vidstack-player-layouts': 'src/elements/bundles/player-layouts.ts', - }; - if (type !== 'server') { - input['define/vidstack-audio-layout'] = - 'src/elements/define/layouts/default/audio-layout-element.ts'; - input['define/vidstack-video-layout'] = - 'src/elements/define/layouts/default/video-layout-element.ts'; - } + input['define/vidstack-audio-layout'] = + 'src/elements/define/layouts/default/audio-layout-element.ts'; + input['define/vidstack-video-layout'] = + 'src/elements/define/layouts/default/video-layout-element.ts'; } return { @@ -155,14 +114,12 @@ function define({ target, type, minify }) { maxParallelFileOps: shouldMangle ? 1 : 20, treeshake: true, preserveEntrySignatures: 'strict', - external: isLocal ? LOCAL_EXTERNAL : MAIN_EXTERNAL, - onwarn: onWarn, + external: EXTERNAL_PACKAGES, output: { format: 'esm', - dir: `${isLocal ? `local` : `dist`}/${type.replace('local-', '')}`, + dir: `dist/${type.replace('local-', '')}`, chunkFileNames: 'chunks/vidstack-[hash].js', manualChunks(id) { - if (isLocal) return null; if (id.includes('maverick') || id.includes('@floating-ui')) return 'framework'; if (id.includes('lit-html')) return 'framework-layouts'; return null; @@ -182,24 +139,12 @@ function define({ target, type, minify }) { platform: isServer ? 'node' : 'browser', minify: minify, legalComments: 'none', - banner: isLocal ? 'import { IS_SERVER } from "@virtual/env";' : '', define: { __DEV__: !isProd && !isServer ? 'true' : 'false', - __SERVER__: isLocal ? 'IS_SERVER' : isServer ? 'true' : 'false', + __SERVER__: isServer ? 'true' : 'false', __TEST__: 'false', }, }), - isLocal && { - name: 'env', - resolveId(id) { - if (id === '@virtual/env') return id; - }, - load(id) { - if (id === '@virtual/env') { - return `export const IS_SERVER = typeof document === 'undefined';`; - } - }, - }, isServer && { name: 'server-bundle', async transform(code, id) { diff --git a/packages/vidstack/src/core/state/media-state-manager.ts b/packages/vidstack/src/core/state/media-state-manager.ts index 28b4755e0..b5ecc7548 100644 --- a/packages/vidstack/src/core/state/media-state-manager.ts +++ b/packages/vidstack/src/core/state/media-state-manager.ts @@ -184,6 +184,15 @@ export class MediaStateManager extends MediaPlayerController { if (prevProvider && event.detail === null) this._resetMediaState(event); } + ['provider-loader-change'](event: ME.MediaProviderLoaderChangeEvent) { + if (__DEV__) { + this._media.logger + ?.infoGroup(`Loader change \`${event.detail?.constructor.name}\``) + .labelledLog('Event', event) + .dispatch(); + } + } + ['autoplay'](event: ME.MediaAutoplayEvent) { appendTriggerEvent(event, this._trackedEvents.get('play')); appendTriggerEvent(event, this._trackedEvents.get('can-play')); diff --git a/packages/vidstack/tsconfig.json b/packages/vidstack/tsconfig.json index ca3df7b59..dff7482a3 100644 --- a/packages/vidstack/tsconfig.json +++ b/packages/vidstack/tsconfig.json @@ -3,9 +3,7 @@ "compilerOptions": { "jsx": "preserve", "paths": { - "$test-utils": ["./src/test-utils/index.ts"], - "vidstack": ["./src/index.ts"], - "vidstack/elements": ["./src/elements/index.ts"] + "$test-utils": ["./src/test-utils/index.ts"] }, "types": ["@types/node", "vitest/globals"] }, diff --git a/tsconfig.json b/tsconfig.json index b0893f07e..5217545d9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,7 @@ "esModuleInterop": true, "experimentalDecorators": true, "forceConsistentCasingInFileNames": true, + "incremental": true, "importHelpers": true, "lib": ["dom", "dom.iterable", "es2020"], "module": "esnext", diff --git a/turbo.json b/turbo.json index fa06ad32d..a9502d389 100644 --- a/turbo.json +++ b/turbo.json @@ -2,18 +2,17 @@ "$schema": "https://turborepo.org/schema.json", "pipeline": { "analyze": { - "dependsOn": ["^types"], "outputs": ["analyze.json", "vscode.html-data.json", "vue.d.ts", "svelte.d.ts", "solid.d.ts"] }, "build": { - "dependsOn": ["^analyze", "^build", "clean"], - "outputs": ["cdn/**", "dist/**", "local/**", "player/**", "tailwind.cjs", "tailwind.d.cts"] + "dependsOn": ["clean"], + "outputs": ["cdn/**", "dist/**", "player/**", "tailwind.*"] }, "clean": { "cache": false }, "types": { - "dependsOn": ["^types", "clean"], + "dependsOn": ["clean"], "outputs": ["dist/types/**", "*.d.ts"] }, "format": {