diff --git a/site/scripts/api-docs-builder/src/index.ts b/site/scripts/api-docs-builder/src/index.ts index eb4a0d3a..a0d39062 100644 --- a/site/scripts/api-docs-builder/src/index.ts +++ b/site/scripts/api-docs-builder/src/index.ts @@ -1,6 +1,5 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; -import { kebabCase } from 'es-toolkit/string'; import * as ts from 'typescript'; import * as tae from 'typescript-api-extractor'; import { extractCore } from './core-handler.js'; @@ -21,6 +20,11 @@ import { } from './types.js'; import { kebabToPascal, partKebabFromSource, sortProps } from './utils.js'; +// Components whose PascalCase name doesn't match simple kebab-to-pascal conversion. +const NAME_OVERRIDES: Record = { + 'pip-button': 'PiPButton', +}; + function buildProps(coreData: CoreExtraction): Record { const props: Record = {}; for (const prop of coreData.props) { @@ -95,7 +99,7 @@ function discoverComponents(): ComponentSource[] { for (const dir of dirs) { if (!dir.isDirectory()) continue; - const componentName = kebabToPascal(dir.name); + const componentName = NAME_OVERRIDES[dir.name] ?? kebabToPascal(dir.name); const componentDir = path.join(CORE_UI_PATH, dir.name); // Look for core file @@ -107,6 +111,7 @@ function discoverComponents(): ComponentSource[] { const source: ComponentSource = { name: componentName, + kebab: dir.name, }; if (fs.existsSync(coreFile)) { @@ -151,8 +156,7 @@ function createProgram(sources: ComponentSource[]): ts.Program { // For multi-part components, include all element files from the HTML directory // and React source files for JSDoc description extraction if (source.partsIndexPath) { - const componentKebab = kebabCase(source.name); - const htmlDir = path.join(HTML_UI_PATH, componentKebab); + const htmlDir = path.join(HTML_UI_PATH, source.kebab); if (fs.existsSync(htmlDir)) { const elementFiles = fs.readdirSync(htmlDir).filter((f) => f.endsWith('-element.ts')); for (const file of elementFiles) { @@ -241,7 +245,7 @@ function discoverParts(source: ComponentSource, program: ts.Program): PartSource const partExports = extractParts(source.partsIndexPath, program); if (partExports.length === 0) return []; - const componentKebab = kebabCase(source.name); + const componentKebab = source.kebab; const htmlDir = path.join(HTML_UI_PATH, componentKebab); const parts: PartSource[] = []; @@ -448,7 +452,7 @@ function main() { } // Write JSON file - const outputFile = path.join(OUTPUT_PATH, `${kebabCase(source.name)}.json`); + const outputFile = path.join(OUTPUT_PATH, `${source.kebab}.json`); const json = `${JSON.stringify(validated.data, null, 2)}\n`; fs.writeFileSync(outputFile, json); diff --git a/site/scripts/api-docs-builder/src/types.ts b/site/scripts/api-docs-builder/src/types.ts index be163d89..02c6c004 100644 --- a/site/scripts/api-docs-builder/src/types.ts +++ b/site/scripts/api-docs-builder/src/types.ts @@ -36,6 +36,8 @@ export interface PartSource { export interface ComponentSource { /** PascalCase component name (e.g., PlayButton) */ name: string; + /** Original kebab-case directory name (e.g., play-button). */ + kebab: string; /** Path to core file (e.g., packages/core/src/core/ui/play-button/play-button-core.ts) */ corePath?: string; /** Path to data attrs file */ diff --git a/site/src/components/docs/demos/pip-button/html/css/BasicUsage.astro b/site/src/components/docs/demos/pip-button/html/css/BasicUsage.astro new file mode 100644 index 00000000..e7e95f49 --- /dev/null +++ b/site/src/components/docs/demos/pip-button/html/css/BasicUsage.astro @@ -0,0 +1,10 @@ +--- +import HtmlDemo from '@/components/docs/demos/HtmlDemo.astro'; +import html from './BasicUsage.html?raw'; +import './BasicUsage.css'; +--- + + + diff --git a/site/src/components/docs/demos/pip-button/html/css/BasicUsage.css b/site/src/components/docs/demos/pip-button/html/css/BasicUsage.css new file mode 100644 index 00000000..d4f8539d --- /dev/null +++ b/site/src/components/docs/demos/pip-button/html/css/BasicUsage.css @@ -0,0 +1,35 @@ +.pip-button-basic { + display: block; + position: relative; +} + +.pip-button-basic video { + width: 100%; +} + +.pip-button-basic__button { + padding-block: 8px; + position: absolute; + bottom: 10px; + right: 10px; + background: rgba(255, 255, 255, 0.7); + backdrop-filter: blur(10px); + color: black; + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: 9999px; + padding-inline: 20px; + cursor: pointer; +} + +.pip-button-basic__button .show-when-pip { + display: none; +} +.pip-button-basic__button .show-when-not-pip { + display: none; +} +.pip-button-basic__button[data-pip] .show-when-pip { + display: inline; +} +.pip-button-basic__button:not([data-pip]) .show-when-not-pip { + display: inline; +} diff --git a/site/src/components/docs/demos/pip-button/html/css/BasicUsage.html b/site/src/components/docs/demos/pip-button/html/css/BasicUsage.html new file mode 100644 index 00000000..f43a08de --- /dev/null +++ b/site/src/components/docs/demos/pip-button/html/css/BasicUsage.html @@ -0,0 +1,13 @@ + + + + Exit PiP + Enter PiP + + diff --git a/site/src/components/docs/demos/pip-button/html/css/BasicUsage.ts b/site/src/components/docs/demos/pip-button/html/css/BasicUsage.ts new file mode 100644 index 00000000..978c2338 --- /dev/null +++ b/site/src/components/docs/demos/pip-button/html/css/BasicUsage.ts @@ -0,0 +1,2 @@ +import '@videojs/html/video/player'; +import '@videojs/html/ui/pip-button'; diff --git a/site/src/components/docs/demos/pip-button/react/css/BasicUsage.css b/site/src/components/docs/demos/pip-button/react/css/BasicUsage.css new file mode 100644 index 00000000..fd56f54f --- /dev/null +++ b/site/src/components/docs/demos/pip-button/react/css/BasicUsage.css @@ -0,0 +1,21 @@ +.pip-button-basic { + position: relative; +} + +.pip-button-basic video { + width: 100%; +} + +.pip-button-basic__button { + padding-block: 8px; + position: absolute; + bottom: 10px; + right: 10px; + background: rgba(255, 255, 255, 0.7); + backdrop-filter: blur(10px); + color: black; + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: 9999px; + padding-inline: 20px; + cursor: pointer; +} diff --git a/site/src/components/docs/demos/pip-button/react/css/BasicUsage.tsx b/site/src/components/docs/demos/pip-button/react/css/BasicUsage.tsx new file mode 100644 index 00000000..cf85e187 --- /dev/null +++ b/site/src/components/docs/demos/pip-button/react/css/BasicUsage.tsx @@ -0,0 +1,25 @@ +import { createPlayer, features, PiPButton, Video } from '@videojs/react'; + +import './BasicUsage.css'; + +const Player = createPlayer({ features: [...features.video] }); + +export default function BasicUsage() { + return ( + + + + + ); +} diff --git a/site/src/content/docs/reference/pip-button.mdx b/site/src/content/docs/reference/pip-button.mdx new file mode 100644 index 00000000..74312531 --- /dev/null +++ b/site/src/content/docs/reference/pip-button.mdx @@ -0,0 +1,65 @@ +--- +title: PiPButton +frameworkTitle: + html: media-pip-button +description: A button component for entering and exiting picture-in-picture mode +--- + +import ApiReference from "@/components/docs/api-reference/ApiReference.astro"; +import FrameworkCase from "@/components/docs/FrameworkCase.astro"; +import StyleCase from "@/components/docs/StyleCase.astro"; +import Demo from "@/components/docs/demos/Demo.astro"; + +{/* React demos */} +import BasicUsageDemoReact from "@/components/docs/demos/pip-button/react/css/BasicUsage"; +import basicUsageReactTsx from "@/components/docs/demos/pip-button/react/css/BasicUsage.tsx?raw"; +import basicUsageReactCss from "@/components/docs/demos/pip-button/react/css/BasicUsage.css?raw"; + +{/* HTML demos */} +import BasicUsageDemoHtml from "@/components/docs/demos/pip-button/html/css/BasicUsage.astro"; +import basicUsageHtml from "@/components/docs/demos/pip-button/html/css/BasicUsage.html?raw"; +import basicUsageHtmlCss from "@/components/docs/demos/pip-button/html/css/BasicUsage.css?raw"; +import basicUsageHtmlTs from "@/components/docs/demos/pip-button/html/css/BasicUsage.ts?raw"; + +## Anatomy + + +```tsx + +``` + + + +```html + +``` + + +## Examples + +### Basic Usage + + + + + + + + + + + + + + + + + + diff --git a/site/src/docs.config.ts b/site/src/docs.config.ts index 19b6f977..972ebec4 100644 --- a/site/src/docs.config.ts +++ b/site/src/docs.config.ts @@ -28,6 +28,7 @@ export const sidebar: Sidebar = [ { slug: 'reference/controls' }, { slug: 'reference/fullscreen-button' }, { slug: 'reference/mute-button' }, + { slug: 'reference/pip-button' }, { slug: 'reference/play-button' }, { slug: 'reference/poster' }, { slug: 'reference/time' },