@videojs/html 10.0.0 → 10.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/dist/default/define/media/dash-video.js +1 -1
  2. package/dist/default/define/media/hls-video.js +1 -1
  3. package/dist/default/define/media/hlsjs-video.js +1 -1
  4. package/dist/default/define/media/native-hls-video.js +1 -1
  5. package/dist/default/extensions/mux-data/extension.js +1 -1
  6. package/dist/default/ui/thumbnail/element.js +2 -2
  7. package/dist/default/version.js +1 -1
  8. package/dist/dev/define/audio/compat-skin2.js.map +1 -1
  9. package/dist/dev/define/audio/neutral-skin2.js.map +1 -1
  10. package/dist/dev/define/audio/skin2.js.map +1 -1
  11. package/dist/dev/define/live-audio/compat-skin2.js.map +1 -1
  12. package/dist/dev/define/live-audio/skin2.js.map +1 -1
  13. package/dist/dev/define/live-video/neutral-skin2.js.map +1 -1
  14. package/dist/dev/define/live-video/skin2.js.map +1 -1
  15. package/dist/dev/define/media/dash-video.d.ts +1 -1
  16. package/dist/dev/define/media/dash-video.js +1 -1
  17. package/dist/dev/define/media/dash-video.js.map +1 -1
  18. package/dist/dev/define/media/hls-video.d.ts +1 -1
  19. package/dist/dev/define/media/hls-video.js +1 -1
  20. package/dist/dev/define/media/hls-video.js.map +1 -1
  21. package/dist/dev/define/media/hlsjs-video.d.ts +1 -1
  22. package/dist/dev/define/media/hlsjs-video.js +1 -1
  23. package/dist/dev/define/media/hlsjs-video.js.map +1 -1
  24. package/dist/dev/define/media/native-hls-video.d.ts +1 -1
  25. package/dist/dev/define/media/native-hls-video.js +1 -1
  26. package/dist/dev/define/media/native-hls-video.js.map +1 -1
  27. package/dist/dev/define/video/compat-skin2.js.map +1 -1
  28. package/dist/dev/define/video/skin2.js.map +1 -1
  29. package/dist/dev/extensions/mux-data/extension.d.ts +1 -1
  30. package/dist/dev/extensions/mux-data/extension.js +1 -1
  31. package/dist/dev/extensions/mux-data/extension.js.map +1 -1
  32. package/dist/dev/ui/thumbnail/element.js +2 -2
  33. package/dist/dev/ui/thumbnail/element.js.map +1 -1
  34. package/dist/dev/version.js +1 -1
  35. package/docs/README.md +1 -1
  36. package/docs/guides/architecture.md +3 -3
  37. package/docs/guides/autoplay.md +3 -3
  38. package/docs/guides/captions.md +5 -5
  39. package/docs/guides/casting.md +5 -5
  40. package/docs/guides/cdn.md +11 -11
  41. package/docs/guides/customize-skins.md +2 -2
  42. package/docs/guides/features.md +1 -1
  43. package/docs/guides/fullscreen.md +1 -1
  44. package/docs/guides/installation-cdn.md +2 -2
  45. package/docs/guides/installation-shadcn.md +4 -4
  46. package/docs/guides/installation-svelte.md +2 -2
  47. package/docs/guides/installation-vue.md +2 -2
  48. package/docs/guides/installation.md +2 -2
  49. package/docs/guides/internationalization.md +5 -5
  50. package/docs/guides/live-streams.md +3 -3
  51. package/docs/guides/llms.txt +4 -3
  52. package/docs/guides/media-sources.md +2 -2
  53. package/docs/guides/migrate-from-media-chrome.md +4 -4
  54. package/docs/guides/migrate-from-mux-player.md +7 -7
  55. package/docs/guides/migrate-from-plyr.md +8 -8
  56. package/docs/guides/migrate-from-video-js-8.md +9 -9
  57. package/docs/guides/migrate-from-vidstack.md +9 -9
  58. package/docs/guides/migrate.md +17 -0
  59. package/docs/guides/mux-data.md +1 -1
  60. package/docs/guides/playback-errors.md +4 -4
  61. package/docs/guides/presets.md +13 -13
  62. package/docs/guides/quality.md +3 -3
  63. package/docs/guides/self-hosting.md +6 -6
  64. package/docs/guides/skins.md +5 -5
  65. package/docs/guides/thumbnails.md +2 -2
  66. package/docs/guides/user-preferences.md +2 -2
  67. package/docs/llms.txt +4 -3
  68. package/docs/reference/api/feature-fullscreen.md +2 -2
  69. package/docs/reference/api/feature-metadata.md +2 -2
  70. package/docs/reference/api/feature-source.md +1 -1
  71. package/docs/reference/api/feature-text-tracks.md +2 -2
  72. package/docs/reference/api/llms.txt +1 -1
  73. package/docs/reference/api/media-capabilities.md +1 -1
  74. package/docs/reference/api/player-store.md +3 -3
  75. package/docs/reference/api/preset-audio.md +2 -2
  76. package/docs/reference/api/preset-background.md +3 -3
  77. package/docs/reference/api/preset-live-audio.md +3 -3
  78. package/docs/reference/api/preset-live-video.md +3 -3
  79. package/docs/reference/api/preset-video.md +2 -2
  80. package/docs/reference/api/resolve-adapter-type.md +2 -2
  81. package/docs/reference/api/vjs8-legacy-options.md +1 -1
  82. package/docs/reference/components/audio-compat-skin.md +33 -3
  83. package/docs/reference/components/audio-neutral-skin.md +34 -4
  84. package/docs/reference/components/audio-skin.md +34 -4
  85. package/docs/reference/components/audio.md +1 -1
  86. package/docs/reference/components/background-video-skin.md +36 -4
  87. package/docs/reference/components/background-video.md +1 -1
  88. package/docs/reference/components/cast-button.md +1 -1
  89. package/docs/reference/components/cloudflare-video.md +1 -1
  90. package/docs/reference/components/dash-video.md +1 -1
  91. package/docs/reference/components/google-cast.md +1 -1
  92. package/docs/reference/components/hls-audio.md +1 -1
  93. package/docs/reference/components/hls-background-video.md +1 -1
  94. package/docs/reference/components/hls-video.md +1 -1
  95. package/docs/reference/components/hlsjs-video.md +1 -1
  96. package/docs/reference/components/live-audio-compat-skin.md +35 -4
  97. package/docs/reference/components/live-audio-neutral-skin.md +36 -5
  98. package/docs/reference/components/live-audio-skin.md +36 -5
  99. package/docs/reference/components/live-video-compat-skin.md +36 -4
  100. package/docs/reference/components/live-video-neutral-skin.md +37 -5
  101. package/docs/reference/components/live-video-skin.md +37 -5
  102. package/docs/reference/components/llms.txt +1 -1
  103. package/docs/reference/components/mux-audio.md +2 -2
  104. package/docs/reference/components/mux-background-video.md +1 -1
  105. package/docs/reference/components/mux-data.md +1 -1
  106. package/docs/reference/components/mux-video.md +2 -2
  107. package/docs/reference/components/native-hls-video.md +1 -1
  108. package/docs/reference/components/player-container.md +1 -1
  109. package/docs/reference/components/player.md +4 -4
  110. package/docs/reference/components/shaka-video.md +1 -1
  111. package/docs/reference/components/spotify-audio.md +1 -1
  112. package/docs/reference/components/thumbnail.md +5 -5
  113. package/docs/reference/components/tiktok-video.md +1 -1
  114. package/docs/reference/components/twitch-video.md +1 -1
  115. package/docs/reference/components/video-compat-skin.md +36 -3
  116. package/docs/reference/components/video-neutral-skin.md +37 -4
  117. package/docs/reference/components/video-skin.md +37 -4
  118. package/docs/reference/components/video.md +1 -1
  119. package/docs/reference/components/vimeo-video.md +1 -1
  120. package/docs/reference/components/wistia-video.md +1 -1
  121. package/docs/reference/components/youtube-video.md +1 -1
  122. package/package.json +38 -40
