From 6ad5340b4057bf17adcda8e61163434ddfcdb6db Mon Sep 17 00:00:00 2001 From: Rahim Date: Tue, 23 Sep 2025 23:12:19 +1000 Subject: [PATCH] chore: new builds & types using tsdown (#20) --- package.json | 5 +- packages/core/icons/package.json | 20 +- packages/core/icons/rollup.config.js | 75 - packages/core/icons/src/index.ts | 3 +- packages/core/icons/tsconfig.build.json | 11 +- packages/core/icons/tsconfig.json | 9 +- packages/core/icons/tsdown.config.ts | 15 + packages/core/media-store/package.json | 19 +- packages/core/media-store/rollup.config.js | 68 - .../current-time-display.ts | 2 +- .../duration-display.ts | 2 +- .../play-button.ts | 2 +- packages/core/media-store/src/factory.ts | 22 +- packages/core/media-store/src/index.ts | 2 +- packages/core/media-store/src/media-store.ts | 12 +- .../src/state-mediators/audible.ts | 24 +- .../src/state-mediators/fullscreenable.ts | 10 +- .../media-store/src/state-mediators/index.ts | 2 +- .../src/state-mediators/playable.ts | 8 +- .../{state-mediators => utils}/temporal.ts | 20 +- packages/core/media-store/tsconfig.build.json | 11 +- packages/core/media-store/tsconfig.json | 9 +- packages/core/media-store/tsdown.config.ts | 12 + packages/core/media/package.json | 14 +- packages/core/media/src/playable.ts | 41 +- packages/core/media/tsconfig.build.json | 4 + packages/core/media/tsconfig.json | 9 +- packages/core/media/tsdown.config.ts | 12 + packages/core/media/tsup.config.ts | 21 - packages/core/playback-engine/package.json | 14 +- .../src/HlsJSPlaybackEngine.ts | 24 +- .../core/playback-engine/tsconfig.build.json | 4 + packages/core/playback-engine/tsconfig.json | 9 +- .../core/playback-engine/tsdown.config.ts | 12 + packages/core/playback-engine/tsup.config.ts | 21 - packages/html/html-icons/package.json | 19 +- packages/html/html-icons/rollup.config.js | 68 - .../html/html-icons/src/media-chrome-icon.ts | 2 +- .../src/media-fullscreen-enter-icon.ts | 2 +- .../src/media-fullscreen-exit-icon.ts | 2 +- .../html/html-icons/src/media-pause-icon.ts | 2 +- .../html/html-icons/src/media-play-icon.ts | 2 +- .../html-icons/src/media-volume-high-icon.ts | 2 +- .../html-icons/src/media-volume-low-icon.ts | 2 +- .../html-icons/src/media-volume-off-icon.ts | 2 +- packages/html/html-icons/tsconfig.build.json | 11 +- packages/html/html-icons/tsconfig.json | 9 +- packages/html/html-icons/tsdown.config.ts | 15 + .../html/html-media-elements/package.json | 14 +- .../html-media-elements/src/media-provider.ts | 10 +- .../html-media-elements/tsconfig.build.json | 4 + .../html/html-media-elements/tsconfig.json | 9 +- .../html/html-media-elements/tsdown.config.ts | 12 + .../html/html-media-elements/tsup.config.ts | 21 - packages/html/html-media-store/package.json | 14 +- .../html/html-media-store/tsconfig.build.json | 4 + packages/html/html-media-store/tsconfig.json | 9 +- .../html/html-media-store/tsdown.config.ts | 12 + packages/html/html-media-store/tsup.config.ts | 21 - packages/html/html/package.json | 20 +- packages/html/html/rollup.config.js | 68 - .../src/components/media-chrome-button.ts | 7 +- .../components/media-current-time-display.ts | 36 +- .../src/components/media-duration-display.ts | 28 +- .../src/components/media-fullscreen-button.ts | 23 +- .../html/src/components/media-mute-button.ts | 36 +- .../html/src/components/media-play-button.ts | 27 +- .../html/src/components/media-time-range.ts | 90 +- .../html/src/components/media-volume-range.ts | 41 +- packages/html/html/src/index.ts | 2 +- packages/html/html/src/media-container.ts | 22 +- packages/html/html/src/media-provider.ts | 10 +- packages/html/html/src/media-skin.ts | 2 +- .../html/html/src/skins/media-skin-default.ts | 2 +- .../html/html/src/utils/component-factory.ts | 12 +- packages/html/html/src/utils/element-utils.ts | 4 +- packages/html/html/tsconfig.build.json | 11 +- packages/html/html/tsconfig.json | 9 +- packages/html/html/tsdown.config.ts | 12 + .../react-native-icons/package.json | 14 +- .../react-native-icons/src/index.ts | 35 + .../react-native-icons/src/index.tsx | 37 - .../react-native-icons/tsconfig.build.json | 4 + .../react-native-icons/tsconfig.json | 13 +- .../react-native-icons/tsdown.config.ts | 12 + .../react-native-icons/tsup.config.ts | 21 - .../react-native-media-elements/package.json | 14 +- .../src/{index.tsx => index.ts} | 13 +- .../tsconfig.build.json | 4 + .../react-native-media-elements/tsconfig.json | 13 +- .../tsdown.config.ts | 12 + .../tsup.config.ts | 21 - .../react-native/react-native/package.json | 14 +- .../react-native/src/{index.tsx => index.ts} | 11 +- .../react-native/tsconfig.build.json | 4 + .../react-native/react-native/tsconfig.json | 13 +- .../react-native/tsdown.config.ts | 12 + .../react-native/react-native/tsup.config.ts | 21 - packages/react/react-icons/package.json | 25 +- packages/react/react-icons/rollup.config.js | 68 - packages/react/react-icons/svgr.config.js | 11 +- .../react/react-icons/tsconfig.build.json | 11 +- packages/react/react-icons/tsconfig.json | 12 +- packages/react/react-icons/tsdown.config.ts | 15 + .../react/react-media-elements/package.json | 14 +- .../react/react-media-elements/src/index.ts | 2 - .../src/media-elements.tsx | 16 +- .../react-media-elements/tsconfig.build.json | 4 + .../react/react-media-elements/tsconfig.json | 12 +- .../react-media-elements/tsdown.config.ts | 12 + .../react/react-media-elements/tsup.config.ts | 21 - packages/react/react-media-store/package.json | 14 +- .../react-media-store/src/MediaProvider.tsx | 26 +- packages/react/react-media-store/src/index.ts | 14 +- .../react/react-media-store/src/index.tsx | 15 - .../src/useSyncExternalStoreWithSelector.ts | 2 +- .../react-media-store/tsconfig.build.json | 4 + .../react/react-media-store/tsconfig.json | 12 +- .../react/react-media-store/tsdown.config.ts | 12 + .../react/react-media-store/tsup.config.ts | 21 - packages/react/react/package.json | 21 +- packages/react/react/rollup.config.js | 81 - .../src/components/CurrentTimeDisplay.tsx | 39 +- .../react/src/components/DurationDisplay.tsx | 32 +- .../react/src/components/FullscreenButton.tsx | 30 +- .../react/src/components/MediaContainer.tsx | 13 +- .../react/react/src/components/MuteButton.tsx | 34 +- .../react/react/src/components/PlayButton.tsx | 35 +- .../react/react/src/components/TimeRange.tsx | 97 +- packages/react/react/src/components/Video.tsx | 22 +- .../react/src/components/VolumeRange.tsx | 34 +- .../react/react/src/{index.tsx => index.ts} | 3 - .../react/src/skins/MediaSkinDefault.tsx | 2 - packages/react/react/src/skins/styles.ts | 4 +- .../react/src/utils/component-factory.tsx | 27 +- packages/react/react/tsconfig.build.json | 11 +- packages/react/react/tsconfig.json | 12 +- packages/react/react/tsdown.config.ts | 12 + pnpm-lock.yaml | 2395 +++-------------- tsconfig.base.json | 5 +- tsconfig.json | 49 +- turbo.json | 8 +- 142 files changed, 1407 insertions(+), 3468 deletions(-) delete mode 100644 packages/core/icons/rollup.config.js create mode 100644 packages/core/icons/tsdown.config.ts delete mode 100644 packages/core/media-store/rollup.config.js rename packages/core/media-store/src/{state-mediators => utils}/temporal.ts (86%) create mode 100644 packages/core/media-store/tsdown.config.ts create mode 100644 packages/core/media/tsconfig.build.json create mode 100644 packages/core/media/tsdown.config.ts delete mode 100644 packages/core/media/tsup.config.ts create mode 100644 packages/core/playback-engine/tsconfig.build.json create mode 100644 packages/core/playback-engine/tsdown.config.ts delete mode 100644 packages/core/playback-engine/tsup.config.ts delete mode 100644 packages/html/html-icons/rollup.config.js create mode 100644 packages/html/html-icons/tsdown.config.ts create mode 100644 packages/html/html-media-elements/tsconfig.build.json create mode 100644 packages/html/html-media-elements/tsdown.config.ts delete mode 100644 packages/html/html-media-elements/tsup.config.ts create mode 100644 packages/html/html-media-store/tsconfig.build.json create mode 100644 packages/html/html-media-store/tsdown.config.ts delete mode 100644 packages/html/html-media-store/tsup.config.ts delete mode 100644 packages/html/html/rollup.config.js create mode 100644 packages/html/html/tsdown.config.ts create mode 100644 packages/react-native/react-native-icons/src/index.ts delete mode 100644 packages/react-native/react-native-icons/src/index.tsx create mode 100644 packages/react-native/react-native-icons/tsconfig.build.json create mode 100644 packages/react-native/react-native-icons/tsdown.config.ts delete mode 100644 packages/react-native/react-native-icons/tsup.config.ts rename packages/react-native/react-native-media-elements/src/{index.tsx => index.ts} (66%) create mode 100644 packages/react-native/react-native-media-elements/tsconfig.build.json create mode 100644 packages/react-native/react-native-media-elements/tsdown.config.ts delete mode 100644 packages/react-native/react-native-media-elements/tsup.config.ts rename packages/react-native/react-native/src/{index.tsx => index.ts} (61%) create mode 100644 packages/react-native/react-native/tsconfig.build.json create mode 100644 packages/react-native/react-native/tsdown.config.ts delete mode 100644 packages/react-native/react-native/tsup.config.ts delete mode 100644 packages/react/react-icons/rollup.config.js create mode 100644 packages/react/react-icons/tsdown.config.ts create mode 100644 packages/react/react-media-elements/tsconfig.build.json create mode 100644 packages/react/react-media-elements/tsdown.config.ts delete mode 100644 packages/react/react-media-elements/tsup.config.ts delete mode 100644 packages/react/react-media-store/src/index.tsx create mode 100644 packages/react/react-media-store/tsconfig.build.json create mode 100644 packages/react/react-media-store/tsdown.config.ts delete mode 100644 packages/react/react-media-store/tsup.config.ts delete mode 100644 packages/react/react/rollup.config.js rename packages/react/react/src/{index.tsx => index.ts} (84%) create mode 100644 packages/react/react/tsdown.config.ts diff --git a/package.json b/package.json index a627de0d..efd886ff 100644 --- a/package.json +++ b/package.json @@ -8,12 +8,13 @@ "clean": "turbo run clean", "dev:html": "turbo run dev --filter=html-demo...", "dev:react": "turbo run dev --filter=react-demo...", - "dev": "turbo run dev --parallel", + "dev": "turbo run dev --parallel --filter=./packages/**", + "generate:icons": "turbo run generate:icons", "format:check": "prettier . --check --log-level warn --cache", "format": "prettier . --write --log-level warn --cache", "lint": "turbo run lint", "test": "turbo run test", - "typecheck": "turbo run typecheck" + "typecheck": "pnpm run generate:icons && tsc --build --noEmit" }, "devDependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.7.0", diff --git a/packages/core/icons/package.json b/packages/core/icons/package.json index 117a70b3..7a463cf9 100644 --- a/packages/core/icons/package.json +++ b/packages/core/icons/package.json @@ -1,22 +1,24 @@ { "name": "@vjs-10/icons", + "type": "module", "version": "0.1.0", - "description": "Environment-agnostic library of SVG icons and possibly transforms or tooling for them.", + "description": "SVG icon library for Video.js", "main": "dist/index.js", - "module": "dist/index.mjs", + "module": "dist/index.js", "types": "dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" + "default": "./dist/index.js" } }, "files": [ "dist" ], "scripts": { - "build": "rollup -c && tsc --project tsconfig.build.json", + "build": "tsdown", + "build:watch": "tsdown --watch --silent", + "dev": "pnpm run build:watch", "test": "echo \"No tests yet\"", "clean": "rm -rf dist" }, @@ -29,13 +31,7 @@ ], "license": "Apache-2.0", "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.0", - "@rollup/plugin-node-resolve": "^15.0.0", - "@rollup/plugin-typescript": "^11.0.0", - "rollup": "^4.0.0", - "rollup-plugin-string": "^3.0.0", - "tslib": "^2.6.0", - "tsup": "^8.5.0", + "tsdown": "^0.15.4", "typescript": "^5.9.2" }, "publishConfig": { diff --git a/packages/core/icons/rollup.config.js b/packages/core/icons/rollup.config.js deleted file mode 100644 index 63284534..00000000 --- a/packages/core/icons/rollup.config.js +++ /dev/null @@ -1,75 +0,0 @@ -const typescript = require('@rollup/plugin-typescript'); -const resolve = require('@rollup/plugin-node-resolve'); -const commonjs = require('@rollup/plugin-commonjs'); -const { string } = require('rollup-plugin-string'); - -module.exports = [ - // ESM build - { - input: 'src/index.ts', - output: { - file: 'dist/index.mjs', - format: 'esm', - sourcemap: true, - }, - watch: { - clearScreen: false, - }, - external: (id) => { - // Don't externalize relative imports (starts with . or /) - if (id.startsWith('.') || id.startsWith('/')) return false; - // Don't externalize absolute paths (local files) - if (id.includes('/') && !id.startsWith('@')) return false; - // Externalize all npm packages (including scoped ones) - return true; - }, - plugins: [ - string({ - include: '**/*.svg', - }), - resolve({ - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }), - commonjs(), - typescript({ - tsconfig: 'tsconfig.json', - declaration: false, - outDir: 'dist', - }), - ], - }, - // CommonJS build - { - input: 'src/index.ts', - output: { - file: 'dist/index.js', - format: 'cjs', - sourcemap: true, - }, - watch: { - clearScreen: false, - }, - external: (id) => { - // Don't externalize relative imports (starts with . or /) - if (id.startsWith('.') || id.startsWith('/')) return false; - // Don't externalize absolute paths (local files) - if (id.includes('/') && !id.startsWith('@')) return false; - // Externalize all npm packages (including scoped ones) - return true; - }, - plugins: [ - string({ - include: '**/*.svg', - }), - resolve({ - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }), - commonjs(), - typescript({ - tsconfig: 'tsconfig.json', - declaration: false, - outDir: 'dist', - }), - ], - }, -]; diff --git a/packages/core/icons/src/index.ts b/packages/core/icons/src/index.ts index 31a993ba..0d45b5e4 100644 --- a/packages/core/icons/src/index.ts +++ b/packages/core/icons/src/index.ts @@ -7,8 +7,7 @@ import volumeHighSvg from '../assets/volume-high.svg'; import volumeLowSvg from '../assets/volume-low.svg'; import volumeOffSvg from '../assets/volume-off.svg'; -// Export SVG strings directly -export const SVG_ICONS = { +export const SVG_ICONS: Record = { play: playSvg, pause: pauseSvg, volumeHigh: volumeHighSvg, diff --git a/packages/core/icons/tsconfig.build.json b/packages/core/icons/tsconfig.build.json index 6c809265..b90fc83e 100644 --- a/packages/core/icons/tsconfig.build.json +++ b/packages/core/icons/tsconfig.build.json @@ -1,13 +1,4 @@ { "extends": "./tsconfig.json", - "compilerOptions": { - "declaration": true, - "declarationDir": "dist", - "emitDeclarationOnly": true, - "outDir": "dist", - "skipLibCheck": true, - "composite": false, - "incremental": false - }, - "exclude": ["dist", "node_modules"] + "include": ["src"] } diff --git a/packages/core/icons/tsconfig.json b/packages/core/icons/tsconfig.json index 9d54d911..c4d7be0c 100644 --- a/packages/core/icons/tsconfig.json +++ b/packages/core/icons/tsconfig.json @@ -1,9 +1,10 @@ { "extends": "../../../tsconfig.base.json", "compilerOptions": { - "outDir": "./dist", - "rootDir": "./src" + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } }, - "include": ["src/**/*"], - "exclude": ["dist", "node_modules"] + "include": ["src"] } diff --git a/packages/core/icons/tsdown.config.ts b/packages/core/icons/tsdown.config.ts new file mode 100644 index 00000000..96bf942b --- /dev/null +++ b/packages/core/icons/tsdown.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'tsdown'; + +export default defineConfig({ + entry: 'src/index.ts', + platform: 'browser', + format: 'es', + sourcemap: true, + clean: true, + dts: { + oxc: true, + }, + loader: { + '.svg': 'text', + }, +}); diff --git a/packages/core/media-store/package.json b/packages/core/media-store/package.json index 665b2b2a..ef14a33f 100644 --- a/packages/core/media-store/package.json +++ b/packages/core/media-store/package.json @@ -1,22 +1,24 @@ { "name": "@vjs-10/media-store", + "type": "module", "version": "0.1.0", - "description": "A state abstraction for media. Accepts state owners like a media state owner for sinks and sources of media state.", + "description": "Media store for tracking and managing media state.", "main": "dist/index.js", - "module": "dist/index.mjs", + "module": "dist/index.js", "types": "dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" + "default": "./dist/index.js" } }, "files": [ "dist" ], "scripts": { - "build": "rollup -c && tsc --project tsconfig.build.json", + "build": "tsdown", + "build:watch": "tsdown --watch --silent", + "dev": "pnpm run build:watch", "test": "echo \"No tests yet\"", "clean": "rm -rf dist" }, @@ -32,12 +34,7 @@ "nanostores": "^1.0.1" }, "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.0", - "@rollup/plugin-node-resolve": "^15.0.0", - "@rollup/plugin-typescript": "^11.0.0", - "rollup": "^4.0.0", - "tslib": "^2.6.0", - "tsup": "^8.5.0", + "tsdown": "^0.15.4", "typescript": "^5.9.2" }, "publishConfig": { diff --git a/packages/core/media-store/rollup.config.js b/packages/core/media-store/rollup.config.js deleted file mode 100644 index d4d9cbf8..00000000 --- a/packages/core/media-store/rollup.config.js +++ /dev/null @@ -1,68 +0,0 @@ -const typescript = require('@rollup/plugin-typescript'); -const resolve = require('@rollup/plugin-node-resolve'); -const commonjs = require('@rollup/plugin-commonjs'); - -module.exports = [ - // ESM build - { - input: 'src/index.ts', - output: { - file: 'dist/index.mjs', - format: 'esm', - sourcemap: true, - }, - watch: { - clearScreen: false, - }, - external: (id) => { - // Don't externalize relative imports (starts with . or /) - if (id.startsWith('.') || id.startsWith('/')) return false; - // Don't externalize absolute paths (local files) - if (id.includes('/') && !id.startsWith('@')) return false; - // Externalize all npm packages (including scoped ones) - return true; - }, - plugins: [ - resolve({ - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }), - commonjs(), - typescript({ - tsconfig: 'tsconfig.json', - declaration: false, - outDir: 'dist', - }), - ], - }, - // CommonJS build - { - input: 'src/index.ts', - output: { - file: 'dist/index.js', - format: 'cjs', - sourcemap: true, - }, - watch: { - clearScreen: false, - }, - external: (id) => { - // Don't externalize relative imports (starts with . or /) - if (id.startsWith('.') || id.startsWith('/')) return false; - // Don't externalize absolute paths (local files) - if (id.includes('/') && !id.startsWith('@')) return false; - // Externalize all npm packages (including scoped ones) - return true; - }, - plugins: [ - resolve({ - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }), - commonjs(), - typescript({ - tsconfig: 'tsconfig.json', - declaration: false, - outDir: 'dist', - }), - ], - }, -]; diff --git a/packages/core/media-store/src/component-state-definitions/current-time-display.ts b/packages/core/media-store/src/component-state-definitions/current-time-display.ts index 5ad3deec..e94aad01 100644 --- a/packages/core/media-store/src/component-state-definitions/current-time-display.ts +++ b/packages/core/media-store/src/component-state-definitions/current-time-display.ts @@ -47,7 +47,7 @@ export const currentTimeDisplayStateDefinition = { * @returns Empty object (no request methods) */ createRequestMethods: (_dispatch: (action: { type: string; detail?: any }) => void) => ({}), -} as const; +}; /** * Type helper to extract the state type from the current time display state definition diff --git a/packages/core/media-store/src/component-state-definitions/duration-display.ts b/packages/core/media-store/src/component-state-definitions/duration-display.ts index 9fd99815..874afe8a 100644 --- a/packages/core/media-store/src/component-state-definitions/duration-display.ts +++ b/packages/core/media-store/src/component-state-definitions/duration-display.ts @@ -43,7 +43,7 @@ export const durationDisplayStateDefinition = { * @returns Empty object (no request methods) */ createRequestMethods: (_dispatch: (action: { type: string; detail?: any }) => void) => ({}), -} as const; +}; /** * Type helper to extract the state type from the duration display state definition diff --git a/packages/core/media-store/src/component-state-definitions/play-button.ts b/packages/core/media-store/src/component-state-definitions/play-button.ts index 5906e945..7fc17e2d 100644 --- a/packages/core/media-store/src/component-state-definitions/play-button.ts +++ b/packages/core/media-store/src/component-state-definitions/play-button.ts @@ -10,7 +10,7 @@ export interface PlayButtonMethods { export interface PlayButtonStateDefinition { keys: string[]; stateTransform: (rawState: any) => PlayButtonState; - createRequestMethods: (dispatch: (action: { type: string }) => void) => PlayButtonMethods; + createRequestMethods: (dispatch: (action: { type: string; detail?: unknown }) => void) => PlayButtonMethods; } /** diff --git a/packages/core/media-store/src/factory.ts b/packages/core/media-store/src/factory.ts index b9ece22b..5b2977d1 100644 --- a/packages/core/media-store/src/factory.ts +++ b/packages/core/media-store/src/factory.ts @@ -29,7 +29,7 @@ export type FacadeProp = ReadonlyFacadeProp & { set: FacadeSetter; /** @TODO We probably need to refactor this for more complex cases where we can't simply translate to a setter */ actions: { - [k: string]: (val: Pick, 'type' | 'detail'>) => ReturnType>; + [k: string]: (val: { type: string; detail?: unknown }) => ReturnType>; }; }; @@ -44,6 +44,14 @@ export type StateMediator = { fullscreen: FacadeProp; }; +export interface MediaStore { + dispatch(action: { type: string; detail?: unknown }): void; + getState(): any; + getKeys(keys: string[]): Record; + subscribeKeys(keys: string[], callback: (state: any) => void): void; + subscribe(callback: (state: any) => void): void; +} + export function createMediaStore({ // media, stateMediator, @@ -51,7 +59,7 @@ export function createMediaStore({ media?: any; container?: any; stateMediator: Partial & Pick; -}) { +}): MediaStore { const stateOwners: StateOwners = {}; const store = map({}); const stateUpdateHandlerCleanups: Record void)[]> = {}; @@ -101,7 +109,7 @@ export function createMediaStore({ } return { - dispatch(action: Pick, 'type' | 'detail'>) { + dispatch(action: Pick, 'type' | 'detail'>): void { const { type, detail } = action; if (type === 'mediastateownerchangerequest') { @@ -122,11 +130,11 @@ export function createMediaStore({ } }, - getState() { + getState(): any { return store.get(); }, - getKeys(keys: string[]) { + getKeys(keys: string[]): Record { return keys.reduce( (acc, k) => { acc[k] = getKey(store, k); @@ -136,12 +144,12 @@ export function createMediaStore({ ); }, - subscribeKeys(keys: string[], callback: (state: any) => void) { + subscribeKeys(keys: string[], callback: (state: any) => void): void { subscribeKeys(store, keys, callback); }, // NOTE: In the POC architecture using nano-stores, subscribe is simply subscribeKeys across all keys. (CJP) - subscribe(callback: (state: any) => void) { + subscribe(callback: (state: any) => void): void { subscribeKeys(store, keys, callback); }, }; diff --git a/packages/core/media-store/src/index.ts b/packages/core/media-store/src/index.ts index 32c61ecf..1a7577e9 100644 --- a/packages/core/media-store/src/index.ts +++ b/packages/core/media-store/src/index.ts @@ -2,7 +2,7 @@ export * from './factory'; export { createMediaStore } from './media-store'; export * from './state-mediators/playable'; export * from './state-mediators/audible'; -export * from './state-mediators/temporal'; +export * from './utils/temporal'; export * from './component-state-definitions/play-button'; export * from './component-state-definitions/mute-button'; export * from './component-state-definitions/volume-range'; diff --git a/packages/core/media-store/src/media-store.ts b/packages/core/media-store/src/media-store.ts index eacdace8..035400a5 100644 --- a/packages/core/media-store/src/media-store.ts +++ b/packages/core/media-store/src/media-store.ts @@ -1,11 +1,19 @@ +import type { MediaStore } from './factory'; + import { createMediaStore as factory } from './factory'; import { audible } from './state-mediators/audible'; import { fullscreenable } from './state-mediators/fullscreenable'; import { playable } from './state-mediators/playable'; -import { temporal } from './state-mediators/temporal'; +import { temporal } from './utils/temporal'; // Example of default media store with default state mediator definitions. (CJP) // NOTE: We can also change the API to take an array of stateMediators (or either/both) (CJP) const stateMediator = { ...playable, ...audible, ...temporal, ...fullscreenable }; + type Params = Partial[0]>; -export const createMediaStore = (params: Params = {}) => factory({ stateMediator, ...params }); + +export const createMediaStore = (params: Params = {}): MediaStore => + factory({ + stateMediator: stateMediator as any, + ...params, + }); diff --git a/packages/core/media-store/src/state-mediators/audible.ts b/packages/core/media-store/src/state-mediators/audible.ts index 7d4f7946..05a61f8f 100644 --- a/packages/core/media-store/src/state-mediators/audible.ts +++ b/packages/core/media-store/src/state-mediators/audible.ts @@ -1,10 +1,10 @@ export const audible = { muted: { - get(stateOwners: any) { + get(stateOwners: any): boolean { const { media } = stateOwners; return media?.muted ?? false; }, - set(value: boolean, stateOwners: any) { + set(value: boolean, stateOwners: any): void { const { media } = stateOwners; if (!media) return; media.muted = value; @@ -13,7 +13,7 @@ export const audible = { } }, stateOwnersUpdateHandlers: [ - (handler: (value?: boolean) => void, stateOwners: any) => { + (handler: (value?: boolean) => void, stateOwners: any): (() => void) | void => { const { media } = stateOwners; if (!media) return; @@ -22,7 +22,7 @@ export const audible = { return () => media.removeEventListener('volumechange', eventHandler); }, - ], + ] as const, actions: { /** @TODO Refactor me to play more nicely with side effects that don't/can't correlate with set() API or aren't simple 1:1 with getter vs. setter (CJP) */ muterequest: () => true, @@ -30,11 +30,11 @@ export const audible = { }, }, volume: { - get(stateOwners: any) { + get(stateOwners: any): number { const { media } = stateOwners; return media?.volume ?? 1.0; }, - set(value: number, stateOwners: any) { + set(value: number, stateOwners: any): void { const { media } = stateOwners; if (!media) return; const numericValue = +value; @@ -45,7 +45,7 @@ export const audible = { } }, stateOwnersUpdateHandlers: [ - (handler: (value?: number) => void, stateOwners: any) => { + (handler: (value?: number) => void, stateOwners: any): (() => void) | void => { const { media } = stateOwners; if (!media) return; @@ -54,15 +54,15 @@ export const audible = { return () => media.removeEventListener('volumechange', eventHandler); }, - ], + ] as const, actions: { /** @TODO Refactor me to play more nicely with side effects that don't/can't correlate with set() API (CJP) */ - volumerequest: ({ detail }: Pick, 'detail'> = { detail: 0 }) => +detail, + volumerequest: ({ detail }: Pick, 'detail'> = { detail: 0 }): number => +detail, }, }, // NOTE: This could be (re)implemented as "derived state" in some manner (e.g. selectors but also other patterns/conventions) if preferred. (CJP) volumeLevel: { - get(stateOwners: any) { + get(stateOwners: any): 'high' | 'medium' | 'low' | 'off' { const { media } = stateOwners; if (typeof media?.volume == 'undefined') return 'high'; if (media.muted || media.volume === 0) return 'off'; @@ -71,7 +71,7 @@ export const audible = { return 'high'; }, stateOwnersUpdateHandlers: [ - (handler: (value?: 'high' | 'medium' | 'low' | 'off') => void, stateOwners: any) => { + (handler: (value?: 'high' | 'medium' | 'low' | 'off') => void, stateOwners: any): void | (() => void) => { const { media } = stateOwners; if (!media) return; @@ -80,6 +80,6 @@ export const audible = { return () => media.removeEventListener('volumechange', eventHandler); }, - ], + ] as const, }, }; diff --git a/packages/core/media-store/src/state-mediators/fullscreenable.ts b/packages/core/media-store/src/state-mediators/fullscreenable.ts index 82acee30..4cfb76fb 100644 --- a/packages/core/media-store/src/state-mediators/fullscreenable.ts +++ b/packages/core/media-store/src/state-mediators/fullscreenable.ts @@ -12,7 +12,7 @@ const containsComposedNode = (rootNode: Node, childNode: Node): boolean => { /** @TODO This is implemented for web/browser only! We will need an alternative state mediator model for e.g. React Native. (CJP) */ export const fullscreenable = { fullscreen: { - get(stateOwners: any) { + get(stateOwners: any): boolean { const { container } = stateOwners; if (!container || !globalThis?.document) return false; @@ -64,7 +64,7 @@ export const fullscreenable = { return false; }, - set(value: boolean, stateOwners: any) { + set(value: boolean, stateOwners: any): void { const { container } = stateOwners; if (!container || !globalThis?.document) return; @@ -105,7 +105,7 @@ export const fullscreenable = { } }, stateOwnersUpdateHandlers: [ - (handler: (value?: boolean) => void, _stateOwners: any) => { + (handler: (value?: boolean) => void, _stateOwners: any): void | (() => void) => { if (!globalThis?.document) return; const eventHandler = () => handler(); @@ -121,10 +121,10 @@ export const fullscreenable = { }); }; }, - ], + ] as const, actions: { /** Toggle fullscreen state or explicitly enter/exit based on detail */ - fullscreenrequest: ({ detail }: Pick, 'detail'> = { detail: undefined }) => { + fullscreenrequest: ({ detail }: Pick, 'detail'> = { detail: undefined }): boolean => { // If detail is provided, use it; otherwise toggle current state if (typeof detail === 'boolean') { return detail; diff --git a/packages/core/media-store/src/state-mediators/index.ts b/packages/core/media-store/src/state-mediators/index.ts index b19a68cd..1c6ab4ae 100644 --- a/packages/core/media-store/src/state-mediators/index.ts +++ b/packages/core/media-store/src/state-mediators/index.ts @@ -1,4 +1,4 @@ export { audible } from './audible'; export { playable } from './playable'; -export { temporal } from './temporal'; +export { temporal } from '../utils/temporal'; export { fullscreenable } from './fullscreenable'; diff --git a/packages/core/media-store/src/state-mediators/playable.ts b/packages/core/media-store/src/state-mediators/playable.ts index 089be41c..540f68a1 100644 --- a/packages/core/media-store/src/state-mediators/playable.ts +++ b/packages/core/media-store/src/state-mediators/playable.ts @@ -1,15 +1,15 @@ export const playable = { paused: { - get(stateOwners: any) { + get(stateOwners: any): boolean { const { media } = stateOwners; return media?.paused ?? true; }, - set(value: boolean, stateOwners: any) { + set(value: boolean, stateOwners: any): void { const { media } = stateOwners; media?.[value ? 'pause' : 'play'](); }, stateOwnersUpdateHandlers: [ - (handler: (value?: boolean) => void, stateOwners: any) => { + (handler: (value?: boolean) => void, stateOwners: any): void | (() => void) => { const { media } = stateOwners; if (!media) return; @@ -19,7 +19,7 @@ export const playable = { return () => events.forEach((event) => media.removeEventListener(event, eventHandler)); }, - ], + ] as const, actions: { /** @TODO Refactor me to play more nicely with side effects that don't/can't correlate with set() API (CJP) */ playrequest: () => false, diff --git a/packages/core/media-store/src/state-mediators/temporal.ts b/packages/core/media-store/src/utils/temporal.ts similarity index 86% rename from packages/core/media-store/src/state-mediators/temporal.ts rename to packages/core/media-store/src/utils/temporal.ts index 0e051256..2f0bea54 100644 --- a/packages/core/media-store/src/state-mediators/temporal.ts +++ b/packages/core/media-store/src/utils/temporal.ts @@ -4,17 +4,17 @@ const isValidNumber = (value: any): value is number => { export const temporal = { currentTime: { - get(stateOwners: any) { + get(stateOwners: any): number { const { media } = stateOwners; return media?.currentTime ?? 0; }, - set(value: number, stateOwners: any) { + set(value: number, stateOwners: any): void { const { media } = stateOwners; if (!media || !isValidNumber(value)) return; media.currentTime = value; }, stateOwnersUpdateHandlers: [ - (handler: (value?: number) => void, stateOwners: any) => { + (handler: (value?: number) => void, stateOwners: any): void | (() => void) => { const { media } = stateOwners; if (!media) return; @@ -24,15 +24,15 @@ export const temporal = { return () => events.forEach((event) => media.removeEventListener(event, eventHandler)); }, - ], + ] as const, actions: { /** @TODO Support more sophisticated seeking patterns like seek-to-live, relative seeking, etc. (CJP) */ - seekrequest: ({ detail }: Pick, 'detail'> = { detail: 0 }) => +detail, + seekrequest: ({ detail }: Pick, 'detail'> = { detail: 0 }): number => +detail, }, }, duration: { - get(stateOwners: any) { + get(stateOwners: any): number { const { media } = stateOwners; // Return 0 if no media or invalid duration @@ -43,7 +43,7 @@ export const temporal = { return media.duration; }, stateOwnersUpdateHandlers: [ - (handler: (value?: number) => void, stateOwners: any) => { + (handler: (value?: number) => void, stateOwners: any): void | (() => void) => { const { media } = stateOwners; if (!media) return; @@ -53,7 +53,7 @@ export const temporal = { return () => events.forEach((event) => media.removeEventListener(event, eventHandler)); }, - ], + ] as const, }, seekable: { @@ -71,7 +71,7 @@ export const temporal = { return [Number(start.toFixed(3)), Number(end.toFixed(3))]; }, stateOwnersUpdateHandlers: [ - (handler: (value?: [number, number] | undefined) => void, stateOwners: any) => { + (handler: (value?: [number, number] | undefined) => void, stateOwners: any): void | (() => void) => { const { media } = stateOwners; if (!media) return; @@ -81,6 +81,6 @@ export const temporal = { return () => events.forEach((event) => media.removeEventListener(event, eventHandler)); }, - ], + ] as const, }, }; diff --git a/packages/core/media-store/tsconfig.build.json b/packages/core/media-store/tsconfig.build.json index 6c809265..b90fc83e 100644 --- a/packages/core/media-store/tsconfig.build.json +++ b/packages/core/media-store/tsconfig.build.json @@ -1,13 +1,4 @@ { "extends": "./tsconfig.json", - "compilerOptions": { - "declaration": true, - "declarationDir": "dist", - "emitDeclarationOnly": true, - "outDir": "dist", - "skipLibCheck": true, - "composite": false, - "incremental": false - }, - "exclude": ["dist", "node_modules"] + "include": ["src"] } diff --git a/packages/core/media-store/tsconfig.json b/packages/core/media-store/tsconfig.json index 9d54d911..c4d7be0c 100644 --- a/packages/core/media-store/tsconfig.json +++ b/packages/core/media-store/tsconfig.json @@ -1,9 +1,10 @@ { "extends": "../../../tsconfig.base.json", "compilerOptions": { - "outDir": "./dist", - "rootDir": "./src" + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } }, - "include": ["src/**/*"], - "exclude": ["dist", "node_modules"] + "include": ["src"] } diff --git a/packages/core/media-store/tsdown.config.ts b/packages/core/media-store/tsdown.config.ts new file mode 100644 index 00000000..3b3cc13d --- /dev/null +++ b/packages/core/media-store/tsdown.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'tsdown'; + +export default defineConfig({ + entry: 'src/index.ts', + platform: 'browser', + format: 'es', + sourcemap: true, + clean: true, + dts: { + oxc: true, + }, +}); diff --git a/packages/core/media/package.json b/packages/core/media/package.json index 6721e379..2a7a051e 100644 --- a/packages/core/media/package.json +++ b/packages/core/media/package.json @@ -1,22 +1,24 @@ { "name": "@vjs-10/media", + "type": "module", "version": "0.1.0", - "description": "JS contracts and convenience code for conforming to HTMLMediaElement and related interfaces.", + "description": "Media related contracts and utilities.", "main": "dist/index.js", - "module": "dist/index.mjs", + "module": "dist/index.js", "types": "dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" + "default": "./dist/index.js" } }, "files": [ "dist" ], "scripts": { - "build": "tsup", + "build": "tsdown", + "build:watch": "tsdown --watch --silent", + "dev": "pnpm run build:watch", "test": "echo \"No tests yet\"", "clean": "rm -rf dist" }, @@ -32,7 +34,7 @@ "@vjs-10/playback-engine": "workspace:*" }, "devDependencies": { - "tsup": "^8.5.0", + "tsdown": "^0.15.4", "typescript": "^5.9.2" }, "publishConfig": { diff --git a/packages/core/media/src/playable.ts b/packages/core/media/src/playable.ts index 9d2a5fd1..b001245a 100644 --- a/packages/core/media/src/playable.ts +++ b/packages/core/media/src/playable.ts @@ -14,10 +14,8 @@ export const Events = [ 'durationchange', ] as const; -export interface IBaseMediaStateOwner = Pick> - extends EventTarget, - Pick { - mediaElement?: T | undefined; +export interface IBaseMediaStateOwner extends EventTarget, Pick { + mediaElement?: HTMLMediaElement | undefined; } export interface IPlayableMediaStateOwner @@ -37,23 +35,27 @@ export interface ITemporalMediaStateOwner export class PlayableMediaStateOwner extends EventTarget implements IPlayableMediaStateOwner, IAudibleMediaStateOwner { protected _playbackEngine: IBasePlaybackEngine; + constructor() { super(); this._playbackEngine = createPlaybackEngine(); } - get mediaElement() { + get mediaElement(): HTMLMediaElement | undefined { return this._playbackEngine.mediaElement; } set mediaElement(value) { if (this.mediaElement === value) return; + if (this.mediaElement != null) { Events.forEach((eventType) => { this.mediaElement?.removeEventListener(eventType, this); }); } + this._playbackEngine.mediaElement = value; + if (this.mediaElement) { Events.forEach((eventType) => { this.mediaElement?.addEventListener(eventType, this); @@ -61,64 +63,64 @@ export class PlayableMediaStateOwner extends EventTarget implements IPlayableMed } } - get paused() { + get paused(): boolean { return this.mediaElement?.paused ?? false; } - pause() { + pause(): void { /** @TODO implement deferred state etc. for cases where media has yet to be set */ if (!this.mediaElement) return; return this.mediaElement.pause(); } - play() { + play(): Promise { /** @TODO implement deferred state etc. for cases where media has yet to be set */ if (!this.mediaElement) return Promise.reject(); return this.mediaElement.play(); } - get muted() { + get muted(): boolean { return this.mediaElement?.muted ?? false; } - set muted(value) { + set muted(value: boolean) { if (value === this.muted) return; /** @TODO implement deferred state etc. for cases where media has yet to be set */ if (!this.mediaElement) return; this.mediaElement.muted = value; } - get volume() { + get volume(): number { return this.mediaElement?.volume ?? 0; } - set volume(value) { + set volume(value: number) { if (value === this.volume) return; /** @TODO implement deferred state etc. for cases where media has yet to be set */ if (!this.mediaElement) return; this.mediaElement.volume = value; } - get duration() { + get duration(): number { return this.mediaElement?.duration ?? 0; } - get currentTime() { + get currentTime(): number { return this.mediaElement?.currentTime ?? 0; } - set currentTime(value) { + set currentTime(value: number) { if (value === this.currentTime) return; /** @TODO implement deferred state etc. for cases where media has yet to be set */ if (!this.mediaElement) return; this.mediaElement.currentTime = value; } - get src() { + get src(): string { return this._playbackEngine.src ?? ''; } - set src(value) { + set src(value: string) { this._playbackEngine.src = value; } @@ -129,10 +131,9 @@ export class PlayableMediaStateOwner extends EventTarget implements IPlayableMed } } - destroy() { - this.mediaElement = undefined; + destroy(): void { this._playbackEngine.destroy(); } } -export const createMediaStateOwner = () => new PlayableMediaStateOwner(); +export const createMediaStateOwner = (): PlayableMediaStateOwner => new PlayableMediaStateOwner(); diff --git a/packages/core/media/tsconfig.build.json b/packages/core/media/tsconfig.build.json new file mode 100644 index 00000000..b90fc83e --- /dev/null +++ b/packages/core/media/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["src"] +} diff --git a/packages/core/media/tsconfig.json b/packages/core/media/tsconfig.json index 9d54d911..c4d7be0c 100644 --- a/packages/core/media/tsconfig.json +++ b/packages/core/media/tsconfig.json @@ -1,9 +1,10 @@ { "extends": "../../../tsconfig.base.json", "compilerOptions": { - "outDir": "./dist", - "rootDir": "./src" + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } }, - "include": ["src/**/*"], - "exclude": ["dist", "node_modules"] + "include": ["src"] } diff --git a/packages/core/media/tsdown.config.ts b/packages/core/media/tsdown.config.ts new file mode 100644 index 00000000..3b3cc13d --- /dev/null +++ b/packages/core/media/tsdown.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'tsdown'; + +export default defineConfig({ + entry: 'src/index.ts', + platform: 'browser', + format: 'es', + sourcemap: true, + clean: true, + dts: { + oxc: true, + }, +}); diff --git a/packages/core/media/tsup.config.ts b/packages/core/media/tsup.config.ts deleted file mode 100644 index a4bebd83..00000000 --- a/packages/core/media/tsup.config.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { defineConfig } from 'tsup'; - -export default defineConfig({ - entry: ['src/index.ts'], - format: ['cjs', 'esm'], - clean: true, - sourcemap: true, - outDir: 'dist', - external: [ - // Keep all dependencies external for library builds - /^@vjs-10\//, - /^[^.]/, - ], - // Generate TypeScript declarations with custom config - dts: { - compilerOptions: { - composite: false, - incremental: false, - }, - }, -}); diff --git a/packages/core/playback-engine/package.json b/packages/core/playback-engine/package.json index 6b62cfac..935b46ad 100644 --- a/packages/core/playback-engine/package.json +++ b/packages/core/playback-engine/package.json @@ -1,22 +1,24 @@ { "name": "@vjs-10/playback-engine", + "type": "module", "version": "0.1.0", - "description": "An abstraction for building or abstracting media source management (provides a common contract for things like hls.js or dash.js).", + "description": "Common media playback engine utilities and contracts supporting various streaming protocols", "main": "dist/index.js", - "module": "dist/index.mjs", + "module": "dist/index.js", "types": "dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" + "default": "./dist/index.js" } }, "files": [ "dist" ], "scripts": { - "build": "tsup", + "build": "tsdown", + "build:watch": "tsdown --watch --silent", + "dev": "pnpm run build:watch", "test": "echo \"No tests yet\"", "clean": "rm -rf dist" }, @@ -33,7 +35,7 @@ "hls.js": "^1.6.7" }, "devDependencies": { - "tsup": "^8.5.0", + "tsdown": "^0.15.4", "typescript": "^5.9.2" }, "publishConfig": { diff --git a/packages/core/playback-engine/src/HlsJSPlaybackEngine.ts b/packages/core/playback-engine/src/HlsJSPlaybackEngine.ts index d94ed0c0..a15cfe7c 100644 --- a/packages/core/playback-engine/src/HlsJSPlaybackEngine.ts +++ b/packages/core/playback-engine/src/HlsJSPlaybackEngine.ts @@ -18,17 +18,19 @@ export class HlsJSPlaybackEngine extends EventTarget { protected _hlsInstance: Hls | undefined; - get src() { + get src(): string | undefined { return this._hlsInstance?.url ?? undefined; } - set src(val) { - if (this.src === val) return; + set src(src: string | undefined) { + if (this.src === src) return; + if (!this._hlsInstance) { this._createHlsInstance(); } - if (!this.src && val) { - this._hlsInstance?.loadSource(val); + + if (!this.src && src) { + this._hlsInstance?.loadSource(src); } } @@ -45,32 +47,34 @@ export class HlsJSPlaybackEngine extends EventTarget { this.mediaElement = val as HTMLMediaElement; } - get mediaElement() { + get mediaElement(): HTMLMediaElement | undefined { return this._hlsInstance?.media ?? undefined; } set mediaElement(val) { if (this.mediaElement === val) return; + if (!this._hlsInstance) { this._createHlsInstance(); } + if (!this.mediaElement && val) { this._hlsInstance?.attachMedia(val); } } - protected _createHlsInstance() { + protected _createHlsInstance(): void { this._hlsInstance = new Hls(); } - protected _destroyHlsInstance() { + protected _destroyHlsInstance(): void { this._hlsInstance?.destroy(); this._hlsInstance = undefined; } - destroy() { + destroy(): void { this._destroyHlsInstance(); } } -export const createPlaybackEngine = () => new HlsJSPlaybackEngine(); +export const createPlaybackEngine = (): IBasePlaybackEngine => new HlsJSPlaybackEngine(); diff --git a/packages/core/playback-engine/tsconfig.build.json b/packages/core/playback-engine/tsconfig.build.json new file mode 100644 index 00000000..b90fc83e --- /dev/null +++ b/packages/core/playback-engine/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["src"] +} diff --git a/packages/core/playback-engine/tsconfig.json b/packages/core/playback-engine/tsconfig.json index 9d54d911..c4d7be0c 100644 --- a/packages/core/playback-engine/tsconfig.json +++ b/packages/core/playback-engine/tsconfig.json @@ -1,9 +1,10 @@ { "extends": "../../../tsconfig.base.json", "compilerOptions": { - "outDir": "./dist", - "rootDir": "./src" + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } }, - "include": ["src/**/*"], - "exclude": ["dist", "node_modules"] + "include": ["src"] } diff --git a/packages/core/playback-engine/tsdown.config.ts b/packages/core/playback-engine/tsdown.config.ts new file mode 100644 index 00000000..3b3cc13d --- /dev/null +++ b/packages/core/playback-engine/tsdown.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'tsdown'; + +export default defineConfig({ + entry: 'src/index.ts', + platform: 'browser', + format: 'es', + sourcemap: true, + clean: true, + dts: { + oxc: true, + }, +}); diff --git a/packages/core/playback-engine/tsup.config.ts b/packages/core/playback-engine/tsup.config.ts deleted file mode 100644 index a4bebd83..00000000 --- a/packages/core/playback-engine/tsup.config.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { defineConfig } from 'tsup'; - -export default defineConfig({ - entry: ['src/index.ts'], - format: ['cjs', 'esm'], - clean: true, - sourcemap: true, - outDir: 'dist', - external: [ - // Keep all dependencies external for library builds - /^@vjs-10\//, - /^[^.]/, - ], - // Generate TypeScript declarations with custom config - dts: { - compilerOptions: { - composite: false, - incremental: false, - }, - }, -}); diff --git a/packages/html/html-icons/package.json b/packages/html/html-icons/package.json index 2f8f9eb9..120be94a 100644 --- a/packages/html/html-icons/package.json +++ b/packages/html/html-icons/package.json @@ -1,22 +1,24 @@ { "name": "@vjs-10/html-icons", + "type": "module", "version": "0.1.0", - "description": "HTML/DOM-specific icon components derived from @vjs-10/icons", + "description": "HTML icons for Video.js", "main": "dist/index.js", - "module": "dist/index.mjs", + "module": "dist/index.js", "types": "dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" + "default": "./dist/index.js" } }, "files": [ "dist" ], "scripts": { - "build": "rollup -c && tsc --project tsconfig.build.json", + "build": "tsdown", + "build:watch": "tsdown --watch --silent", + "dev": "pnpm run build:watch", "test": "echo \"No tests yet\"", "clean": "rm -rf dist" }, @@ -33,12 +35,7 @@ "@vjs-10/icons": "workspace:*" }, "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.0", - "@rollup/plugin-node-resolve": "^15.0.0", - "@rollup/plugin-typescript": "^11.0.0", - "rollup": "^4.0.0", - "tslib": "^2.6.0", - "tsup": "^8.5.0", + "tsdown": "^0.15.4", "typescript": "^5.9.2" }, "publishConfig": { diff --git a/packages/html/html-icons/rollup.config.js b/packages/html/html-icons/rollup.config.js deleted file mode 100644 index d4d9cbf8..00000000 --- a/packages/html/html-icons/rollup.config.js +++ /dev/null @@ -1,68 +0,0 @@ -const typescript = require('@rollup/plugin-typescript'); -const resolve = require('@rollup/plugin-node-resolve'); -const commonjs = require('@rollup/plugin-commonjs'); - -module.exports = [ - // ESM build - { - input: 'src/index.ts', - output: { - file: 'dist/index.mjs', - format: 'esm', - sourcemap: true, - }, - watch: { - clearScreen: false, - }, - external: (id) => { - // Don't externalize relative imports (starts with . or /) - if (id.startsWith('.') || id.startsWith('/')) return false; - // Don't externalize absolute paths (local files) - if (id.includes('/') && !id.startsWith('@')) return false; - // Externalize all npm packages (including scoped ones) - return true; - }, - plugins: [ - resolve({ - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }), - commonjs(), - typescript({ - tsconfig: 'tsconfig.json', - declaration: false, - outDir: 'dist', - }), - ], - }, - // CommonJS build - { - input: 'src/index.ts', - output: { - file: 'dist/index.js', - format: 'cjs', - sourcemap: true, - }, - watch: { - clearScreen: false, - }, - external: (id) => { - // Don't externalize relative imports (starts with . or /) - if (id.startsWith('.') || id.startsWith('/')) return false; - // Don't externalize absolute paths (local files) - if (id.includes('/') && !id.startsWith('@')) return false; - // Externalize all npm packages (including scoped ones) - return true; - }, - plugins: [ - resolve({ - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }), - commonjs(), - typescript({ - tsconfig: 'tsconfig.json', - declaration: false, - outDir: 'dist', - }), - ], - }, -]; diff --git a/packages/html/html-icons/src/media-chrome-icon.ts b/packages/html/html-icons/src/media-chrome-icon.ts index a141c18c..f9a5c284 100644 --- a/packages/html/html-icons/src/media-chrome-icon.ts +++ b/packages/html/html-icons/src/media-chrome-icon.ts @@ -13,7 +13,7 @@ export function getTemplateHTML() { export class MediaChromeIcon extends HTMLElement { static shadowRootOptions = { mode: 'open' as ShadowRootMode }; - static getTemplateHTML = getTemplateHTML; + static getTemplateHTML: () => string = getTemplateHTML; constructor() { super(); diff --git a/packages/html/html-icons/src/media-fullscreen-enter-icon.ts b/packages/html/html-icons/src/media-fullscreen-enter-icon.ts index da147c15..83124a2a 100644 --- a/packages/html/html-icons/src/media-fullscreen-enter-icon.ts +++ b/packages/html/html-icons/src/media-fullscreen-enter-icon.ts @@ -15,7 +15,7 @@ export function getTemplateHTML() { } export class MediaFullscreenEnterIcon extends MediaChromeIcon { - static getTemplateHTML = getTemplateHTML; + static getTemplateHTML: () => string = getTemplateHTML; } customElements.define('media-fullscreen-enter-icon', MediaFullscreenEnterIcon); diff --git a/packages/html/html-icons/src/media-fullscreen-exit-icon.ts b/packages/html/html-icons/src/media-fullscreen-exit-icon.ts index 1f4a737e..a15b8589 100644 --- a/packages/html/html-icons/src/media-fullscreen-exit-icon.ts +++ b/packages/html/html-icons/src/media-fullscreen-exit-icon.ts @@ -15,7 +15,7 @@ export function getTemplateHTML() { } export class MediaFullscreenExitIcon extends MediaChromeIcon { - static getTemplateHTML = getTemplateHTML; + static getTemplateHTML: () => string = getTemplateHTML; } customElements.define('media-fullscreen-exit-icon', MediaFullscreenExitIcon); diff --git a/packages/html/html-icons/src/media-pause-icon.ts b/packages/html/html-icons/src/media-pause-icon.ts index 0d6776a8..07ff5999 100644 --- a/packages/html/html-icons/src/media-pause-icon.ts +++ b/packages/html/html-icons/src/media-pause-icon.ts @@ -10,7 +10,7 @@ export function getTemplateHTML() { } export class MediaPauseIcon extends MediaChromeIcon { - static getTemplateHTML = getTemplateHTML; + static getTemplateHTML: () => string = getTemplateHTML; } customElements.define('media-pause-icon', MediaPauseIcon); diff --git a/packages/html/html-icons/src/media-play-icon.ts b/packages/html/html-icons/src/media-play-icon.ts index 4dae0b8b..23d7a75e 100644 --- a/packages/html/html-icons/src/media-play-icon.ts +++ b/packages/html/html-icons/src/media-play-icon.ts @@ -15,7 +15,7 @@ export function getTemplateHTML() { } export class MediaPlayIcon extends MediaChromeIcon { - static getTemplateHTML = getTemplateHTML; + static getTemplateHTML: () => string = getTemplateHTML; } customElements.define('media-play-icon', MediaPlayIcon); diff --git a/packages/html/html-icons/src/media-volume-high-icon.ts b/packages/html/html-icons/src/media-volume-high-icon.ts index 032c6158..cb983527 100644 --- a/packages/html/html-icons/src/media-volume-high-icon.ts +++ b/packages/html/html-icons/src/media-volume-high-icon.ts @@ -15,7 +15,7 @@ export function getTemplateHTML() { } export class MediaVolumeHighIcon extends MediaChromeIcon { - static getTemplateHTML = getTemplateHTML; + static getTemplateHTML: () => string = getTemplateHTML; } customElements.define('media-volume-high-icon', MediaVolumeHighIcon); diff --git a/packages/html/html-icons/src/media-volume-low-icon.ts b/packages/html/html-icons/src/media-volume-low-icon.ts index 1814aa1a..5fa879ec 100644 --- a/packages/html/html-icons/src/media-volume-low-icon.ts +++ b/packages/html/html-icons/src/media-volume-low-icon.ts @@ -15,7 +15,7 @@ export function getTemplateHTML() { } export class MediaVolumeLowIcon extends MediaChromeIcon { - static getTemplateHTML = getTemplateHTML; + static getTemplateHTML: () => string = getTemplateHTML; } customElements.define('media-volume-low-icon', MediaVolumeLowIcon); diff --git a/packages/html/html-icons/src/media-volume-off-icon.ts b/packages/html/html-icons/src/media-volume-off-icon.ts index f6a05d1f..cea78215 100644 --- a/packages/html/html-icons/src/media-volume-off-icon.ts +++ b/packages/html/html-icons/src/media-volume-off-icon.ts @@ -15,7 +15,7 @@ export function getTemplateHTML() { } export class MediaVolumeOffIcon extends MediaChromeIcon { - static getTemplateHTML = getTemplateHTML; + static getTemplateHTML: () => string = getTemplateHTML; } customElements.define('media-volume-off-icon', MediaVolumeOffIcon); diff --git a/packages/html/html-icons/tsconfig.build.json b/packages/html/html-icons/tsconfig.build.json index 6c809265..b90fc83e 100644 --- a/packages/html/html-icons/tsconfig.build.json +++ b/packages/html/html-icons/tsconfig.build.json @@ -1,13 +1,4 @@ { "extends": "./tsconfig.json", - "compilerOptions": { - "declaration": true, - "declarationDir": "dist", - "emitDeclarationOnly": true, - "outDir": "dist", - "skipLibCheck": true, - "composite": false, - "incremental": false - }, - "exclude": ["dist", "node_modules"] + "include": ["src"] } diff --git a/packages/html/html-icons/tsconfig.json b/packages/html/html-icons/tsconfig.json index 9d54d911..c4d7be0c 100644 --- a/packages/html/html-icons/tsconfig.json +++ b/packages/html/html-icons/tsconfig.json @@ -1,9 +1,10 @@ { "extends": "../../../tsconfig.base.json", "compilerOptions": { - "outDir": "./dist", - "rootDir": "./src" + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } }, - "include": ["src/**/*"], - "exclude": ["dist", "node_modules"] + "include": ["src"] } diff --git a/packages/html/html-icons/tsdown.config.ts b/packages/html/html-icons/tsdown.config.ts new file mode 100644 index 00000000..652da4c4 --- /dev/null +++ b/packages/html/html-icons/tsdown.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'tsdown'; + +export default defineConfig({ + entry: 'src/index.ts', + platform: 'browser', + format: 'es', + sourcemap: true, + clean: true, + dts: { + oxc: true, + }, + loaders: { + '.svg': 'text', + }, +}); diff --git a/packages/html/html-media-elements/package.json b/packages/html/html-media-elements/package.json index 1d6657d0..dc8c292c 100644 --- a/packages/html/html-media-elements/package.json +++ b/packages/html/html-media-elements/package.json @@ -1,22 +1,24 @@ { "name": "@vjs-10/html-media-elements", + "type": "module", "version": "0.1.0", - "description": "HTML/DOM-specific media element components and utilities", + "description": "HTML media element components and utilities", "main": "dist/index.js", - "module": "dist/index.mjs", + "module": "dist/index.js", "types": "dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" + "default": "./dist/index.js" } }, "files": [ "dist" ], "scripts": { - "build": "tsup", + "build": "tsdown", + "build:watch": "tsdown --watch --silent", + "dev": "pnpm run build:watch", "test": "echo \"No tests yet\"", "clean": "rm -rf dist" }, @@ -34,7 +36,7 @@ "@vjs-10/media-store": "workspace:*" }, "devDependencies": { - "tsup": "^8.5.0", + "tsdown": "^0.15.4", "typescript": "^5.9.2" }, "publishConfig": { diff --git a/packages/html/html-media-elements/src/media-provider.ts b/packages/html/html-media-elements/src/media-provider.ts index 7f802774..90ad8dc6 100644 --- a/packages/html/html-media-elements/src/media-provider.ts +++ b/packages/html/html-media-elements/src/media-provider.ts @@ -1,12 +1,18 @@ +import type { Constructor, CustomElement } from '@open-wc/context-protocol'; +import type { MediaStore } from '@vjs-10/media-store'; + import { ProviderMixin } from '@open-wc/context-protocol'; import { createMediaStore } from '@vjs-10/media-store'; -export class MediaProvider extends ProviderMixin(HTMLElement) { +const ProviderHTMLElement: Constructor = ProviderMixin(HTMLElement); + +export class MediaProvider extends ProviderHTMLElement { contexts = { - mediaStore: () => { + mediaStore: (): MediaStore => { return createMediaStore(); }, }; } +// @ts-expect-error - fix types after (Rahim) customElements.define('media-provider', MediaProvider); diff --git a/packages/html/html-media-elements/tsconfig.build.json b/packages/html/html-media-elements/tsconfig.build.json new file mode 100644 index 00000000..b90fc83e --- /dev/null +++ b/packages/html/html-media-elements/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["src"] +} diff --git a/packages/html/html-media-elements/tsconfig.json b/packages/html/html-media-elements/tsconfig.json index 9d54d911..c4d7be0c 100644 --- a/packages/html/html-media-elements/tsconfig.json +++ b/packages/html/html-media-elements/tsconfig.json @@ -1,9 +1,10 @@ { "extends": "../../../tsconfig.base.json", "compilerOptions": { - "outDir": "./dist", - "rootDir": "./src" + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } }, - "include": ["src/**/*"], - "exclude": ["dist", "node_modules"] + "include": ["src"] } diff --git a/packages/html/html-media-elements/tsdown.config.ts b/packages/html/html-media-elements/tsdown.config.ts new file mode 100644 index 00000000..3b3cc13d --- /dev/null +++ b/packages/html/html-media-elements/tsdown.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'tsdown'; + +export default defineConfig({ + entry: 'src/index.ts', + platform: 'browser', + format: 'es', + sourcemap: true, + clean: true, + dts: { + oxc: true, + }, +}); diff --git a/packages/html/html-media-elements/tsup.config.ts b/packages/html/html-media-elements/tsup.config.ts deleted file mode 100644 index a4bebd83..00000000 --- a/packages/html/html-media-elements/tsup.config.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { defineConfig } from 'tsup'; - -export default defineConfig({ - entry: ['src/index.ts'], - format: ['cjs', 'esm'], - clean: true, - sourcemap: true, - outDir: 'dist', - external: [ - // Keep all dependencies external for library builds - /^@vjs-10\//, - /^[^.]/, - ], - // Generate TypeScript declarations with custom config - dts: { - compilerOptions: { - composite: false, - incremental: false, - }, - }, -}); diff --git a/packages/html/html-media-store/package.json b/packages/html/html-media-store/package.json index 705bba2b..a9d5dda6 100644 --- a/packages/html/html-media-store/package.json +++ b/packages/html/html-media-store/package.json @@ -1,22 +1,24 @@ { "name": "@vjs-10/html-media-store", + "type": "module", "version": "0.1.0", - "description": "HTML/DOM-specific media store integration and components", + "description": "HTML media store integration", "main": "dist/index.js", - "module": "dist/index.mjs", + "module": "dist/index.js", "types": "dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" + "default": "./dist/index.js" } }, "files": [ "dist" ], "scripts": { - "build": "tsup", + "build": "tsdown", + "build:watch": "tsdown --watch --silent", + "dev": "pnpm run build:watch", "test": "echo \"No tests yet\"", "clean": "rm -rf dist" }, @@ -33,7 +35,7 @@ "@vjs-10/media-store": "workspace:*" }, "devDependencies": { - "tsup": "^8.5.0", + "tsdown": "^0.15.4", "typescript": "^5.9.2" }, "publishConfig": { diff --git a/packages/html/html-media-store/tsconfig.build.json b/packages/html/html-media-store/tsconfig.build.json new file mode 100644 index 00000000..b90fc83e --- /dev/null +++ b/packages/html/html-media-store/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["src"] +} diff --git a/packages/html/html-media-store/tsconfig.json b/packages/html/html-media-store/tsconfig.json index 9d54d911..c4d7be0c 100644 --- a/packages/html/html-media-store/tsconfig.json +++ b/packages/html/html-media-store/tsconfig.json @@ -1,9 +1,10 @@ { "extends": "../../../tsconfig.base.json", "compilerOptions": { - "outDir": "./dist", - "rootDir": "./src" + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } }, - "include": ["src/**/*"], - "exclude": ["dist", "node_modules"] + "include": ["src"] } diff --git a/packages/html/html-media-store/tsdown.config.ts b/packages/html/html-media-store/tsdown.config.ts new file mode 100644 index 00000000..3b3cc13d --- /dev/null +++ b/packages/html/html-media-store/tsdown.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'tsdown'; + +export default defineConfig({ + entry: 'src/index.ts', + platform: 'browser', + format: 'es', + sourcemap: true, + clean: true, + dts: { + oxc: true, + }, +}); diff --git a/packages/html/html-media-store/tsup.config.ts b/packages/html/html-media-store/tsup.config.ts deleted file mode 100644 index a4bebd83..00000000 --- a/packages/html/html-media-store/tsup.config.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { defineConfig } from 'tsup'; - -export default defineConfig({ - entry: ['src/index.ts'], - format: ['cjs', 'esm'], - clean: true, - sourcemap: true, - outDir: 'dist', - external: [ - // Keep all dependencies external for library builds - /^@vjs-10\//, - /^[^.]/, - ], - // Generate TypeScript declarations with custom config - dts: { - compilerOptions: { - composite: false, - incremental: false, - }, - }, -}); diff --git a/packages/html/html/package.json b/packages/html/html/package.json index 21fe5d25..7d98fc87 100644 --- a/packages/html/html/package.json +++ b/packages/html/html/package.json @@ -1,23 +1,24 @@ { "name": "@vjs-10/html", + "type": "module", "version": "0.1.0", - "description": "Core UI components for building media player UIs. Also an import + export of various other HTML packages for convenience and discoverability.", + "description": "HTML library for building media players", "main": "dist/index.js", - "module": "dist/index.mjs", + "module": "dist/index.js", "types": "dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" + "default": "./dist/index.js" } }, "files": [ "dist" ], "scripts": { - "build": "rollup -c && tsc --project tsconfig.build.json", - "dev": "rollup -c -w", + "build": "tsdown", + "build:watch": "tsdown --watch --silent", + "dev": "pnpm run build:watch", "test": "echo \"No tests yet\"", "clean": "rm -rf dist" }, @@ -37,12 +38,7 @@ "@vjs-10/media-store": "workspace:*" }, "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.0", - "@rollup/plugin-node-resolve": "^15.0.0", - "@rollup/plugin-typescript": "^11.0.0", - "rollup": "^4.0.0", - "tslib": "^2.6.0", - "tsup": "^8.5.0", + "tsdown": "^0.15.4", "typescript": "^5.9.2" }, "publishConfig": { diff --git a/packages/html/html/rollup.config.js b/packages/html/html/rollup.config.js deleted file mode 100644 index d4d9cbf8..00000000 --- a/packages/html/html/rollup.config.js +++ /dev/null @@ -1,68 +0,0 @@ -const typescript = require('@rollup/plugin-typescript'); -const resolve = require('@rollup/plugin-node-resolve'); -const commonjs = require('@rollup/plugin-commonjs'); - -module.exports = [ - // ESM build - { - input: 'src/index.ts', - output: { - file: 'dist/index.mjs', - format: 'esm', - sourcemap: true, - }, - watch: { - clearScreen: false, - }, - external: (id) => { - // Don't externalize relative imports (starts with . or /) - if (id.startsWith('.') || id.startsWith('/')) return false; - // Don't externalize absolute paths (local files) - if (id.includes('/') && !id.startsWith('@')) return false; - // Externalize all npm packages (including scoped ones) - return true; - }, - plugins: [ - resolve({ - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }), - commonjs(), - typescript({ - tsconfig: 'tsconfig.json', - declaration: false, - outDir: 'dist', - }), - ], - }, - // CommonJS build - { - input: 'src/index.ts', - output: { - file: 'dist/index.js', - format: 'cjs', - sourcemap: true, - }, - watch: { - clearScreen: false, - }, - external: (id) => { - // Don't externalize relative imports (starts with . or /) - if (id.startsWith('.') || id.startsWith('/')) return false; - // Don't externalize absolute paths (local files) - if (id.includes('/') && !id.startsWith('@')) return false; - // Externalize all npm packages (including scoped ones) - return true; - }, - plugins: [ - resolve({ - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }), - commonjs(), - typescript({ - tsconfig: 'tsconfig.json', - declaration: false, - outDir: 'dist', - }), - ], - }, -]; diff --git a/packages/html/html/src/components/media-chrome-button.ts b/packages/html/html/src/components/media-chrome-button.ts index a83fac23..be9175c7 100644 --- a/packages/html/html/src/components/media-chrome-button.ts +++ b/packages/html/html/src/components/media-chrome-button.ts @@ -4,7 +4,7 @@ export function getTemplateHTML( this: typeof MediaChromeButton, _attrs: Record, _props: Record = {} -) { +): string { return /* html */ `