Skip to content

feat: add media delegate mixin#598

Merged
luwes merged 1 commit intomainfrom
media-delegate
Feb 24, 2026
Merged

feat: add media delegate mixin#598
luwes merged 1 commit intomainfrom
media-delegate

Conversation

@luwes
Copy link
Copy Markdown
Collaborator

@luwes luwes commented Feb 24, 2026

This pull request refactors the media proxy and custom media element system to improve clarity, extensibility, and code organization. The changes introduce a new delegation mixin for advanced media behavior, rename and update proxy mixins for consistency, and streamline the custom media element implementation. There are also updates to how HLS (HTTP Live Streaming) media is handled, and some minor configuration and import adjustments.

Media Proxy and Delegation Refactor:

  • Introduced MediaDelegateMixin and MediaDelegate interface in media/delegate.ts, allowing property/method delegation to a delegate class before falling back to the base implementation. This enables advanced behaviors such as HLS support to be injected cleanly.
  • Renamed MediaApiProxyMixin to MediaProxyMixin and updated its usage across the codebase for consistency and clarity. The new signature improves type safety and extensibility. [1] [2] [3]
  • Updated proxy class exports in dom/media/proxy.ts and documentation to use the new MediaProxyMixin naming and structure. [1] [2]

Custom Media Element Improvements:

  • Refactored CustomMediaMixin (now in core/src/dom/media/custom-media-element.ts) to directly implement get, set, and call methods for property access, attribute mapping, and method invocation, simplifying the code and improving maintainability. [1] [2] [3]
  • Updated imports in HTML package components to use the new core location for CustomMediaMixin.

HLS Media Handling Enhancements:

  • Replaced the old HLS mixin with a new HlsMediaDelegate class, and used MediaDelegateMixin to create HlsCustomMedia and HlsMedia classes for web components and React, respectively. This allows HLS-specific logic to be injected via delegation. [1] [2]

Build and Configuration Updates:

  • Added the new custom media element entry point to the build config and updated TypeScript library targets for better compatibility. [1] [2]

File and Code Organization:

  • Moved and renamed files to better reflect their purpose (e.g., custom media element code moved from packages/html to packages/core).

These changes collectively make the media handling system more modular, extensible, and maintainable, especially for advanced use cases like HLS streaming.

@luwes luwes requested a review from Copilot February 24, 2026 19:59
@luwes luwes self-assigned this Feb 24, 2026
@vercel
Copy link
Copy Markdown

vercel bot commented Feb 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
vjs-10-demo-react Ignored Ignored Feb 24, 2026 7:59pm

Request Review

@netlify
Copy link
Copy Markdown

netlify bot commented Feb 24, 2026

Deploy Preview for vjs10-site ready!

Name Link
🔨 Latest commit 5106002
🔍 Latest deploy log https://app.netlify.com/projects/vjs10-site/deploys/699e0311bfc2c60008b2cfd9
😎 Deploy Preview https://deploy-preview-598--vjs10-site.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions
Copy link
Copy Markdown
Contributor

📦 Bundle Size Report

Package Size Diff %
@videojs/core 5.68 kB +9 B ████████ +0.2% 🔺
@videojs/element 1.60 kB 0 B ░░░░░░░░ 0%
@videojs/html 8.63 kB 0 B ░░░░░░░░ 0%
@videojs/icons 3.46 kB 0 B ░░░░░░░░ 0%
@videojs/react 14.89 kB -8 B ███░░░░░ -0.1% 🔽
@videojs/store 1.94 kB 0 B ░░░░░░░░ 0%
@videojs/utils 2.47 kB 0 B ░░░░░░░░ 0%

Total: 38.68 kB · +1 B · +0.0%


Entry Breakdown

Subpath sizes are the additional bytes on top of the root entry point, measured by bundling root + subpath together and subtracting the root-only size.

@videojs/core
Entry Base PR Diff %
. 3.09 kB 3.10 kB +10 B +0.3% 🔺
./dom 2.58 kB 2.58 kB -1 B -0.0% 🔽
total 5.67 kB 5.68 kB +9 B +0.2%
@videojs/element
Entry Base PR Diff %
. 817 B 817 B 0 B 0%
./context 823 B 823 B 0 B 0%
total 1.60 kB 1.60 kB 0 B 0%
@videojs/icons
Entry Base PR Diff %
./react 2.10 kB 2.10 kB 0 B 0%
./html 1.37 kB 1.37 kB 0 B 0%
total 3.46 kB 3.46 kB 0 B 0%
@videojs/react
Entry Base PR Diff %
. 7.69 kB 7.69 kB 0 B 0%
./audio 266 B 266 B 0 B 0%
./background 268 B 268 B 0 B 0%
./video 6.70 kB 6.69 kB -8 B -0.1% 🔽
total 14.90 kB 14.89 kB -8 B -0.1%
@videojs/store
Entry Base PR Diff %
. 1.29 kB 1.29 kB 0 B 0%
./html 468 B 468 B 0 B 0%
./react 199 B 199 B 0 B 0%
total 1.94 kB 1.94 kB 0 B 0%
@videojs/utils
Entry Base PR Diff %
./array 104 B 104 B 0 B 0%
./dom 684 B 684 B 0 B 0%
./events 227 B 227 B 0 B 0%
./function 197 B 197 B 0 B 0%
./object 119 B 119 B 0 B 0%
./predicate 265 B 265 B 0 B 0%
./string 110 B 110 B 0 B 0%
./style 185 B 185 B 0 B 0%
./time 478 B 478 B 0 B 0%
./number 158 B 158 B 0 B 0%
total 2.47 kB 2.47 kB 0 B 0%