@@ -1 +1 @@
1
- {"version":3,"file":"element.js","names":[],"sources":["../../../../src/ui/thumbnail/element.ts"],"sourcesContent":["import {\n mapCuesToThumbnails,\n ThumbnailCore,\n ThumbnailDataAttrs,\n type ThumbnailImage,\n type ThumbnailResizeResult,\n type ThumbnailImageProps,\n type ThumbnailProps,\n} from '@videojs/core';\nimport type { ThumbnailApi } from '@videojs/core/dom';\nimport { applyElementProps, applyStateDataAttrs, createThumbnail, selectTextTrack } from '@videojs/core/dom';\nimport type { PropertyDeclarationMap, PropertyValues } from '@videojs/element';\nimport type { MediaTextTrackState } from '@videojs/media';\nimport { findComposedElement, isHTMLImageElement, listen } from '@videojs/utils/dom';\n\nimport { playerContext } from '../../player/context';\nimport { PlayerController } from '../../player/controller';\nimport { UIElement } from '../ui-element';\n\nconst SHADOW_CSS = `\\\n:host {\n display: inline-block;\n overflow: hidden;\n}\nimg,\n::slotted(img) {\n display: block;\n}`;\n\n/**\n * Image attributes the element fills in from its own properties. Ones already on an image when it is adopted are the\n * author's and are left alone, so an `<img slot=\"thumbnail\" loading=\"lazy\">` keeps its settings inside a skin.\n */\nconst IMAGE_ATTRIBUTES = ['crossorigin', 'loading', 'fetchpriority'] as const;\n\ntype ImageAttribute = (typeof IMAGE_ATTRIBUTES)[number];\n\n/** The image the element draws when none is supplied, reachable from outside as `::part(image)`. */\nfunction createFallbackImage(): HTMLImageElement {\n const img = document.createElement('img');\n\n img.alt = '';\n img.setAttribute('part', 'image');\n img.setAttribute('aria-hidden', 'true');\n img.setAttribute('decoding', 'async');\n\n return img;\n}\n\n/**\n * `<media-thumbnail>` — resolves and sizes a time-based thumbnail into an image.\n *\n * The element owns `src` and `srcset` on the active image. Left empty, it draws an image of its own in its shadow root.\n * Supply an `<img>` child instead — `<media-thumbnail time=\"12\"><img alt=\"\"></media-thumbnail>` — to compose overlays\n * or loading indicators beside the image the element controls. Any `crossorigin`, `loading`, or `fetchpriority` the\n * child already carries wins over the element's own; the rest are filled in. Inside a skin, an `<img slot=\"thumbnail\">`\n * of yours replaces the one the skin carries.\n */\nexport class ThumbnailElement extends UIElement {\n static readonly tagName = 'media-thumbnail';\n\n static override properties = {\n time: { type: Number },\n crossOrigin: { type: String, attribute: 'crossorigin' },\n loading: { type: String },\n fetchPriority: { type: String, attribute: 'fetchpriority' },\n } satisfies PropertyDeclarationMap<Exclude<keyof (ThumbnailProps & ThumbnailImageProps), 'thumbnails'>>;\n\n time = 0;\n crossOrigin: (ThumbnailProps & ThumbnailImageProps)['crossOrigin'];\n loading: (ThumbnailProps & ThumbnailImageProps)['loading'];\n fetchPriority: (ThumbnailProps & ThumbnailImageProps)['fetchPriority'];\n\n readonly #core = new ThumbnailCore();\n readonly #shadow = this.attachShadow({ mode: 'open' });\n readonly #fallback = createFallbackImage();\n readonly #children = new MutationObserver(() => this.requestUpdate());\n // An image assigned through a forwarding slot lives outside this subtree, so its\n // attributes are watched on the image itself.\n readonly #imageAttributes = new MutationObserver(() => this.requestUpdate());\n readonly #textTracks = new PlayerController(this, playerContext, selectTextTrack);\n\n #slots: AbortController | null = null;\n #img: HTMLImageElement | null = null;\n /** Attributes `#img` already carried when adopted, which the author owns. */\n #authored = new Set<ImageAttribute>();\n #thumbnails: ThumbnailImage[] = [];\n #externalThumbnails: ThumbnailImage[] | undefined;\n #lastTextTrack: MediaTextTrackState | undefined;\n #api: ThumbnailApi | null = null;\n\n constructor() {\n super();\n\n const style = document.createElement('style');\n\n style.textContent = SHADOW_CSS;\n this.#shadow.append(style, document.createElement('slot'), this.#fallback);\n }\n\n /**\n * Set thumbnail images directly, bypassing the automatic `<track>` detection. When set, this takes priority over the\n * text track path.\n */\n get thumbnails(): ThumbnailImage[] | undefined {\n return this.#externalThumbnails;\n }\n\n set thumbnails(value: ThumbnailImage[] | undefined) {\n this.#externalThumbnails = value;\n this.requestUpdate();\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n\n if (this.destroyed) return;\n\n this.#api = createThumbnail({\n getContainer: () => this,\n getImg: () => this.#img,\n onStateChange: () => this.requestUpdate(),\n });\n this.#children.observe(this, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['src', 'srcset'],\n });\n\n // Nodes assigned to a forwarding slot are not children of this subtree, so an image slotted\n // in later never shows up as a mutation. The slot announces it with `slotchange` instead.\n this.#slots = new AbortController();\n listen(this, 'slotchange', () => this.requestUpdate(), { signal: this.#slots.signal });\n\n // Disconnecting let go of the image, and reconnecting alone schedules no update,\n // so a moved element adopts its image and reapplies the source here.\n this.requestUpdate();\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n\n this.#adopt(null);\n this.#children.disconnect();\n this.#slots?.abort();\n this.#slots = null;\n this.#api?.destroy();\n this.#api = null;\n }\n\n override destroyCallback(): void {\n this.#api?.destroy();\n super.destroyCallback();\n }\n\n protected override update(changed: PropertyValues): void {\n super.update(changed);\n\n const textTrack = this.#textTracks.value;\n\n // Resolve thumbnails: external prop takes priority over auto <track> path.\n if (this.#externalThumbnails) {\n this.#thumbnails = this.#externalThumbnails;\n } else if (textTrack !== this.#lastTextTrack) {\n this.#lastTextTrack = textTrack;\n const thumbnailsTrack = textTrack?.thumbnailsTrack;\n\n this.#thumbnails =\n thumbnailsTrack && thumbnailsTrack.cues.length > 0\n ? mapCuesToThumbnails(thumbnailsTrack.cues, thumbnailsTrack.src ?? undefined)\n : [];\n }\n\n const thumbnail = this.#core.findActiveThumbnail(this.#thumbnails, this.time);\n const img = findComposedElement(this, isHTMLImageElement) ?? this.#fallback;\n\n this.#adopt(img);\n this.#applyImageAttributes(img, textTrack);\n\n // Track src changes via the thumbnail API.\n this.#api?.updateSrc(thumbnail?.url);\n this.#applySource(thumbnail?.url);\n this.#api?.connect();\n\n if (!thumbnail) {\n this.#resetStyles();\n\n const state = this.#core.getState(false, false, undefined);\n\n applyElementProps(this, this.#core.getAttrs(state));\n applyStateDataAttrs(this, state, ThumbnailDataAttrs);\n return;\n }\n\n const api = this.#api;\n const state = this.#core.getState(api?.loading ?? false, api?.error ?? false, thumbnail);\n\n applyElementProps(this, this.#core.getAttrs(state));\n applyStateDataAttrs(this, state, ThumbnailDataAttrs);\n\n if (api?.naturalWidth && api.naturalHeight) {\n const constraints = api.readConstraints();\n const result = this.#core.resize(thumbnail, api.naturalWidth, api.naturalHeight, constraints);\n\n if (result) {\n this.#applyResize(result);\n }\n }\n }\n\n /**\n * Leaving `crossOrigin` unset means \"follow the media element\", so thumbnails keep working on a CORS-enabled player\n * without a skin having to thread an attribute through. Only the `<track>` path inherits: `thumbnails` set directly\n * may point at a host that has nothing to do with the media element.\n */\n #inheritedCrossOrigin(\n textTrack: MediaTextTrackState | undefined\n ): (ThumbnailProps & ThumbnailImageProps)['crossOrigin'] {\n return this.#externalThumbnails ? undefined : textTrack?.thumbnailsTrack?.crossOrigin;\n }\n\n /** Sync image attributes from element properties, leaving the ones the author put on the image alone. */\n #applyImageAttributes(img: HTMLImageElement, textTrack: MediaTextTrackState | undefined): void {\n const props: Partial<Record<ImageAttribute, string | undefined>> = {\n crossorigin: this.#core.resolveCrossOrigin(this.crossOrigin, this.#inheritedCrossOrigin(textTrack)),\n loading: this.loading,\n fetchpriority: this.fetchPriority,\n };\n\n for (const name of this.#authored) delete props[name];\n\n applyElementProps(img, props);\n }\n\n #applyResize(result: ThumbnailResizeResult): void {\n this.style.width = `${result.containerWidth}px`;\n this.style.height = `${result.containerHeight}px`;\n\n const imgStyle = this.#img?.style;\n if (!imgStyle) return;\n\n imgStyle.width = `${result.imageWidth}px`;\n imgStyle.height = `${result.imageHeight}px`;\n imgStyle.maxWidth = 'none';\n imgStyle.transform =\n result.offsetX || result.offsetY ? `translate(-${result.offsetX}px, -${result.offsetY}px)` : '';\n }\n\n #resetStyles(): void {\n this.style.width = '';\n this.style.height = '';\n\n const imgStyle = this.#img?.style;\n if (!imgStyle) return;\n\n imgStyle.width = '';\n imgStyle.height = '';\n imgStyle.maxWidth = '';\n imgStyle.transform = '';\n }\n\n #adopt(next: HTMLImageElement | null): void {\n if (next === this.#img) return;\n\n const previous = this.#img;\n\n if (previous) {\n this.#api?.disconnectImg(previous);\n this.#resetStyles();\n previous.removeAttribute('src');\n previous.removeAttribute('srcset');\n\n for (const name of IMAGE_ATTRIBUTES) {\n if (!this.#authored.has(name)) previous.removeAttribute(name);\n }\n }\n\n // Ownership is settled once, when an image becomes active: after the first\n // sync the attributes we set would themselves look authored.\n this.#img = next;\n this.#authored = new Set(next ? IMAGE_ATTRIBUTES.filter((name) => next.hasAttribute(name)) : []);\n this.#imageAttributes.disconnect();\n\n if (next && next !== this.#fallback) {\n this.#imageAttributes.observe(next, { attributes: true, attributeFilter: ['src', 'srcset'] });\n }\n\n // The fallback only occupies the shadow root while it is the active image,\n // so a supplied image never sits beside a hidden one.\n if (next === this.#fallback) this.#shadow.append(this.#fallback);\n else if (next) this.#fallback.remove();\n\n // Reset the request even when the next image will receive the same URL. A\n // replacement image is a new download with its own lifecycle.\n this.#api?.updateSrc(undefined);\n }\n\n #applySource(src: string | undefined): void {\n const img = this.#img;\n if (!img) return;\n\n // A srcset candidate wins over src, so the root has to clear both parts of\n // the source contract before applying the selected thumbnail URL.\n img.removeAttribute('srcset');\n\n if (!src) img.removeAttribute('src');\n else if (img.getAttribute('src') !== src) img.setAttribute('src', src);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"element.js","names":[],"sources":["../../../../src/ui/thumbnail/element.ts"],"sourcesContent":["import {\n mapCuesToThumbnails,\n ThumbnailCore,\n ThumbnailDataAttrs,\n type ThumbnailImage,\n type ThumbnailResizeResult,\n type ThumbnailImageProps,\n type ThumbnailProps,\n} from '@videojs/core';\nimport type { ThumbnailApi } from '@videojs/core/dom';\nimport { applyElementProps, applyStateDataAttrs, createThumbnail, selectTextTrack } from '@videojs/core/dom';\nimport type { PropertyDeclarationMap, PropertyValues } from '@videojs/element';\nimport type { MediaTextTrackState } from '@videojs/media';\nimport { findComposedElement, isHTMLImageElement, listen } from '@videojs/utils/dom';\n\nimport { playerContext } from '../../player/context';\nimport { PlayerController } from '../../player/controller';\nimport { UIElement } from '../ui-element';\n\nconst SHADOW_CSS = `\\\n:host {\n display: inline-block;\n overflow: hidden;\n}\nimg,\n::slotted(img) {\n display: block;\n}`;\n\n/**\n * Image attributes the element fills in from its own properties. Ones already on an image when it is adopted are the\n * author's and are left alone, so an `<img slot=\"thumbnail\" loading=\"lazy\">` keeps its settings inside a skin.\n */\nconst IMAGE_ATTRIBUTES = ['crossorigin', 'loading', 'fetchpriority'] as const;\n\ntype ImageAttribute = (typeof IMAGE_ATTRIBUTES)[number];\n\n/** The image the element draws when none is supplied, reachable from outside as `::part(image)`. */\nfunction createFallbackImage(): HTMLImageElement {\n const img = document.createElement('img');\n\n img.alt = '';\n img.setAttribute('part', 'image');\n img.setAttribute('aria-hidden', 'true');\n img.setAttribute('decoding', 'async');\n\n return img;\n}\n\n/**\n * `<media-thumbnail>` — resolves and sizes a time-based thumbnail into an image.\n *\n * The element owns `src` and `srcset` on the active image. Left empty, it draws an image of its own in its shadow root.\n * Supply an `<img>` child instead — `<media-thumbnail time=\"12\"><img alt=\"\"></media-thumbnail>` — to compose overlays\n * or loading indicators beside the image the element controls. Any `crossorigin`, `loading`, or `fetchpriority` the\n * child already carries wins over the element's own; the rest are filled in. Inside a skin, an `<img slot=\"thumbnail\">`\n * of yours replaces the one the skin carries.\n */\nexport class ThumbnailElement extends UIElement {\n static readonly tagName = 'media-thumbnail';\n\n static override properties = {\n time: { type: Number },\n crossOrigin: { type: String, attribute: 'crossorigin' },\n loading: { type: String },\n fetchPriority: { type: String, attribute: 'fetchpriority' },\n } satisfies PropertyDeclarationMap<Exclude<keyof (ThumbnailProps & ThumbnailImageProps), 'thumbnails'>>;\n\n time = 0;\n crossOrigin: (ThumbnailProps & ThumbnailImageProps)['crossOrigin'];\n loading: (ThumbnailProps & ThumbnailImageProps)['loading'];\n fetchPriority: (ThumbnailProps & ThumbnailImageProps)['fetchPriority'];\n\n readonly #core = new ThumbnailCore();\n readonly #shadow = this.attachShadow({ mode: 'open' });\n readonly #fallback = createFallbackImage();\n readonly #children = new MutationObserver(() => this.requestUpdate());\n // An image assigned through a forwarding slot lives outside this subtree, so its\n // attributes are watched on the image itself.\n readonly #imageAttributes = new MutationObserver(() => this.requestUpdate());\n readonly #textTracks = new PlayerController(this, playerContext, selectTextTrack);\n\n #slots: AbortController | null = null;\n #img: HTMLImageElement | null = null;\n /** Attributes `#img` already carried when adopted, which the author owns. */\n #authored = new Set<ImageAttribute>();\n #thumbnails: ThumbnailImage[] = [];\n #externalThumbnails: ThumbnailImage[] | undefined;\n #lastTextTrack: MediaTextTrackState | undefined;\n #api: ThumbnailApi | null = null;\n\n constructor() {\n super();\n\n const style = document.createElement('style');\n\n style.textContent = SHADOW_CSS;\n this.#shadow.append(style, document.createElement('slot'), this.#fallback);\n }\n\n /**\n * Set thumbnail images directly, bypassing the automatic `<track>` detection. When set, this takes priority over the\n * text track path.\n */\n get thumbnails(): ThumbnailImage[] | undefined {\n return this.#externalThumbnails;\n }\n\n set thumbnails(value: ThumbnailImage[] | undefined) {\n this.#externalThumbnails = value;\n this.requestUpdate();\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n\n if (this.destroyed) return;\n\n this.#api = createThumbnail({\n getContainer: () => this,\n getImg: () => this.#img,\n onStateChange: () => this.requestUpdate(),\n });\n this.#children.observe(this, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['src', 'srcset'],\n });\n\n // Nodes assigned to a forwarding slot are not children of this subtree, so an image slotted\n // in later never shows up as a mutation. The slot announces it with `slotchange` instead.\n this.#slots = new AbortController();\n listen(this, 'slotchange', () => this.requestUpdate(), { signal: this.#slots.signal });\n\n // Disconnecting let go of the image, and reconnecting alone schedules no update,\n // so a moved element adopts its image and reapplies the source here.\n this.requestUpdate();\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n\n this.#adopt(null);\n this.#children.disconnect();\n this.#slots?.abort();\n this.#slots = null;\n this.#api?.destroy();\n this.#api = null;\n }\n\n override destroyCallback(): void {\n this.#api?.destroy();\n super.destroyCallback();\n }\n\n protected override update(changed: PropertyValues): void {\n super.update(changed);\n\n const textTrack = this.#textTracks.value;\n\n // Resolve thumbnails: external prop takes priority over auto <track> path.\n if (this.#externalThumbnails) {\n this.#thumbnails = this.#externalThumbnails;\n } else if (textTrack !== this.#lastTextTrack) {\n this.#lastTextTrack = textTrack;\n const thumbnailsTrack = textTrack?.thumbnailsTrack;\n\n this.#thumbnails =\n thumbnailsTrack && thumbnailsTrack.cues.length > 0\n ? mapCuesToThumbnails(thumbnailsTrack.cues, thumbnailsTrack.src ?? undefined)\n : [];\n }\n\n const thumbnail = this.#core.findActiveThumbnail(this.#thumbnails, this.time);\n const img = findComposedElement(this, isHTMLImageElement) ?? this.#fallback;\n\n this.#adopt(img);\n this.#applyImageAttributes(img, textTrack);\n\n // Track src changes via the thumbnail API.\n this.#api?.updateSrc(thumbnail?.url);\n this.#applySource(thumbnail?.url);\n this.#api?.connect();\n\n if (!thumbnail) {\n this.#resetStyles();\n\n const state = this.#core.getState(false, false, undefined);\n\n applyElementProps(this, this.#core.getAttrs(state));\n applyStateDataAttrs(this, state, ThumbnailDataAttrs);\n return;\n }\n\n const api = this.#api;\n const state = this.#core.getState(api?.loading ?? false, api?.error ?? false, thumbnail);\n\n applyElementProps(this, this.#core.getAttrs(state));\n applyStateDataAttrs(this, state, ThumbnailDataAttrs);\n\n if (api?.naturalWidth && api.naturalHeight) {\n const constraints = api.readConstraints();\n const result = this.#core.resize(thumbnail, api.naturalWidth, api.naturalHeight, constraints);\n\n if (result) {\n this.#applyResize(result);\n }\n }\n }\n\n /**\n * Leaving `crossOrigin` unset means \"follow the media component\", so thumbnails keep working on a CORS-enabled player\n * without a skin having to thread an attribute through. Only the `<track>` path inherits: `thumbnails` set directly\n * may point at a host that has nothing to do with the media component.\n */\n #inheritedCrossOrigin(\n textTrack: MediaTextTrackState | undefined\n ): (ThumbnailProps & ThumbnailImageProps)['crossOrigin'] {\n return this.#externalThumbnails ? undefined : textTrack?.thumbnailsTrack?.crossOrigin;\n }\n\n /** Sync image attributes from element properties, leaving the ones the author put on the image alone. */\n #applyImageAttributes(img: HTMLImageElement, textTrack: MediaTextTrackState | undefined): void {\n const props: Partial<Record<ImageAttribute, string | undefined>> = {\n crossorigin: this.#core.resolveCrossOrigin(this.crossOrigin, this.#inheritedCrossOrigin(textTrack)),\n loading: this.loading,\n fetchpriority: this.fetchPriority,\n };\n\n for (const name of this.#authored) delete props[name];\n\n applyElementProps(img, props);\n }\n\n #applyResize(result: ThumbnailResizeResult): void {\n this.style.width = `${result.containerWidth}px`;\n this.style.height = `${result.containerHeight}px`;\n\n const imgStyle = this.#img?.style;\n if (!imgStyle) return;\n\n imgStyle.width = `${result.imageWidth}px`;\n imgStyle.height = `${result.imageHeight}px`;\n imgStyle.maxWidth = 'none';\n imgStyle.transform =\n result.offsetX || result.offsetY ? `translate(-${result.offsetX}px, -${result.offsetY}px)` : '';\n }\n\n #resetStyles(): void {\n this.style.width = '';\n this.style.height = '';\n\n const imgStyle = this.#img?.style;\n if (!imgStyle) return;\n\n imgStyle.width = '';\n imgStyle.height = '';\n imgStyle.maxWidth = '';\n imgStyle.transform = '';\n }\n\n #adopt(next: HTMLImageElement | null): void {\n if (next === this.#img) return;\n\n const previous = this.#img;\n\n if (previous) {\n this.#api?.disconnectImg(previous);\n this.#resetStyles();\n previous.removeAttribute('src');\n previous.removeAttribute('srcset');\n\n for (const name of IMAGE_ATTRIBUTES) {\n if (!this.#authored.has(name)) previous.removeAttribute(name);\n }\n }\n\n // Ownership is settled once, when an image becomes active: after the first\n // sync the attributes we set would themselves look authored.\n this.#img = next;\n this.#authored = new Set(next ? IMAGE_ATTRIBUTES.filter((name) => next.hasAttribute(name)) : []);\n this.#imageAttributes.disconnect();\n\n if (next && next !== this.#fallback) {\n this.#imageAttributes.observe(next, { attributes: true, attributeFilter: ['src', 'srcset'] });\n }\n\n // The fallback only occupies the shadow root while it is the active image,\n // so a supplied image never sits beside a hidden one.\n if (next === this.#fallback) this.#shadow.append(this.#fallback);\n else if (next) this.#fallback.remove();\n\n // Reset the request even when the next image will receive the same URL. A\n // replacement image is a new download with its own lifecycle.\n this.#api?.updateSrc(undefined);\n }\n\n #applySource(src: string | undefined): void {\n const img = this.#img;\n if (!img) return;\n\n // A srcset candidate wins over src, so the root has to clear both parts of\n // the source contract before applying the selected thumbnail URL.\n img.removeAttribute('srcset');\n\n if (!src) img.removeAttribute('src');\n else if (img.getAttribute('src') !== src) img.setAttribute('src', src);\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  //#region src/version.ts
2
2
  const readVersion = () => {
3
3
  try {
4
- return "10.0.0";
4
+ return "10.0.1";
5
5
  } catch {}
6
6
  return "UNKNOWN";
7
7
  };
package/docs/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @videojs/html documentation
2
2
 
3
- Bundled markdown documentation for `@videojs/html` v10.0.0.
3
+ Bundled markdown documentation for `@videojs/html` v10.0.1.
4
4
 
5
5
  Start at [`./llms.txt`](./llms.txt) — it's the structured index of every page in this directory.
6
6
 
@@ -70,7 +70,7 @@ Media components are the components that actually display your media. They’re
70
70
 
71
71
  Media components can be format specific (HLS, DASH), service specific (YouTube, Vimeo, Mux), or use case specific (background video).
72
72
 
73
- Media elements are discovered automatically. Plain `<video>` and `<audio>` elements are found via a `querySelector`. Custom media elements like `<hlsjs-video>` register themselves after you import their registration entry point.
73
+ Media components are discovered automatically. Plain `<video>` and `<audio>` elements are found via a `querySelector`. Media components like `<hlsjs-video>` register themselves after you import their registration entry point.
74
74
 
75
75
  ```html
76
76
  <video-player>
@@ -104,7 +104,7 @@ An extension can provide behavior that a UI component controls: `<google-cast>`
104
104
 
105
105
  The default presets are `@videojs/html/video` and `@videojs/html/audio`, covering the baseline set of controls you’d expect from the HTML `<video>` and `<audio>` tags.
106
106
 
107
- Beyond the defaults, presets target more specific use cases. The `/background` preset combines a media element with autoplay, mute, and loop built in, a skin with no controls, and only the features needed to power it.
107
+ Beyond the defaults, presets target more specific use cases. The `/background` preset combines a media component with autoplay, mute, and loop built in, a skin with no controls, and only the features needed to power it.
108
108
 
109
109
  You can use it from the `@videojs/html/background/*` registration entry points.
110
110
 
@@ -117,4 +117,4 @@ You can use it from the `@videojs/html/background/*` registration entry points.
117
117
  - [Installation](./installation.md): Install Video.js packages and build an accessible, customizable video player with composable controls
118
118
  - [Features](./features.md): The state and actions each feature adds to the player
119
119
  - [Skins](./skins.md): Packaged player designs that include both UI components and their styles.
120
- - [Presets](./presets.md): Pre-packaged player configurations that bundle state management, skins, and media elements for specific use cases.
120
+ - [Presets](./presets.md): Pre-packaged player configurations that bundle state management, skins, and media components for specific use cases.
@@ -6,7 +6,7 @@ For the best chance of autoplay succeeding, start playback muted and enable inli
6
6
 
7
7
  ## Recommended approach
8
8
 
9
- Set autoplay, muted, and inline playback on the media element, and keep a manual play control available for when autoplay is blocked.
9
+ Set autoplay, muted, and inline playback on the media component, and keep a manual play control available for when autoplay is blocked.
10
10
 
11
11
  **index.html**
12
12
 
@@ -112,7 +112,7 @@ These components default to muted, looping playback without player controls. Pro
112
112
 
113
113
  Do not rely on unmuted autoplay for a user’s first visit. Start playback from an explicit user action instead.
114
114
 
115
- Call `play()` on the media element from a click handler:
115
+ Call `play()` on the media component from a click handler:
116
116
 
117
117
  ```html
118
118
  <video-player>
@@ -148,7 +148,7 @@ If autoplay is blocked, the player stays paused and the Play button remains in i
148
148
 
149
149
  ### The video opens fullscreen on iPhone
150
150
 
151
- Enable inline playback with the `playsinline` attribute on the media element.
151
+ Enable inline playback with the `playsinline` attribute on the media component.
152
152
 
153
153
  ### The video starts without sound
154
154
 
@@ -8,7 +8,7 @@ Show captions and subtitles, and let users turn them on and pick a language.
8
8
 
9
9
  ## Recommended approach
10
10
 
11
- Add WebVTT tracks as `<track>` children of the media element, and give users a [`<media-captions-button>`](../reference/components/captions-button.md) to toggle them.
11
+ Add WebVTT tracks as `<track>` children of the media component, and give users a [`<media-captions-button>`](../reference/components/captions-button.md) to toggle them.
12
12
 
13
13
  The `<track>` loads `/docs/demos/text-tracks/captions.vtt`, shown in the `captions.vtt` tab. Host a WebVTT file for your video and point `src` at its URL.
14
14
 
@@ -93,7 +93,7 @@ Toggle captions on and off with a single click.
93
93
 
94
94
  ## How it works
95
95
 
96
- The [text track feature](../reference/api/feature-text-tracks.md) mirrors the media element’s `textTracks` into player state:
96
+ The [text track feature](../reference/api/feature-text-tracks.md) mirrors the media component’s `textTracks` into player state:
97
97
 
98
98
  - `textTrackList` holds every track with its `id`, `kind`, `label`, `language`, and `mode`.
99
99
  - `subtitlesShowing` is `true` when any caption or subtitle track is showing.
@@ -108,7 +108,7 @@ The browser renders the cues. Style them with the `::cue` pseudo-element.
108
108
 
109
109
  - Captions availability is `'unavailable'` until the media has at least one caption or subtitle track; caption controls render nothing in that case.
110
110
  - Cues load asynchronously. A track appears in `textTrackList` before its cues are parsed, so cue-driven UI fills in when the track finishes loading.
111
- - Cross-origin track files require CORS: serve the VTT with CORS headers and set `crossorigin` on the media element.
111
+ - Cross-origin track files require CORS: serve the VTT with CORS headers and set `crossorigin` on the media component.
112
112
  - Track selection UIs identify tracks by `label` and `language`; give every track both.
113
113
  - `default` on a `<track>` marks it as the preferred initial track. The browser’s caption preferences can select another track.
114
114
 
@@ -155,7 +155,7 @@ Confirm that:
155
155
 
156
156
  ### Captions work locally but not in production
157
157
 
158
- The track file is served from another origin without CORS headers. Serve it with `Access-Control-Allow-Origin` and set `crossorigin` on the media element.
158
+ The track file is served from another origin without CORS headers. Serve it with `Access-Control-Allow-Origin` and set `crossorigin` on the media component.
159
159
 
160
160
  ### The captions menu is empty
161
161
 
@@ -176,5 +176,5 @@ The radio group hides when there are no caption or subtitle tracks, but the exam
176
176
  ### Guides
177
177
 
178
178
  - [Show timeline thumbnail previews](./thumbnails.md): Preview frames along the timeline while the user scrubs, powered by a storyboard track.
179
- - [Media sources](./media-sources.md): Set what a media element plays and how its engine plays it with the structured source property
179
+ - [Media sources](./media-sources.md): Set what a media component plays and how its engine plays it with the structured source property
180
180
  - [Accessibility](./accessibility.md): How Video.js approaches accessibility, and what you should consider if you're deeply customizing your player
@@ -116,7 +116,7 @@ import '@videojs/html/ui/airplay-button';
116
116
  import '@videojs/html/ui/cast-button';
117
117
  ```
118
118
 
119
- The demo pairs the media element with the `<google-cast>` extension. Without that extension, `<media-cast-button>` drives the browser’s native Remote Playback API instead, which does not provide Video.js receiver or load-request configuration.
119
+ The demo pairs the media component with the `<google-cast>` extension. Without that extension, `<media-cast-button>` drives the browser’s native Remote Playback API instead, which does not provide Video.js receiver or load-request configuration.
120
120
 
121
121
  ## How it works
122
122
 
@@ -130,7 +130,7 @@ AirPlay uses WebKit’s presentation APIs. Google Cast uses a sender and receive
130
130
 
131
131
  While connected, playback actions — play, pause, seek, volume — proxy to the remote device, and player state keeps reflecting the remote session. Local playback is suspended.
132
132
 
133
- Control playback and read its state through the player while casting: use the built-in controls or the [store actions and state](../reference/api/player-store.md) on the player element’s `store`. Don’t call methods on the media element or listen for its events to drive or track a session.
133
+ Control playback and read its state through the player while casting: use the built-in controls or the [store actions and state](../reference/api/player-store.md) on the player element’s `store`. Don’t call methods on the media component or listen for its events to drive or track a session.
134
134
 
135
135
  For a custom control, call `promptRemotePlayback()` directly from the click handler and catch its promise. It rejects when no remote route exists or the browser refuses the request. A canceled Google Cast picker can also resolve without connecting, so show success only when `remotePlaybackState` is `'connected'`. The built-in buttons handle the request for you.
136
136
 
@@ -142,7 +142,7 @@ The Google Cast SDK loads only when the player includes the `<google-cast>` exte
142
142
  - Google Cast works only in Chromium-based browsers; elsewhere its route reports `'unsupported'`.
143
143
  - AirPlay works only in Safari; availability requires an AirPlay device reachable on the network.
144
144
  - The remote device fetches the source and its text tracks on its own. Localhost, VPN-only, expired, or cross-origin URLs without the necessary CORS headers will fail on the receiver even if they play in the browser.
145
- - Set the `disableremoteplayback` attribute on the media element to opt out entirely.
145
+ - Set the `disableremoteplayback` attribute on the media component to opt out entirely.
146
146
 
147
147
  ## Common variations
148
148
 
@@ -172,7 +172,7 @@ The receiver cannot fetch the media. Confirm the source URL is reachable from th
172
172
 
173
173
  ### Custom UI shows local playback while casting
174
174
 
175
- The code reads or controls the media element directly. Read playback state from the player store and call its actions instead; only the player reflects the remote session.
175
+ The code reads or controls the media component directly. Read playback state from the player store and call its actions instead; only the player reflects the remote session.
176
176
 
177
177
  ### The UI freezes on “connecting”
178
178
 
@@ -193,4 +193,4 @@ For Google Cast, track the `promptRemotePlayback()` promise separately from `rem
193
193
 
194
194
  ### Guides
195
195
 
196
- - [Media sources](./media-sources.md): Set what a media element plays and how its engine plays it with the structured source property
196
+ - [Media sources](./media-sources.md): Set what a media component plays and how its engine plays it with the structured source property
@@ -27,7 +27,7 @@ Each installation [preset](./presets.md) ships its bundles at the package root:
27
27
  | `video-compat.js` | `<video-player>`, `<video-compat-skin>`, and the UI elements the compat skin composes |
28
28
  | `video-player.js` | `<video-player>` alone, for markup without a packaged skin |
29
29
 
30
- The other presets follow the same pattern. Background video is the exception: one bundle, `background.js`, registers the player, the skin, and the `<background-video>` media element.
30
+ The other presets follow the same pattern. Background video is the exception: one bundle, `background.js`, registers the player, the skin, and the `<background-video>` media component.
31
31
 
32
32
  A skin bundle registers every UI element its skin is built from. Any element the skin does not compose is its own bundle under `ui/`.
33
33
 
@@ -36,19 +36,19 @@ A skin bundle registers every UI element its skin is built from. Any element the
36
36
  Each [UI element](./ui-components.md) is its own bundle under `ui/`, for markup that a skin bundle does not already cover: a player-only bundle, [skin source](./customize-skins.md#style-skin-source) that adds a component the packaged skin lacks, or a [dialog](../reference/components/dialog.md) your page opens beside a packaged skin.
37
37
 
38
38
  ```html
39
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/video-player.js"></script>
40
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/ui/play-button.js"></script>
39
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/video-player.js"></script>
40
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/ui/play-button.js"></script>
41
41
  ```
42
42
 
43
43
  Each path mirrors its npm subpath: `ui/play-button.js` registers the element that `@videojs/html/ui/play-button` does. Compound components list one bundle per part in their reference page’s Import section, and all of the bundles share chunks with the player.
44
44
 
45
45
  ## Media bundles
46
46
 
47
- The default presets play through the browser’s own `<video>` and `<audio>`. Every other [media element](./media-sources.md) is its own bundle under `media/`, loaded beside the player bundle:
47
+ The default presets play through the browser’s own `<video>` and `<audio>`. Every other [media component](./media-sources.md) is its own bundle under `media/`, loaded beside the player bundle:
48
48
 
49
49
  ```html
50
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/video.js"></script>
51
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/media/hlsjs-video.js"></script>
50
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/video.js"></script>
51
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/media/hlsjs-video.js"></script>
52
52
  ```
53
53
 
54
54
  Each path mirrors its npm subpath. Elements with more than one playback engine keep the extra flavors in a directory named for the element, such as `media/mux-video/spf.js`. Load one flavor per page: every flavor claims the same tag name, and the first registration wins.
@@ -58,9 +58,9 @@ Each path mirrors its npm subpath. Elements with more than one playback engine k
58
58
  Each [extension](./architecture.md) is its own bundle under `extensions/`, loaded beside the player and media bundles:
59
59
 
60
60
  ```html
61
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/video.js"></script>
62
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/media/mux-video.js"></script>
63
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/extensions/mux-data.js"></script>
61
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/video.js"></script>
62
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/media/mux-video.js"></script>
63
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/extensions/mux-data.js"></script>
64
64
  ```
65
65
 
66
66
  As with media, each path mirrors its npm subpath: `extensions/mux-data.js` registers the element that `@videojs/html/extensions/mux-data` does.
@@ -70,8 +70,8 @@ As with media, each path mirrors its npm subpath: `extensions/mux-data.js` regis
70
70
  English ships inside the skin bundles. Each other locale is a bundle under `locales/` that registers its translations on import. Load it before the player script to avoid a flash of English:
71
71
 
72
72
  ```html
73
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/locales/es.js"></script>
74
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/video.js"></script>
73
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/locales/es.js"></script>
74
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/video.js"></script>
75
75
  ```
76
76
 
77
77
  One bundle exists per locale pack, plus bare-language aliases such as `pt`. For custom strings, see [Internationalize the player](./internationalization.md).
@@ -38,7 +38,7 @@ If you omit `--media-accent-text-color`, the skins choose a contrasting text col
38
38
 
39
39
  The skins use [`Inter`](https://rsms.me/inter/) when your page loads it and fall back to the system UI font. Video.js does not load the webfont for you. Set `--media-font-family` to use another font.
40
40
 
41
- The media element and poster share `--media-object-fit` and `--media-object-position`, so a `cover` poster stays aligned with `cover` video. See [Add a poster and loading placeholder](./poster.md).
41
+ The media component and poster share `--media-object-fit` and `--media-object-position`, so a `cover` poster stays aligned with `cover` video. See [Add a poster and loading placeholder](./poster.md).
42
42
 
43
43
  ### Set the color scheme
44
44
 
@@ -96,7 +96,7 @@ The Shadcn installation guide handles project setup, lets you choose the skin an
96
96
 
97
97
  ### Use the installed skin
98
98
 
99
- The skin directory contains `skin.html`, `skin.ts`, and `skin.css`. Keep importing the player and media from `@videojs/html`. Import the installed `skin.ts` once, then paste the markup from `skin.html` inside your player around the media element.
99
+ The skin directory contains `skin.html`, `skin.ts`, and `skin.css`. Keep importing the player and media from `@videojs/html`. Import the installed `skin.ts` once, then paste the markup from `skin.html` inside your player around the media component.
100
100
 
101
101
  ### Edit the installed files
102
102
 
@@ -24,7 +24,7 @@ For example, if you import `<video-player>` from the `/video` path, you will hav
24
24
  </video-player>
25
25
  ```
26
26
 
27
- Feature bundles are usually paired with specific skins and media elements in a **preset**. To learn more about this, and the available presets, you’ll want to check out the presets guide.
27
+ Feature bundles are usually paired with specific skins and media components in a **preset**. To learn more about this, and the available presets, you’ll want to check out the presets guide.
28
28
 
29
29
  - [Learn more about presets](./presets.md)
30
30
 
@@ -77,7 +77,7 @@ import '@videojs/html/ui/fullscreen-button';
77
77
  The [fullscreen feature](../reference/api/feature-fullscreen.md) tracks fullscreen state and provides the actions:
78
78
 
79
79
  - `isFullscreen` is `true` while the player is fullscreen, from any path — your button, native controls, or the platform presentation.
80
- - `fullscreenAvailability` is `'available'`, `'unavailable'`, or `'unsupported'`. It starts as `'unavailable'`, then settles to `'available'` or `'unsupported'` when the feature attaches to a media element.
80
+ - `fullscreenAvailability` is `'available'`, `'unavailable'`, or `'unsupported'`. It starts as `'unavailable'`, then settles to `'available'` or `'unsupported'` when the feature attaches to a media component.
81
81
  - `requestFullscreen()` and `exitFullscreen()` change the presentation. When the Fullscreen API is available, requests target the player container. Otherwise they fall back to the media element’s native presentation.
82
82
 
83
83
  Fullscreen and picture-in-picture are exclusive: requesting fullscreen exits an active picture-in-picture presentation first.
@@ -89,7 +89,7 @@ Defaulted options: project, preset, skin, source-url, media, extensions, templat
89
89
  ## Reproduce or change these instructions
90
90
 
91
91
  ```sh
92
- npx @videojs/cli@10.0.0 agents init --method cdn --framework html --project existing --preset video --skin default --media html5-video --extensions none --source-url https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4 --template none
92
+ npx @videojs/cli@10.0.1 agents init --method cdn --framework html --project existing --preset video --skin default --media html5-video --extensions none --source-url https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4 --template none
93
93
  ```
94
94
 
95
95
  ## Load Video.js
@@ -101,7 +101,7 @@ Add these module scripts to the page head. Module scripts are deferred, so they
101
101
  _Merge this into the page `<head>`._
102
102
 
103
103
  ```html
104
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/video.js"></script>
104
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/video.js"></script>
105
105
  ```
106
106
 
107
107
  ## Add your player
@@ -94,7 +94,7 @@ Defaulted options: project, preset, skin, source-url, media, extensions, templat
94
94
  ## Reproduce or change these instructions
95
95
 
96
96
  ```sh
97
- npx @videojs/cli@10.0.0 agents init --method shadcn --framework html --project existing --preset video --skin default --media html5-video --extensions none --source-url https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4 --package-manager pnpm --template vite --styling css
97
+ npx @videojs/cli@10.0.1 agents init --method shadcn --framework html --project existing --preset video --skin default --media html5-video --extensions none --source-url https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4 --package-manager pnpm --template vite --styling css
98
98
  ```
99
99
 
100
100
  ## Configure app aliases
@@ -214,7 +214,7 @@ pnpm dlx shadcn@latest registry add @videojs=https://shadcn.videojs.org/r/html/{
214
214
 
215
215
  ## Add the skin source
216
216
 
217
- Make sure the working tree is clean or checkpointed so every added or replaced file is reviewable; ask before committing. The add command overwrites an existing Video.js skin so catalog and theme changes fully apply. Review and remove obsolete Video.js style files left by a previous catalog. The later media step restores the selected media element after an overwrite.
217
+ Make sure the working tree is clean or checkpointed so every added or replaced file is reviewable; ask before committing. The add command overwrites an existing Video.js skin so catalog and theme changes fully apply. Review and remove obsolete Video.js style files left by a previous catalog. The later media step restores the selected media component after an overwrite.
218
218
 
219
219
  ```bash
220
220
  pnpm dlx shadcn@latest add @videojs/video --overwrite --yes
@@ -222,11 +222,11 @@ pnpm dlx shadcn@latest add @videojs/video --overwrite --yes
222
222
 
223
223
  ## Add your player
224
224
 
225
- Use the aliases.components value from components.json when it differs from the generated @/components path: the skin file then lives under the directory that alias maps to instead of src/components, and the skin import uses that alias. Replace the <!-- Add a compatible media element here. --> placeholder in src/components/videojs/video/skin.html with the media snippet below. Size the video on the skin's root media-container by replacing its opening <media-container with the snippet below. Then replace the <!-- Paste the contents of src/components/videojs/video/skin.html here. --> comment in the page with the complete updated skin markup. Merge the example into the existing Vite route or component that should render the player, and preserve unrelated content.
225
+ Use the aliases.components value from components.json when it differs from the generated @/components path: the skin file then lives under the directory that alias maps to instead of src/components, and the skin import uses that alias. Replace the <!-- Add a compatible media component here. --> placeholder in src/components/videojs/video/skin.html with the media snippet below. Size the video on the skin's root media-container by replacing its opening <media-container with the snippet below. Then replace the <!-- Paste the contents of src/components/videojs/video/skin.html here. --> comment in the page with the complete updated skin markup. Merge the example into the existing Vite route or component that should render the player, and preserve unrelated content.
226
226
 
227
227
  ### `src/components/videojs/video/skin.html`
228
228
 
229
- _Replace `<!-- Add a compatible media element here. -->` with this block._
229
+ _Replace `<!-- Add a compatible media component here. -->` with this block._
230
230
 
231
231
  ```html
232
232
  <video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" playsinline></video>
@@ -90,13 +90,13 @@ Defaulted options: project, preset, skin, source-url, media, extensions, templat
90
90
  ## Reproduce or change these instructions
91
91
 
92
92
  ```sh
93
- npx @videojs/cli@10.0.0 agents init --method packaged --framework svelte --project existing --preset video --skin default --media html5-video --extensions none --source-url https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4 --package-manager pnpm --template vite
93
+ npx @videojs/cli@10.0.1 agents init --method packaged --framework svelte --project existing --preset video --skin default --media html5-video --extensions none --source-url https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4 --package-manager pnpm --template vite
94
94
  ```
95
95
 
96
96
  ## Install the packages
97
97
 
98
98
  ```bash
99
- pnpm add @videojs/html@10.0.0
99
+ pnpm add @videojs/html@10.0.1
100
100
  ```
101
101
 
102
102
  ## Add your player
@@ -90,13 +90,13 @@ Defaulted options: project, preset, skin, source-url, media, extensions, templat
90
90
  ## Reproduce or change these instructions
91
91
 
92
92
  ```sh
93
- npx @videojs/cli@10.0.0 agents init --method packaged --framework vue --project existing --preset video --skin default --media html5-video --extensions none --source-url https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4 --package-manager pnpm --template vite
93
+ npx @videojs/cli@10.0.1 agents init --method packaged --framework vue --project existing --preset video --skin default --media html5-video --extensions none --source-url https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4 --package-manager pnpm --template vite
94
94
  ```
95
95
 
96
96
  ## Install the packages
97
97
 
98
98
  ```bash
99
- pnpm add @videojs/html@10.0.0
99
+ pnpm add @videojs/html@10.0.1
100
100
  ```
101
101
 
102
102
  ## Register custom elements
@@ -92,13 +92,13 @@ Defaulted options: project, preset, skin, source-url, media, extensions, templat
92
92
  ## Reproduce or change these instructions
93
93
 
94
94
  ```sh
95
- npx @videojs/cli@10.0.0 agents init --method packaged --framework html --project existing --preset video --skin default --media html5-video --extensions none --source-url https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4 --package-manager pnpm --template vite
95
+ npx @videojs/cli@10.0.1 agents init --method packaged --framework html --project existing --preset video --skin default --media html5-video --extensions none --source-url https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4 --package-manager pnpm --template vite
96
96
  ```
97
97
 
98
98
  ## Install the packages
99
99
 
100
100
  ```bash
101
- pnpm add @videojs/html@10.0.0
101
+ pnpm add @videojs/html@10.0.1
102
102
  ```
103
103
 
104
104
  ## Add your player
@@ -199,8 +199,8 @@ import '@videojs/html/i18n/locales/ja/register';
199
199
  CDN locale modules call `registerI18n` on import. Pin every URL to the same version:
200
200
 
201
201
  ```html
202
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/locales/es.js"></script>
203
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/video.js"></script>
202
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/locales/es.js"></script>
203
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/video.js"></script>
204
204
  ```
205
205
 
206
206
  Use the same pinned version for your locale pack, `i18n.js`, and player script. Copies loaded in the same window share a registry; matching versions keeps their translation keys and APIs compatible. Import the full locale pack before partial overrides, and register before the player loads to translate the first render:
@@ -208,15 +208,15 @@ Use the same pinned version for your locale pack, `i18n.js`, and player script.
208
208
  **my-locale.js**
209
209
 
210
210
  ```js
211
- import 'https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/locales/es.js';
212
- import { registerI18n } from 'https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/i18n.js';
211
+ import 'https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/locales/es.js';
212
+ import { registerI18n } from 'https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/i18n.js';
213
213
 
214
214
  registerI18n('es', { buttons: { play: 'Reproducir', pause: 'Pausa' } });
215
215
  ```
216
216
 
217
217
  ```html
218
218
  <script type="module" src="/my-locale.js"></script>
219
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/video.js"></script>
219
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/video.js"></script>
220
220
  ```
221
221
 
222
222
  ### Switch locale at runtime
@@ -16,7 +16,7 @@ pnpm add @videojs/html @videojs/hlsjs-video
16
16
 
17
17
  ## Recommended approach
18
18
 
19
- Use the live feature bundle with a streaming media element, and give users a `<media-live-button>`: it shows whether playback is at the live edge and seeks back to it when activated.
19
+ Use the live feature bundle with a streaming media component, and give users a `<media-live-button>`: it shows whether playback is at the live edge and seeks back to it when activated.
20
20
 
21
21
  ```html
22
22
  <live-video-player>
@@ -119,7 +119,7 @@ Render live or on-demand controls from `streamType` when one player handles both
119
119
 
120
120
  ### The live badge never activates
121
121
 
122
- `<media-live-button>` reads `targetLiveWindow`, `currentTime`, and `seekable`. Confirm that `targetLiveWindow` is `0` or `Infinity` and that `seekable` has a finite end. Use a live-capable media element such as [`<hlsjs-video>`](../reference/components/hlsjs-video.md). The live button does not need `streamTypeFeature`; add it only when your own UI reads `streamType`.
122
+ `<media-live-button>` reads `targetLiveWindow`, `currentTime`, and `seekable`. Confirm that `targetLiveWindow` is `0` or `Infinity` and that `seekable` has a finite end. Use a live-capable media component such as [`<hlsjs-video>`](../reference/components/hlsjs-video.md). The live button does not need `streamTypeFeature`; add it only when your own UI reads `streamType`.
123
123
 
124
124
  ### Playback keeps falling behind the edge
125
125
 
@@ -145,4 +145,4 @@ Compare the slider’s range with `seekable`. The built-in slider always starts
145
145
 
146
146
  ### Guides
147
147
 
148
- - [Media sources](./media-sources.md): Set what a media element plays and how its engine plays it with the structured source property
148
+ - [Media sources](./media-sources.md): Set what a media component plays and how its engine plays it with the structured source property
@@ -1,6 +1,6 @@
1
1
  # Video.js v10 — HTML Guides
2
2
 
3
- > Installation, migration, concepts, playback guides, customization, and tooling for Video.js. Bundled with `@videojs/html` v10.0.0. Links are relative paths to files in this directory.
3
+ > Installation, migration, concepts, playback guides, customization, and tooling for Video.js. Bundled with `@videojs/html` v10.0.1. Links are relative paths to files in this directory.
4
4
 
5
5
  ## Getting Started
6
6
 
@@ -43,10 +43,10 @@ Understanding-oriented pages that explain how and why things work. Read these to
43
43
 
44
44
  - [Features](./features.md): The state and actions each feature adds to the player
45
45
  - [Skins](./skins.md): Packaged player designs that include both UI components and their styles.
46
- - [Presets](./presets.md): Pre-packaged player configurations that bundle state management, skins, and media elements for specific use cases.
46
+ - [Presets](./presets.md): Pre-packaged player configurations that bundle state management, skins, and media components for specific use cases.
47
47
  - [UI components](./ui-components.md): How Video.js UI components use focused elements, data attributes for state, and compound composition.
48
48
  - [Accessibility](./accessibility.md): How Video.js approaches accessibility, and what you should consider if you're deeply customizing your player
49
- - [Media sources](./media-sources.md): Set what a media element plays and how its engine plays it with the structured source property
49
+ - [Media sources](./media-sources.md): Set what a media component plays and how its engine plays it with the structured source property
50
50
 
51
51
  ## Playback
52
52
 
@@ -73,6 +73,7 @@ Guides for one player capability each: the recommended setup, how it works, brow
73
73
 
74
74
  Guides for moving an existing player integration to Video.js v10, one per player you might be coming from.
75
75
 
76
+ - [Migrate to Video.js v10](./migrate.md): Understand how Video.js v10 differs from the players it brings together, and choose the migration guide for the player you use today.
76
77
  - [Migrate from Video.js 8](./migrate-from-video-js-8.md): Move a Video.js 8 integration to v10, mapping the options object, techs, plugins, and player API onto composed components
77
78
  - [Migrate from Mux Player](./migrate-from-mux-player.md): Move a Mux Player embed to Video.js v10 using a player, media component, skin, and analytics extension
78
79
  - [Migrate from Plyr](./migrate-from-plyr.md): Move an existing Plyr integration to Video.js v10, mapping Plyr options and its instance API onto components and player state
@@ -1,8 +1,8 @@
1
1
  # Media sources
2
2
 
3
- Set what a media element plays and how its engine plays it with the structured source property
3
+ Set what a media component plays and how its engine plays it with the structured source property
4
4
 
5
- Every media element takes a `src`. Elements that drive a playback engine also take `source`, a structured object that carries the URL alongside everything else about that source:
5
+ Every media component takes a `src`. Elements that drive a playback engine also take `source`, a structured object that carries the URL alongside everything else about that source:
6
6
 
7
7
  ```ts
8
8
  const video = document.querySelector('hlsjs-video');
@@ -46,14 +46,14 @@ Before loading Video.js HTML, remove every Media Chrome import and CDN script fr
46
46
  For a page without a bundler, load the CDN video preset. It registers the player, the UI elements and icons used in the controller example below, and the `<media-i18n>` element:
47
47
 
48
48
  ```html
49
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/video.js"></script>
49
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/video.js"></script>
50
50
  ```
51
51
 
52
52
  Some elements in the mapping table below need separate bundles. If you use any of these elements, also load its bundle:
53
53
 
54
- - `media-seek-button`: `https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/ui/seek-button.js`
55
- - `media-playback-rate-button`: `https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/ui/playback-rate-button.js`
56
- - `media-thumbnail`: `https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/ui/thumbnail.js`
54
+ - `media-seek-button`: `https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/ui/seek-button.js`
55
+ - `media-playback-rate-button`: `https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/ui/playback-rate-button.js`
56
+ - `media-thumbnail`: `https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/ui/thumbnail.js`
57
57
 
58
58
  Load each with `<script type="module" src="…"></script>`. See [CDN](./cdn.md) for individual component bundles.
59
59
 
@@ -43,7 +43,7 @@ Make a migration checklist before changing your embed:
43
43
 
44
44
  - **List the Mux Player attributes or React props you set.** Compare them with the mapping tables below.
45
45
  - **Grep your codebase for `mux-player` selectors.** After the swap, CSS rules and `querySelector` calls that reach into the element stop matching, with no error. Look for patterns such as `mux-player::part(…)`, `mux-player [role="slider"]`, and `player.shadowRoot`. Restyle the UI with the skin’s custom properties or rebuild it with Video.js components.
46
- - **Find your event listeners and imperative calls** (`play()`, `currentTime`, `addChapters`). Media APIs move to the media element; the rest is mapped under [Drive playback](#drive-playback).
46
+ - **Find your event listeners and imperative calls** (`play()`, `currentTime`, `addChapters`). Media APIs move to the media component; the rest is mapped under [Drive playback](#drive-playback).
47
47
  - **Note your theme and CSS variables.** Compare your Mux Player theme with the two Video.js skins, and map its CSS variables.
48
48
  - **Check [Known gaps](#known-gaps)** for features your app needs.
49
49
  - **Check your catalog for MPEG-TS, raw ADTS AAC, AES-128, low-latency HLS, or DVR streams.** Check whether the SPF engine supports these requirements. If you use DRM, verify playback with whichever engine you choose. See [Which Mux media should you use?](#which-mux-media-should-you-use).
@@ -68,9 +68,9 @@ The examples keep a playback ID, analytics metadata, and a poster from two secon
68
68
  From the CDN, load the video [preset](./presets.md), the Mux media, and analytics:
69
69
 
70
70
  ```html
71
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/video.js"></script>
72
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/media/mux-video.js"></script>
73
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/extensions/mux-data.js"></script>
71
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/video.js"></script>
72
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/media/mux-video.js"></script>
73
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/extensions/mux-data.js"></script>
74
74
 
75
75
  <video-player content-title="Test VOD">
76
76
  <video-skin style="aspect-ratio: 16 / 9">
@@ -421,8 +421,8 @@ Mux Player switches to live controls automatically. In Video.js, choose the live
421
421
  Register the live preset and Mux media. From the CDN:
422
422
 
423
423
  ```html
424
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/live-video.js"></script>
425
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/media/mux-video.js"></script>
424
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/live-video.js"></script>
425
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/media/mux-video.js"></script>
426
426
 
427
427
  <live-video-player>
428
428
  <live-video-skin>
@@ -452,7 +452,7 @@ Use [`createPlayer`](../reference/api/html-create-player.md) to build a player e
452
452
  The live skin already includes a live button. If you build your own controls, use that same component and style it to match your app. It keeps track of whether playback is live and returns viewers to the newest available point in the stream.
453
453
 
454
454
  ```html
455
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0/ui/live-button.js"></script>
455
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.1/ui/live-button.js"></script>
456
456
 
457
457
  <media-live-button class="station-live-button">On air</media-live-button>
458
458
  ```