mirror of
https://github.com/zoriya/v10.git
synced 2026-08-06 22:28:24 +00:00
fix(html): prevent tsdown from stripping custom element registrations (#703)
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { audioFeatures } from '@videojs/core/dom';
|
||||
import { MediaContainerElement } from '../../media/container-element';
|
||||
import { createPlayer } from '../../player/create-player';
|
||||
import { MediaElement } from '../../ui/media-element';
|
||||
import '../media/container';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
const { ProviderMixin } = createPlayer({
|
||||
features: audioFeatures,
|
||||
@@ -11,7 +12,9 @@ export class AudioPlayerElement extends ProviderMixin(MediaElement) {
|
||||
static readonly tagName = 'audio-player';
|
||||
}
|
||||
|
||||
customElements.define(AudioPlayerElement.tagName, AudioPlayerElement);
|
||||
// Provider must be defined before consumer for context handshake during upgrade.
|
||||
safeDefine(AudioPlayerElement);
|
||||
safeDefine(MediaContainerElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { backgroundFeatures } from '@videojs/core/dom';
|
||||
import { MediaContainerElement } from '../../media/container-element';
|
||||
import { createPlayer } from '../../player/create-player';
|
||||
import { MediaElement } from '../../ui/media-element';
|
||||
import '../media/container';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
const { ProviderMixin } = createPlayer({
|
||||
features: backgroundFeatures,
|
||||
@@ -11,7 +12,9 @@ export class BackgroundVideoPlayerElement extends ProviderMixin(MediaElement) {
|
||||
static readonly tagName = 'background-video-player';
|
||||
}
|
||||
|
||||
customElements.define(BackgroundVideoPlayerElement.tagName, BackgroundVideoPlayerElement);
|
||||
// Provider must be defined before consumer for context handshake during upgrade.
|
||||
safeDefine(BackgroundVideoPlayerElement);
|
||||
safeDefine(MediaContainerElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ReactiveElement } from '@videojs/element';
|
||||
import { namedNodeMapToObject } from '@videojs/utils/dom';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
function getTemplateHTML(_attrs: Record<string, string>) {
|
||||
return /*html*/ `
|
||||
@@ -24,7 +25,7 @@ export class BackgroundVideoSkinElement extends ReactiveElement {
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(BackgroundVideoSkinElement.tagName, BackgroundVideoSkinElement);
|
||||
safeDefine(BackgroundVideoSkinElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { BackgroundVideo } from '../../media/background-video';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
export class BackgroundVideoElement extends BackgroundVideo {
|
||||
static readonly tagName = 'background-video';
|
||||
}
|
||||
|
||||
customElements.define(BackgroundVideoElement.tagName, BackgroundVideoElement);
|
||||
safeDefine(BackgroundVideoElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
import { playerContext } from '../../player/context';
|
||||
import { createContainerMixin } from '../../store/container-mixin';
|
||||
import { MediaElement } from '../../ui/media-element';
|
||||
import { MediaContainerElement } from '../../media/container-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
const ContainerMixin = createContainerMixin(playerContext);
|
||||
|
||||
export class MediaContainerElement extends ContainerMixin(MediaElement) {
|
||||
static readonly tagName = 'media-container';
|
||||
}
|
||||
|
||||
customElements.define(MediaContainerElement.tagName, MediaContainerElement);
|
||||
safeDefine(MediaContainerElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { HlsVideo } from '../../media/hls-video';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
export class HlsVideoElement extends HlsVideo {
|
||||
static readonly tagName = 'hls-video';
|
||||
}
|
||||
|
||||
customElements.define(HlsVideoElement.tagName, HlsVideoElement);
|
||||
safeDefine(HlsVideoElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
type DefinableElement = CustomElementConstructor & { tagName: string };
|
||||
|
||||
/** Define a custom element only if not already registered. */
|
||||
export function safeDefine(element: DefinableElement): void {
|
||||
if (!customElements.get(element.tagName)) {
|
||||
customElements.define(element.tagName, element);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
import { afterAll, beforeAll, describe, expect, it, type MockInstance, vi } from 'vitest';
|
||||
|
||||
/**
|
||||
* Tests that composite define files register all expected custom elements
|
||||
* and that provider/parent elements are defined before consumer/child elements.
|
||||
*
|
||||
* Tests run sequentially. Each dynamically imports a composite define file and
|
||||
* checks the batch of `customElements.define()` calls that resulted. Because
|
||||
* modules are cached within a test file, shared sub-elements (e.g. slider parts)
|
||||
* are only registered by the first composite that imports them — subsequent
|
||||
* composites skip them via `safeDefine`. This is intentional and tested.
|
||||
*/
|
||||
describe('composite define registration', () => {
|
||||
let spy: MockInstance;
|
||||
|
||||
/** Tag names registered since `offset` (the call count before an import). */
|
||||
function batchSince(offset: number): string[] {
|
||||
return spy.mock.calls.slice(offset).map((call) => call[0] as string);
|
||||
}
|
||||
|
||||
beforeAll(() => {
|
||||
spy = vi.spyOn(customElements, 'define');
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
spy.mockRestore();
|
||||
});
|
||||
|
||||
// ── Player composites ────────────────────────────────────────────────
|
||||
|
||||
describe('video/player', () => {
|
||||
it('registers video-player before media-container', async () => {
|
||||
const before = spy.mock.calls.length;
|
||||
await import('../video/player');
|
||||
const batch = batchSince(before);
|
||||
|
||||
expect(batch).toContain('video-player');
|
||||
expect(batch).toContain('media-container');
|
||||
expect(batch.indexOf('video-player')).toBeLessThan(batch.indexOf('media-container'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('audio/player', () => {
|
||||
it('registers audio-player', async () => {
|
||||
const before = spy.mock.calls.length;
|
||||
await import('../audio/player');
|
||||
const batch = batchSince(before);
|
||||
|
||||
expect(batch).toContain('audio-player');
|
||||
// media-container already registered by video/player — safeDefine skips it
|
||||
expect(batch).not.toContain('media-container');
|
||||
});
|
||||
});
|
||||
|
||||
describe('background/player', () => {
|
||||
it('registers background-video-player', async () => {
|
||||
const before = spy.mock.calls.length;
|
||||
await import('../background/player');
|
||||
const batch = batchSince(before);
|
||||
|
||||
expect(batch).toContain('background-video-player');
|
||||
expect(batch).not.toContain('media-container');
|
||||
});
|
||||
});
|
||||
|
||||
// ── Slider composites ────────────────────────────────────────────────
|
||||
|
||||
describe('ui/time-slider', () => {
|
||||
it('registers media-time-slider before sub-elements', async () => {
|
||||
const before = spy.mock.calls.length;
|
||||
await import('../ui/time-slider');
|
||||
const batch = batchSince(before);
|
||||
|
||||
// Parent slider must be first (provider for sliderContext)
|
||||
expect(batch[0]).toBe('media-time-slider');
|
||||
|
||||
// All sub-elements registered (first composite to claim them)
|
||||
expect(batch).toContain('media-slider-buffer');
|
||||
expect(batch).toContain('media-slider-fill');
|
||||
expect(batch).toContain('media-slider-thumb');
|
||||
expect(batch).toContain('media-slider-track');
|
||||
expect(batch).toContain('media-slider-value');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ui/volume-slider', () => {
|
||||
it('registers media-volume-slider and skips already-defined sub-elements', async () => {
|
||||
const before = spy.mock.calls.length;
|
||||
await import('../ui/volume-slider');
|
||||
const batch = batchSince(before);
|
||||
|
||||
expect(batch).toContain('media-volume-slider');
|
||||
|
||||
// Sub-elements already registered by time-slider — safeDefine skips them
|
||||
expect(batch).not.toContain('media-slider-fill');
|
||||
expect(batch).not.toContain('media-slider-thumb');
|
||||
expect(batch).not.toContain('media-slider-track');
|
||||
expect(batch).not.toContain('media-slider-value');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ui/slider', () => {
|
||||
it('registers media-slider', async () => {
|
||||
const before = spy.mock.calls.length;
|
||||
await import('../ui/slider');
|
||||
const batch = batchSince(before);
|
||||
|
||||
expect(batch).toContain('media-slider');
|
||||
});
|
||||
});
|
||||
|
||||
// ── Other composites ─────────────────────────────────────────────────
|
||||
|
||||
describe('ui/time', () => {
|
||||
it('registers media-time before sub-elements', async () => {
|
||||
const before = spy.mock.calls.length;
|
||||
await import('../ui/time');
|
||||
const batch = batchSince(before);
|
||||
|
||||
expect(batch[0]).toBe('media-time');
|
||||
expect(batch).toContain('media-time-group');
|
||||
expect(batch).toContain('media-time-separator');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ui/controls', () => {
|
||||
it('registers media-controls before sub-elements', async () => {
|
||||
const before = spy.mock.calls.length;
|
||||
await import('../ui/controls');
|
||||
const batch = batchSince(before);
|
||||
|
||||
expect(batch[0]).toBe('media-controls');
|
||||
expect(batch).toContain('media-controls-group');
|
||||
});
|
||||
});
|
||||
|
||||
// ── Final state ──────────────────────────────────────────────────────
|
||||
|
||||
describe('registry completeness', () => {
|
||||
it('all expected elements are registered after importing all composites', () => {
|
||||
const expected = [
|
||||
// Players + container
|
||||
'video-player',
|
||||
'audio-player',
|
||||
'background-video-player',
|
||||
'media-container',
|
||||
// Sliders
|
||||
'media-slider',
|
||||
'media-time-slider',
|
||||
'media-volume-slider',
|
||||
// Slider sub-elements
|
||||
'media-slider-buffer',
|
||||
'media-slider-fill',
|
||||
'media-slider-thumb',
|
||||
'media-slider-track',
|
||||
'media-slider-value',
|
||||
// Time
|
||||
'media-time',
|
||||
'media-time-group',
|
||||
'media-time-separator',
|
||||
// Controls
|
||||
'media-controls',
|
||||
'media-controls-group',
|
||||
];
|
||||
|
||||
for (const tagName of expected) {
|
||||
expect(customElements.get(tagName), `${tagName} should be registered`).toBeDefined();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
describe('safeDefine', () => {
|
||||
it('registers a custom element', () => {
|
||||
class TestElement extends HTMLElement {
|
||||
static tagName = 'test-sd-register';
|
||||
}
|
||||
|
||||
expect(customElements.get('test-sd-register')).toBeUndefined();
|
||||
safeDefine(TestElement);
|
||||
expect(customElements.get('test-sd-register')).toBe(TestElement);
|
||||
});
|
||||
|
||||
it('does not throw when element is already registered', () => {
|
||||
class TestElement extends HTMLElement {
|
||||
static tagName = 'test-sd-no-throw';
|
||||
}
|
||||
|
||||
customElements.define('test-sd-no-throw', TestElement);
|
||||
expect(() => safeDefine(TestElement)).not.toThrow();
|
||||
});
|
||||
|
||||
it('does not replace an existing registration', () => {
|
||||
class Original extends HTMLElement {
|
||||
static tagName = 'test-sd-no-replace';
|
||||
}
|
||||
class Replacement extends HTMLElement {
|
||||
static tagName = 'test-sd-no-replace';
|
||||
}
|
||||
|
||||
safeDefine(Original);
|
||||
safeDefine(Replacement);
|
||||
expect(customElements.get('test-sd-no-replace')).toBe(Original);
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
import { BufferingIndicatorElement } from '../../ui/buffering-indicator/buffering-indicator-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(BufferingIndicatorElement.tagName, BufferingIndicatorElement);
|
||||
safeDefine(BufferingIndicatorElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ControlsGroupElement } from '../../ui/controls/controls-group-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(ControlsGroupElement.tagName, ControlsGroupElement);
|
||||
safeDefine(ControlsGroupElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { ControlsElement } from '../../ui/controls/controls-element';
|
||||
import { ControlsGroupElement } from '../../ui/controls/controls-group-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
import './controls-group';
|
||||
|
||||
customElements.define(ControlsElement.tagName, ControlsElement);
|
||||
safeDefine(ControlsElement);
|
||||
safeDefine(ControlsGroupElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { FullscreenButtonElement } from '../../ui/fullscreen-button/fullscreen-button-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(FullscreenButtonElement.tagName, FullscreenButtonElement);
|
||||
safeDefine(FullscreenButtonElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { MuteButtonElement } from '../../ui/mute-button/mute-button-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(MuteButtonElement.tagName, MuteButtonElement);
|
||||
safeDefine(MuteButtonElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { PiPButtonElement } from '../../ui/pip-button/pip-button-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(PiPButtonElement.tagName, PiPButtonElement);
|
||||
safeDefine(PiPButtonElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { PlayButtonElement } from '../../ui/play-button/play-button-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(PlayButtonElement.tagName, PlayButtonElement);
|
||||
safeDefine(PlayButtonElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { PlaybackRateButtonElement } from '../../ui/playback-rate-button/playback-rate-button-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(PlaybackRateButtonElement.tagName, PlaybackRateButtonElement);
|
||||
safeDefine(PlaybackRateButtonElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { PopoverElement } from '../../ui/popover/popover-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(PopoverElement.tagName, PopoverElement);
|
||||
safeDefine(PopoverElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { PosterElement } from '../../ui/poster/poster-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(PosterElement.tagName, PosterElement);
|
||||
safeDefine(PosterElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { SeekButtonElement } from '../../ui/seek-button/seek-button-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(SeekButtonElement.tagName, SeekButtonElement);
|
||||
safeDefine(SeekButtonElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { SliderBufferElement } from '../../ui/slider/slider-buffer-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(SliderBufferElement.tagName, SliderBufferElement);
|
||||
safeDefine(SliderBufferElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { SliderFillElement } from '../../ui/slider/slider-fill-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(SliderFillElement.tagName, SliderFillElement);
|
||||
safeDefine(SliderFillElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { SliderThumbElement } from '../../ui/slider/slider-thumb-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(SliderThumbElement.tagName, SliderThumbElement);
|
||||
safeDefine(SliderThumbElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { SliderTrackElement } from '../../ui/slider/slider-track-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(SliderTrackElement.tagName, SliderTrackElement);
|
||||
safeDefine(SliderTrackElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { SliderValueElement } from '../../ui/slider/slider-value-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(SliderValueElement.tagName, SliderValueElement);
|
||||
safeDefine(SliderValueElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { SliderElement } from '../../ui/slider/slider-element';
|
||||
import { SliderFillElement } from '../../ui/slider/slider-fill-element';
|
||||
import { SliderThumbElement } from '../../ui/slider/slider-thumb-element';
|
||||
import { SliderTrackElement } from '../../ui/slider/slider-track-element';
|
||||
import { SliderValueElement } from '../../ui/slider/slider-value-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
import './slider-fill';
|
||||
import './slider-thumb';
|
||||
import './slider-track';
|
||||
import './slider-value';
|
||||
|
||||
customElements.define(SliderElement.tagName, SliderElement);
|
||||
// Parent slider first — sub-elements consume its context.
|
||||
safeDefine(SliderElement);
|
||||
safeDefine(SliderFillElement);
|
||||
safeDefine(SliderThumbElement);
|
||||
safeDefine(SliderTrackElement);
|
||||
safeDefine(SliderValueElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ThumbnailElement } from '../../ui/thumbnail/thumbnail-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(ThumbnailElement.tagName, ThumbnailElement);
|
||||
safeDefine(ThumbnailElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { TimeGroupElement } from '../../ui/time/time-group-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(TimeGroupElement.tagName, TimeGroupElement);
|
||||
safeDefine(TimeGroupElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { TimeSeparatorElement } from '../../ui/time/time-separator-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
customElements.define(TimeSeparatorElement.tagName, TimeSeparatorElement);
|
||||
safeDefine(TimeSeparatorElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import { SliderBufferElement } from '../../ui/slider/slider-buffer-element';
|
||||
import { SliderFillElement } from '../../ui/slider/slider-fill-element';
|
||||
import { SliderThumbElement } from '../../ui/slider/slider-thumb-element';
|
||||
import { SliderTrackElement } from '../../ui/slider/slider-track-element';
|
||||
import { SliderValueElement } from '../../ui/slider/slider-value-element';
|
||||
import { TimeSliderElement } from '../../ui/time-slider/time-slider-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
import './slider-buffer';
|
||||
import './slider-fill';
|
||||
import './slider-thumb';
|
||||
import './slider-track';
|
||||
import './slider-value';
|
||||
|
||||
customElements.define(TimeSliderElement.tagName, TimeSliderElement);
|
||||
// Parent slider first — sub-elements consume its context.
|
||||
safeDefine(TimeSliderElement);
|
||||
safeDefine(SliderBufferElement);
|
||||
safeDefine(SliderFillElement);
|
||||
safeDefine(SliderThumbElement);
|
||||
safeDefine(SliderTrackElement);
|
||||
safeDefine(SliderValueElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { TimeElement } from '../../ui/time/time-element';
|
||||
import { TimeGroupElement } from '../../ui/time/time-group-element';
|
||||
import { TimeSeparatorElement } from '../../ui/time/time-separator-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
import './time-group';
|
||||
import './time-separator';
|
||||
|
||||
customElements.define(TimeElement.tagName, TimeElement);
|
||||
safeDefine(TimeElement);
|
||||
safeDefine(TimeGroupElement);
|
||||
safeDefine(TimeSeparatorElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { SliderFillElement } from '../../ui/slider/slider-fill-element';
|
||||
import { SliderThumbElement } from '../../ui/slider/slider-thumb-element';
|
||||
import { SliderTrackElement } from '../../ui/slider/slider-track-element';
|
||||
import { SliderValueElement } from '../../ui/slider/slider-value-element';
|
||||
import { VolumeSliderElement } from '../../ui/volume-slider/volume-slider-element';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
import './slider-fill';
|
||||
import './slider-thumb';
|
||||
import './slider-track';
|
||||
import './slider-value';
|
||||
|
||||
customElements.define(VolumeSliderElement.tagName, VolumeSliderElement);
|
||||
// Parent slider first — sub-elements consume its context.
|
||||
safeDefine(VolumeSliderElement);
|
||||
safeDefine(SliderFillElement);
|
||||
safeDefine(SliderThumbElement);
|
||||
safeDefine(SliderTrackElement);
|
||||
safeDefine(SliderValueElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { videoFeatures } from '@videojs/core/dom';
|
||||
import { MediaContainerElement } from '../../media/container-element';
|
||||
import { createPlayer } from '../../player/create-player';
|
||||
import { MediaElement } from '../../ui/media-element';
|
||||
import '../media/container';
|
||||
import { safeDefine } from '../safe-define';
|
||||
|
||||
const { ProviderMixin } = createPlayer({
|
||||
features: videoFeatures,
|
||||
@@ -11,7 +12,9 @@ export class VideoPlayerElement extends ProviderMixin(MediaElement) {
|
||||
static readonly tagName = 'video-player';
|
||||
}
|
||||
|
||||
customElements.define(VideoPlayerElement.tagName, VideoPlayerElement);
|
||||
// Provider must be defined before consumer for context handshake during upgrade.
|
||||
safeDefine(VideoPlayerElement);
|
||||
safeDefine(MediaContainerElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
||||
@@ -4,7 +4,8 @@ export * from '@videojs/core/dom';
|
||||
// Store
|
||||
export type { Comparator, Selector } from '@videojs/store';
|
||||
export { createSelector, shallowEqual } from '@videojs/store';
|
||||
|
||||
// Media
|
||||
export { MediaContainerElement } from './media/container-element';
|
||||
// Player
|
||||
export * from './player/context';
|
||||
export * from './player/create-player';
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { playerContext } from '../player/context';
|
||||
import { createContainerMixin } from '../store/container-mixin';
|
||||
import { MediaElement } from '../ui/media-element';
|
||||
|
||||
const ContainerMixin = createContainerMixin(playerContext);
|
||||
|
||||
export class MediaContainerElement extends ContainerMixin(MediaElement) {
|
||||
static readonly tagName = 'media-container';
|
||||
}
|
||||
@@ -7,10 +7,12 @@ type BuildMode = 'dev' | 'default';
|
||||
const buildModes: BuildMode[] = ['dev', 'default'];
|
||||
|
||||
const defineEntries = Object.fromEntries(
|
||||
globSync('src/define/**/*.ts').map((file) => {
|
||||
const key = file.replace('src/', '').replace('.ts', '');
|
||||
return [key, file];
|
||||
})
|
||||
globSync('src/define/**/*.ts')
|
||||
.filter((file) => !file.includes('.test.'))
|
||||
.map((file) => {
|
||||
const key = file.replace('src/', '').replace('.ts', '');
|
||||
return [key, file];
|
||||
})
|
||||
);
|
||||
|
||||
const presetEntries = Object.fromEntries(
|
||||
|
||||
Reference in New Issue
Block a user