ℹ️ How to interpret

Sizes are minified + brotli, measured with esbuild.
Package totals are computed as root size + marginal subpath costs.
Subpath marginal cost = (root + subpath bundled together) − root alone.

Icon Meaning
No change
🔺 Increased ≤ 10%
🔴 Increased > 10%
🔽 Decreased
🆕 New (no baseline)

Run pnpm size locally to check current sizes.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the media proxy/custom media element architecture to support delegated media behaviors (e.g., HLS) via a new delegation mixin, while renaming/reworking proxy mixins and relocating custom media element utilities into @videojs/core.

Changes:

  • Added MediaDelegateMixin + MediaDelegate to enable delegated overrides of get/set/call with lifecycle hooks (attach/detach).
  • Renamed and updated the proxy mixin (MediaApiProxyMixinMediaProxyMixin) and adjusted HLS to use delegation instead of an HLS mixin.
  • Moved/standardized custom media element imports and added a new build entry point for dom/media/custom-media-element.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/html/src/media/hls-video/index.ts Switches HLS custom element to extend the new delegated HLS base (HlsCustomMedia).
packages/html/src/media/background-video/index.ts Updates import path to the new core CustomMediaMixin entry point.
packages/core/tsdown.config.ts Adds a dedicated build entry for dom/media/custom-media-element.
packages/core/src/dom/tsconfig.json Updates TS lib target from ES2020 to ES2022 for DOM package compilation.
packages/core/src/dom/media/proxy.ts Removes old DOM proxy wrapper exports (now superseded by core proxy mixin usage).
packages/core/src/dom/media/hls.ts Replaces HLS mixin with HlsMediaDelegate + MediaDelegateMixin composition.
packages/core/src/dom/media/custom-media-element.ts Refactors to implement get/set/call directly and centralizes attr/property mapping.
packages/core/src/core/media/proxy.ts Renames and re-signatures proxy mixin to MediaProxyMixin(PrimaryClass, ...AdditionalClasses).
packages/core/src/core/media/delegate.ts Introduces delegation mixin for intercepting get/set/call and forwarding attach/detach.
internal/design/media-api.md Updates design docs to reference MediaProxyMixin naming (needs signature alignment).
Comments suppressed due to low confidence (2)

packages/core/src/dom/media/custom-media-element.ts:305

  • defaultMuted is intended to reflect the muted attribute (see comment in #define), but it now calls get('muted')/set('muted') even though muted is removed from #propsToAttrs. This makes defaultMuted track the native element’s muted property instead of the attribute and stops updating the attribute on set. Consider handling defaultMuted explicitly via hasAttribute('muted')/toggleAttribute('muted', ...) (and, if needed for browser quirks, also sync nativeEl.muted).
    packages/core/src/dom/media/custom-media-element.ts:253
  • get() currently treats every attribute in #propsToAttrs as boolean-or-string and returns false when the attribute is missing. For non-boolean attributes like src, preload, poster, etc., this changes the observable API (e.g., preload would become false instead of the native default). Consider special-casing boolean attributes vs string attributes, or falling back to nativeEl[prop] when getAttribute() is null for non-boolean attributes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +164 to 165
export const MediaProxyMixin = <T extends EventTarget>(
...MediaApiTargetClasses: AnyConstructor<T extends [unknown, ...unknown[]] ? T : any>[]
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The design doc’s MediaProxyMixin signature no longer matches the implementation in packages/core/src/core/media/proxy.ts (which now takes PrimaryClass, ...AdditionalClasses rather than a single rest parameter with the conditional type). Updating the snippet here will avoid confusion for readers following the design doc.

Suggested change
export const MediaProxyMixin = <T extends EventTarget>(
...MediaApiTargetClasses: AnyConstructor<T extends [unknown, ...unknown[]] ? T : any>[]
export const MediaProxyMixin = <PrimaryClass extends EventTarget>(
PrimaryClass: AnyConstructor<PrimaryClass>,
...AdditionalClasses: AnyConstructor<EventTarget>[]

Copilot uses AI. Check for mistakes.
@luwes luwes merged commit c4ef94e into main Feb 24, 2026
16 checks passed
@luwes luwes deleted the media-delegate branch February 24, 2026 20:53
This was referenced Feb 24, 2026
@github-actions github-actions bot mentioned this pull request Mar 10, 2026
@luwes luwes mentioned this pull request Apr 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants