feat(core): add thumbnail component and text track store feature (#643)

This commit is contained in:
rahim
2026-02-27 15:19:11 -08:00
committed by GitHub
parent 2581699877
commit 7bae887920
20 changed files with 1488 additions and 0 deletions
+1
View File
@@ -8,5 +8,6 @@ export { isHTMLAudioElement, isHTMLMediaElement, isHTMLVideoElement } from './pr
export { type RafThrottled, rafThrottle } from './raf-throttle';
export { getSlottedElement, querySlot } from './slotted';
export { supportsAnimationFrame, supportsIdleCallback } from './supports';
export { findTrackElement } from './text-track';
export { serializeTimeRanges } from './time-ranges';
export type { CustomElement, CustomElementCallbacks } from './types';
@@ -0,0 +1,62 @@
import { describe, expect, it } from 'vitest';
import { findTrackElement } from '../text-track';
/**
* jsdom does not create unique TextTrack objects per <track> element,
* so we mock the `.track` property to simulate real browser behavior.
*/
function mockTrackProperty(el: HTMLTrackElement): TextTrack {
const track = {} as TextTrack;
Object.defineProperty(el, 'track', { value: track, configurable: true });
return track;
}
describe('findTrackElement', () => {
it('returns the track element that owns the given TextTrack', () => {
const video = document.createElement('video');
const el = document.createElement('track');
const track = mockTrackProperty(el);
video.appendChild(el);
expect(findTrackElement(video, track)).toBe(el);
});
it('returns null when no track element matches', () => {
const video = document.createElement('video');
const el = document.createElement('track');
mockTrackProperty(el);
video.appendChild(el);
const unmatchedTrack = {} as TextTrack;
expect(findTrackElement(video, unmatchedTrack)).toBeNull();
});
it('returns null when there are no track elements', () => {
const video = document.createElement('video');
const unmatchedTrack = {} as TextTrack;
expect(findTrackElement(video, unmatchedTrack)).toBeNull();
});
it('finds the correct track among multiple track elements', () => {
const video = document.createElement('video');
const captionsEl = document.createElement('track');
const captionsTrack = mockTrackProperty(captionsEl);
video.appendChild(captionsEl);
const thumbnailsEl = document.createElement('track');
const thumbnailsTrack = mockTrackProperty(thumbnailsEl);
video.appendChild(thumbnailsEl);
const chaptersEl = document.createElement('track');
const chaptersTrack = mockTrackProperty(chaptersEl);
video.appendChild(chaptersEl);
expect(findTrackElement(video, thumbnailsTrack)).toBe(thumbnailsEl);
expect(findTrackElement(video, captionsTrack)).toBe(captionsEl);
expect(findTrackElement(video, chaptersTrack)).toBe(chaptersEl);
});
});
+7
View File
@@ -0,0 +1,7 @@
/** Find the `<track>` element that owns the given `TextTrack`. */
export function findTrackElement(media: HTMLMediaElement, track: TextTrack): HTMLTrackElement | null {
for (const el of media.querySelectorAll('track')) {
if (el.track === track) return el;
}
return null;
}