From edefc2a2d63e2124d0a11a15f44bd7109c6d9788 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Sun, 15 Feb 2026 17:42:45 +1100 Subject: [PATCH] feat(react): initial skin scaffolding (#523) Co-authored-by: Rahim --- packages/react/package.json | 18 ++++++++++++++- packages/react/src/index.ts | 2 -- packages/react/src/presets/audio/index.ts | 3 +++ .../react/src/presets/audio/minimal-skin.css | 3 +++ .../react/src/presets/audio/minimal-skin.tsx | 8 +++++++ packages/react/src/presets/audio/skin.css | 3 +++ packages/react/src/presets/audio/skin.tsx | 8 +++++++ .../react/src/presets/background/index.ts | 1 + .../react/src/presets/background/skin.css | 3 +++ .../react/src/presets/background/skin.tsx | 8 +++++++ packages/react/src/presets/types.ts | 3 +++ packages/react/src/presets/video/index.ts | 3 +++ .../react/src/presets/video/minimal-skin.css | 3 +++ .../react/src/presets/video/minimal-skin.tsx | 8 +++++++ packages/react/src/presets/video/skin.css | 3 +++ packages/react/src/presets/video/skin.tsx | 8 +++++++ packages/react/tsdown.config.ts | 23 ++++++++++++++++--- packages/sandbox/templates/react/main.tsx | 3 ++- pnpm-lock.yaml | 2 +- .../demos/controls/react/css/BasicUsage.tsx | 3 ++- .../react/css/BasicUsage.tsx | 3 ++- .../mute-button/react/css/BasicUsage.tsx | 3 ++- .../play-button/react/css/BasicUsage.tsx | 3 ++- .../demos/poster/react/css/BasicUsage.tsx | 3 ++- .../demos/time/react/css/CurrentDuration.tsx | 3 ++- .../docs/demos/time/react/css/CurrentTime.tsx | 3 ++- .../time/react/css/CustomNegativeSign.tsx | 3 ++- .../demos/time/react/css/CustomSeparator.tsx | 3 ++- .../docs/demos/time/react/css/Remaining.tsx | 3 ++- 29 files changed, 125 insertions(+), 18 deletions(-) create mode 100644 packages/react/src/presets/audio/index.ts create mode 100644 packages/react/src/presets/audio/minimal-skin.css create mode 100644 packages/react/src/presets/audio/minimal-skin.tsx create mode 100644 packages/react/src/presets/audio/skin.css create mode 100644 packages/react/src/presets/audio/skin.tsx create mode 100644 packages/react/src/presets/background/index.ts create mode 100644 packages/react/src/presets/background/skin.css create mode 100644 packages/react/src/presets/background/skin.tsx create mode 100644 packages/react/src/presets/types.ts create mode 100644 packages/react/src/presets/video/index.ts create mode 100644 packages/react/src/presets/video/minimal-skin.css create mode 100644 packages/react/src/presets/video/minimal-skin.tsx create mode 100644 packages/react/src/presets/video/skin.css create mode 100644 packages/react/src/presets/video/skin.tsx diff --git a/packages/react/package.json b/packages/react/package.json index 97265e36..b28efe09 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -16,12 +16,28 @@ "types": "./dist/dev/index.d.ts", "development": "./dist/dev/index.js", "default": "./dist/default/index.js" + }, + "./*.css": "./dist/default/presets/*.css", + "./audio": { + "types": "./dist/dev/presets/audio/index.d.ts", + "development": "./dist/dev/presets/audio/index.js", + "default": "./dist/default/presets/audio/index.js" + }, + "./background": { + "types": "./dist/dev/presets/background/index.d.ts", + "development": "./dist/dev/presets/background/index.js", + "default": "./dist/default/presets/background/index.js" + }, + "./video": { + "types": "./dist/dev/presets/video/index.d.ts", + "development": "./dist/dev/presets/video/index.js", + "default": "./dist/default/presets/video/index.js" } }, "scripts": { "build": "tsdown", "build:watch": "tsdown --watch ./src --no-clean", - "dev": "pnpm run build:watch", + "dev": "pnpm build:watch", "test": "vitest run", "test:watch": "vitest", "clean": "rm -rf dist types" diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index f101fa07..db02da9f 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -9,8 +9,6 @@ export { createSelector, shallowEqual } from '@videojs/store'; export { useSelector, useStore } from '@videojs/store/react'; // Media primitives -export { Audio, type AudioProps } from './media/audio'; -export { Video, type VideoProps } from './media/video'; export { Container, type ContainerProps, diff --git a/packages/react/src/presets/audio/index.ts b/packages/react/src/presets/audio/index.ts new file mode 100644 index 00000000..d8ec0bfc --- /dev/null +++ b/packages/react/src/presets/audio/index.ts @@ -0,0 +1,3 @@ +export { Audio, type AudioProps } from '@/media/audio'; +export * from './minimal-skin'; +export * from './skin'; diff --git a/packages/react/src/presets/audio/minimal-skin.css b/packages/react/src/presets/audio/minimal-skin.css new file mode 100644 index 00000000..abd1fe89 --- /dev/null +++ b/packages/react/src/presets/audio/minimal-skin.css @@ -0,0 +1,3 @@ +.media-minimal-skin { + color: var(--media-color, red); +} diff --git a/packages/react/src/presets/audio/minimal-skin.tsx b/packages/react/src/presets/audio/minimal-skin.tsx new file mode 100644 index 00000000..dba6f9eb --- /dev/null +++ b/packages/react/src/presets/audio/minimal-skin.tsx @@ -0,0 +1,8 @@ +import type { BaseSkinProps } from '../types'; + +export type MinimalAudioSkinProps = BaseSkinProps; + +export function MinimalAudioSkin(props: MinimalAudioSkinProps) { + const { children } = props; + return
{children}
; +} diff --git a/packages/react/src/presets/audio/skin.css b/packages/react/src/presets/audio/skin.css new file mode 100644 index 00000000..9c9762b2 --- /dev/null +++ b/packages/react/src/presets/audio/skin.css @@ -0,0 +1,3 @@ +.media-skin { + color: var(--media-color, red); +} diff --git a/packages/react/src/presets/audio/skin.tsx b/packages/react/src/presets/audio/skin.tsx new file mode 100644 index 00000000..57228b38 --- /dev/null +++ b/packages/react/src/presets/audio/skin.tsx @@ -0,0 +1,8 @@ +import type { BaseSkinProps } from '../types'; + +export type AudioSkinProps = BaseSkinProps; + +export function AudioSkin(props: AudioSkinProps) { + const { children } = props; + return
{children}
; +} diff --git a/packages/react/src/presets/background/index.ts b/packages/react/src/presets/background/index.ts new file mode 100644 index 00000000..966e7046 --- /dev/null +++ b/packages/react/src/presets/background/index.ts @@ -0,0 +1 @@ +export * from './skin'; diff --git a/packages/react/src/presets/background/skin.css b/packages/react/src/presets/background/skin.css new file mode 100644 index 00000000..9c9762b2 --- /dev/null +++ b/packages/react/src/presets/background/skin.css @@ -0,0 +1,3 @@ +.media-skin { + color: var(--media-color, red); +} diff --git a/packages/react/src/presets/background/skin.tsx b/packages/react/src/presets/background/skin.tsx new file mode 100644 index 00000000..2cdf43ba --- /dev/null +++ b/packages/react/src/presets/background/skin.tsx @@ -0,0 +1,8 @@ +import type { BaseSkinProps } from '../types'; + +export type BackgroundVideoSkinProps = BaseSkinProps; + +export function BackgroundVideoSkin(props: BackgroundVideoSkinProps) { + const { children } = props; + return
{children}
; +} diff --git a/packages/react/src/presets/types.ts b/packages/react/src/presets/types.ts new file mode 100644 index 00000000..5ace3e65 --- /dev/null +++ b/packages/react/src/presets/types.ts @@ -0,0 +1,3 @@ +import type { PropsWithChildren } from 'react'; + +export type BaseSkinProps = PropsWithChildren; diff --git a/packages/react/src/presets/video/index.ts b/packages/react/src/presets/video/index.ts new file mode 100644 index 00000000..93f7dd44 --- /dev/null +++ b/packages/react/src/presets/video/index.ts @@ -0,0 +1,3 @@ +export { Video, type VideoProps } from '@/media/video'; +export * from './minimal-skin'; +export * from './skin'; diff --git a/packages/react/src/presets/video/minimal-skin.css b/packages/react/src/presets/video/minimal-skin.css new file mode 100644 index 00000000..abd1fe89 --- /dev/null +++ b/packages/react/src/presets/video/minimal-skin.css @@ -0,0 +1,3 @@ +.media-minimal-skin { + color: var(--media-color, red); +} diff --git a/packages/react/src/presets/video/minimal-skin.tsx b/packages/react/src/presets/video/minimal-skin.tsx new file mode 100644 index 00000000..f1d19cc5 --- /dev/null +++ b/packages/react/src/presets/video/minimal-skin.tsx @@ -0,0 +1,8 @@ +import type { BaseSkinProps } from '../types'; + +export type MinimalVideoSkinProps = BaseSkinProps; + +export function MinimalVideoSkin(props: MinimalVideoSkinProps) { + const { children } = props; + return
{children}
; +} diff --git a/packages/react/src/presets/video/skin.css b/packages/react/src/presets/video/skin.css new file mode 100644 index 00000000..9c9762b2 --- /dev/null +++ b/packages/react/src/presets/video/skin.css @@ -0,0 +1,3 @@ +.media-skin { + color: var(--media-color, red); +} diff --git a/packages/react/src/presets/video/skin.tsx b/packages/react/src/presets/video/skin.tsx new file mode 100644 index 00000000..f183d9d1 --- /dev/null +++ b/packages/react/src/presets/video/skin.tsx @@ -0,0 +1,8 @@ +import type { BaseSkinProps } from '../types'; + +export type VideoSkinProps = BaseSkinProps; + +export function VideoSkin(props: VideoSkinProps) { + const { children } = props; + return
{children}
; +} diff --git a/packages/react/tsdown.config.ts b/packages/react/tsdown.config.ts index 6df8c8f1..faedff72 100644 --- a/packages/react/tsdown.config.ts +++ b/packages/react/tsdown.config.ts @@ -1,3 +1,4 @@ +import { globSync } from 'node:fs'; import type { UserConfig } from 'tsdown'; import { defineConfig } from 'tsdown'; @@ -6,9 +7,7 @@ type BuildMode = 'dev' | 'default'; const buildModes: BuildMode[] = ['dev', 'default']; const createConfig = (mode: BuildMode): UserConfig => ({ - entry: { - index: './src/index.ts', - }, + entry: 'src/**/index.ts', platform: 'browser', format: 'es', sourcemap: true, @@ -23,6 +22,24 @@ const createConfig = (mode: BuildMode): UserConfig => ({ __DEV__: mode === 'dev' ? 'true' : 'false', }, dts: mode === 'dev', + copy: [ + { + from: 'src/**/*.css', + to: `dist/${mode}`, + flatten: false, + }, + ], + plugins: [ + { + name: 'watch-css', + buildStart() { + const cssFiles = globSync('src/**/*.css'); + for (const file of cssFiles) { + this.addWatchFile(file); + } + }, + }, + ], }); export default defineConfig(buildModes.map((mode) => createConfig(mode))); diff --git a/packages/sandbox/templates/react/main.tsx b/packages/sandbox/templates/react/main.tsx index 7e67d936..39ab2b32 100644 --- a/packages/sandbox/templates/react/main.tsx +++ b/packages/sandbox/templates/react/main.tsx @@ -1,7 +1,8 @@ // React sandbox — React player // http://localhost:5173/react/ -import { Container, createPlayer, features, Video } from '@videojs/react'; +import { Container, createPlayer, features } from '@videojs/react'; +import { Video } from '@videojs/react/video'; import { createRoot } from 'react-dom/client'; const { Provider } = createPlayer({ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cd627781..8bef7d7b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9899,7 +9899,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.15 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) '@vitest/utils@3.2.4': dependencies: diff --git a/site/src/components/docs/demos/controls/react/css/BasicUsage.tsx b/site/src/components/docs/demos/controls/react/css/BasicUsage.tsx index 98be27fb..c98d2cfa 100644 --- a/site/src/components/docs/demos/controls/react/css/BasicUsage.tsx +++ b/site/src/components/docs/demos/controls/react/css/BasicUsage.tsx @@ -1,4 +1,5 @@ -import { Controls, createPlayer, features, PlayButton, Time, Video } from '@videojs/react'; +import { Controls, createPlayer, features, PlayButton, Time } from '@videojs/react'; +import { Video } from '@videojs/react/video'; import './BasicUsage.css'; diff --git a/site/src/components/docs/demos/fullscreen-button/react/css/BasicUsage.tsx b/site/src/components/docs/demos/fullscreen-button/react/css/BasicUsage.tsx index ac813524..5da6e275 100644 --- a/site/src/components/docs/demos/fullscreen-button/react/css/BasicUsage.tsx +++ b/site/src/components/docs/demos/fullscreen-button/react/css/BasicUsage.tsx @@ -1,4 +1,5 @@ -import { createPlayer, FullscreenButton, features, Video } from '@videojs/react'; +import { createPlayer, FullscreenButton, features } from '@videojs/react'; +import { Video } from '@videojs/react/video'; import './BasicUsage.css'; diff --git a/site/src/components/docs/demos/mute-button/react/css/BasicUsage.tsx b/site/src/components/docs/demos/mute-button/react/css/BasicUsage.tsx index 59ca479c..5d34a53d 100644 --- a/site/src/components/docs/demos/mute-button/react/css/BasicUsage.tsx +++ b/site/src/components/docs/demos/mute-button/react/css/BasicUsage.tsx @@ -1,4 +1,5 @@ -import { createPlayer, features, MuteButton, Video } from '@videojs/react'; +import { createPlayer, features, MuteButton } from '@videojs/react'; +import { Video } from '@videojs/react/video'; import './BasicUsage.css'; diff --git a/site/src/components/docs/demos/play-button/react/css/BasicUsage.tsx b/site/src/components/docs/demos/play-button/react/css/BasicUsage.tsx index d2575072..9a815419 100644 --- a/site/src/components/docs/demos/play-button/react/css/BasicUsage.tsx +++ b/site/src/components/docs/demos/play-button/react/css/BasicUsage.tsx @@ -1,4 +1,5 @@ -import { createPlayer, features, PlayButton, Video } from '@videojs/react'; +import { createPlayer, features, PlayButton } from '@videojs/react'; +import { Video } from '@videojs/react/video'; import './BasicUsage.css'; diff --git a/site/src/components/docs/demos/poster/react/css/BasicUsage.tsx b/site/src/components/docs/demos/poster/react/css/BasicUsage.tsx index c29c77b7..532e2835 100644 --- a/site/src/components/docs/demos/poster/react/css/BasicUsage.tsx +++ b/site/src/components/docs/demos/poster/react/css/BasicUsage.tsx @@ -1,4 +1,5 @@ -import { createPlayer, features, PlayButton, Poster, Video } from '@videojs/react'; +import { createPlayer, features, PlayButton, Poster } from '@videojs/react'; +import { Video } from '@videojs/react/video'; import './BasicUsage.css'; diff --git a/site/src/components/docs/demos/time/react/css/CurrentDuration.tsx b/site/src/components/docs/demos/time/react/css/CurrentDuration.tsx index c2af6f5c..b815fd53 100644 --- a/site/src/components/docs/demos/time/react/css/CurrentDuration.tsx +++ b/site/src/components/docs/demos/time/react/css/CurrentDuration.tsx @@ -1,4 +1,5 @@ -import { createPlayer, features, Time, Video } from '@videojs/react'; +import { createPlayer, features, Time } from '@videojs/react'; +import { Video } from '@videojs/react/video'; import './CurrentDuration.css'; diff --git a/site/src/components/docs/demos/time/react/css/CurrentTime.tsx b/site/src/components/docs/demos/time/react/css/CurrentTime.tsx index de72aee0..1f8d1c6a 100644 --- a/site/src/components/docs/demos/time/react/css/CurrentTime.tsx +++ b/site/src/components/docs/demos/time/react/css/CurrentTime.tsx @@ -1,4 +1,5 @@ -import { createPlayer, features, Time, Video } from '@videojs/react'; +import { createPlayer, features, Time } from '@videojs/react'; +import { Video } from '@videojs/react/video'; import './CurrentTime.css'; diff --git a/site/src/components/docs/demos/time/react/css/CustomNegativeSign.tsx b/site/src/components/docs/demos/time/react/css/CustomNegativeSign.tsx index 7b00f6a9..fd7b423d 100644 --- a/site/src/components/docs/demos/time/react/css/CustomNegativeSign.tsx +++ b/site/src/components/docs/demos/time/react/css/CustomNegativeSign.tsx @@ -1,4 +1,5 @@ -import { createPlayer, features, Time, Video } from '@videojs/react'; +import { createPlayer, features, Time } from '@videojs/react'; +import { Video } from '@videojs/react/video'; import './CustomNegativeSign.css'; diff --git a/site/src/components/docs/demos/time/react/css/CustomSeparator.tsx b/site/src/components/docs/demos/time/react/css/CustomSeparator.tsx index f9868bf2..66f462a0 100644 --- a/site/src/components/docs/demos/time/react/css/CustomSeparator.tsx +++ b/site/src/components/docs/demos/time/react/css/CustomSeparator.tsx @@ -1,4 +1,5 @@ -import { createPlayer, features, Time, Video } from '@videojs/react'; +import { createPlayer, features, Time } from '@videojs/react'; +import { Video } from '@videojs/react/video'; import './CustomSeparator.css'; diff --git a/site/src/components/docs/demos/time/react/css/Remaining.tsx b/site/src/components/docs/demos/time/react/css/Remaining.tsx index f2714ba1..b9421167 100644 --- a/site/src/components/docs/demos/time/react/css/Remaining.tsx +++ b/site/src/components/docs/demos/time/react/css/Remaining.tsx @@ -1,4 +1,5 @@ -import { createPlayer, features, Time, Video } from '@videojs/react'; +import { createPlayer, features, Time } from '@videojs/react'; +import { Video } from '@videojs/react/video'; import './Remaining.css';