@fusion.dev/helix-headless 0.26.0 → 0.30.0

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 (89) hide show
  1. package/custom-elements.json +4966 -755
  2. package/dist/accordion/root/accordion-root.d.ts +5 -6
  3. package/dist/accordion/root/accordion-root.js +13 -36
  4. package/dist/announcement/root/announcement-root.js +1 -1
  5. package/dist/avatar/root/avatar-root.d.ts +17 -3
  6. package/dist/avatar/root/avatar-root.js +27 -8
  7. package/dist/blockquote/root/blockquote-root.js +1 -1
  8. package/dist/button/root/button-root.js +1 -1
  9. package/dist/carousel/root/carousel-root.js +2 -2
  10. package/dist/chat/root/chat-root.js +1 -1
  11. package/dist/checkbox/root/checkbox-root.js +2 -2
  12. package/dist/checkbox-group/root/checkbox-group-root.js +2 -2
  13. package/dist/color-input/root/color-input-root.d.ts +12 -14
  14. package/dist/color-input/root/color-input-root.js +4 -52
  15. package/dist/color-picker/root/color-picker-root.js +2 -2
  16. package/dist/combobox/root/combobox-root.js +11 -14
  17. package/dist/command/root/command-root.js +2 -3
  18. package/dist/data-table/root/data-table-root.js +1 -1
  19. package/dist/date-input/root/date-input-root.d.ts +5 -77
  20. package/dist/date-input/root/date-input-root.js +16 -108
  21. package/dist/date-picker/root/date-picker-root.js +2 -2
  22. package/dist/divider/root/divider-root.js +1 -1
  23. package/dist/drawer/root/drawer-root.js +1 -1
  24. package/dist/drilldown/item/drilldown-item.js +1 -1
  25. package/dist/file-input/root/file-input-root.js +4 -7
  26. package/dist/filter-input/field/filter-field.d.ts +1 -1
  27. package/dist/filter-input/root/filter-input-root.d.ts +2 -2
  28. package/dist/filter-input/root/filter-input-root.js +12 -15
  29. package/dist/heatmap/root/heatmap-root.js +1 -1
  30. package/dist/image/root/image-root.d.ts +7 -0
  31. package/dist/image/root/image-root.js +6 -2
  32. package/dist/input/root/input-root.js +3 -3
  33. package/dist/listbox/root/listbox-root.js +3 -3
  34. package/dist/megamenu/root/megamenu-root.d.ts +12 -2
  35. package/dist/megamenu/root/megamenu-root.js +20 -15
  36. package/dist/menu/item/menu-item.js +1 -1
  37. package/dist/menu/root/menu-root.js +3 -10
  38. package/dist/navigation/root/navigation-root.d.ts +1 -2
  39. package/dist/navigation/root/navigation-root.js +3 -9
  40. package/dist/number-input/root/number-input-root.js +5 -5
  41. package/dist/object-inspector/root/object-inspector-root.js +4 -4
  42. package/dist/outline/root/outline-root.d.ts +0 -1
  43. package/dist/outline/root/outline-root.js +6 -12
  44. package/dist/pin-input/root/pin-input-root.js +2 -2
  45. package/dist/popover/root/popover-root.js +2 -10
  46. package/dist/radio/root/radio-root.js +1 -1
  47. package/dist/scatter-chart/root/scatter-chart-root.js +1 -1
  48. package/dist/scroll-area/root/scroll-area-root.js +1 -1
  49. package/dist/select/root/select-root.js +8 -9
  50. package/dist/slider/root/slider-root.js +2 -2
  51. package/dist/sparkline/root/sparkline-root.d.ts +2 -1
  52. package/dist/sparkline/root/sparkline-root.js +2 -2
  53. package/dist/speed-dial/item/speed-dial-item.js +1 -1
  54. package/dist/speed-dial/root/speed-dial-root.d.ts +2 -2
  55. package/dist/speed-dial/root/speed-dial-root.js +4 -7
  56. package/dist/switch/root/switch-root.js +3 -3
  57. package/dist/table/column/table-column.js +1 -1
  58. package/dist/tabs/root/tabs-root.d.ts +2 -17
  59. package/dist/tabs/root/tabs-root.js +3 -21
  60. package/dist/tabs/tab/tab.js +1 -1
  61. package/dist/textarea/root/textarea-root.js +3 -3
  62. package/dist/time-input/root/time-input-root.d.ts +5 -64
  63. package/dist/time-input/root/time-input-root.js +15 -107
  64. package/dist/time-picker/root/time-picker-root.js +2 -2
  65. package/dist/toggle/group/toggle-group.d.ts +0 -13
  66. package/dist/toggle/group/toggle-group.js +3 -23
  67. package/dist/toggle/root/toggle-root.js +1 -1
  68. package/dist/tooltip/root/tooltip-root.d.ts +0 -13
  69. package/dist/tooltip/root/tooltip-root.js +8 -16
  70. package/dist/tour/root/tour-root.js +6 -6
  71. package/dist/tour/stop/tour-stop.js +2 -2
  72. package/dist/video/root/captions.d.ts +85 -0
  73. package/dist/video/root/captions.js +45 -0
  74. package/dist/video/root/fullscreen.d.ts +28 -0
  75. package/dist/video/root/fullscreen.js +28 -0
  76. package/dist/video/root/idle.d.ts +34 -0
  77. package/dist/video/root/idle.js +24 -0
  78. package/dist/video/root/media-session.d.ts +54 -0
  79. package/dist/video/root/media-session.js +49 -0
  80. package/dist/video/root/remote-playback.d.ts +34 -0
  81. package/dist/video/root/remote-playback.js +38 -0
  82. package/dist/video/root/video-root.d.ts +11 -89
  83. package/dist/video/root/video-root.js +45 -139
  84. package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -1
  85. package/dist/video-playlist/menu/video-playlist-menu.js +8 -10
  86. package/dist/virtual-list/root/virtual-list-root.js +1 -1
  87. package/package.json +8 -7
  88. package/types/jsx.d.ts +264 -192
  89. package/types/vue.d.ts +78 -69
@@ -22,10 +22,10 @@ let HelixHeadlessTourStop = class HelixHeadlessTourStop extends HelixElement {
22
22
  this.skipLabel = 'Skip';
23
23
  this.floating = new PopoverController(this, {
24
24
  anchor: () => this.target,
25
- arrow: () => this.renderRoot?.querySelector('[part="arrow"]'),
25
+ arrow: () => this.partNamed('arrow'),
26
26
  onDismiss: () => { },
27
27
  placement: () => this.placement,
28
- surface: () => this.renderRoot?.querySelector('[part="bubble"]'),
28
+ surface: () => this.partNamed('bubble'),
29
29
  });
30
30
  }
31
31
  get target() {
@@ -0,0 +1,85 @@
1
+ import type { ReactiveController, ReactiveControllerHost } from 'lit';
2
+ /** One caption track, named as the menu names it. */
3
+ export interface Caption {
4
+ label: string;
5
+ language: string;
6
+ }
7
+ /** A `<track>` as the consumer wrote it, reduced to what naming it needs. */
8
+ interface TrackCopy {
9
+ attrs: Record<string, string>;
10
+ tag: string;
11
+ }
12
+ /**
13
+ * The tracks a reader could choose between, in the order they were written.
14
+ *
15
+ * Filtered by kind, because `textTracks` also carries `chapters`, `metadata`
16
+ * and `descriptions`, and a menu offering "Chapters" as a subtitle language
17
+ * would be offering something that draws no words. Read off the video rather
18
+ * than off the slot: a `<track>` added later is in one and not the other, and
19
+ * the video is the one that has resolved them.
20
+ */
21
+ export declare const captionTracks: (video: HTMLVideoElement | null) => TextTrack[];
22
+ /**
23
+ * Shows one track and disables every other, or shows none at `-1`.
24
+ *
25
+ * Every other, rather than only the one that was on. Two tracks in `hidden`
26
+ * both fire `cuechange`, so the rendered cue becomes whichever fired last and
27
+ * a reader who switched language gets the two interleaved. Measured as two
28
+ * subtitles alternating line by line.
29
+ *
30
+ * `hidden`, never `showing`. Hidden is the mode where a track still fires
31
+ * `cuechange` and still fills `activeCues`, and the browser draws nothing,
32
+ * which is exactly what is wanted when something else is doing the drawing.
33
+ */
34
+ export declare const showCaption: (tracks: readonly TextTrack[], index: number) => void;
35
+ /**
36
+ * Whether a track the platform started showing is now ours to draw.
37
+ *
38
+ * A `<track default>` arrives `showing`, which is the browser drawing it.
39
+ * Moved to `hidden` so the cues keep coming and we draw them instead. What
40
+ * comes back is whether captions are on, which is not always "off": a button
41
+ * that began there reported the opposite of what was on screen.
42
+ */
43
+ export declare const adoptTrack: (track: TextTrack) => boolean;
44
+ /**
45
+ * The caption tracks among the copies, before the render that draws them.
46
+ *
47
+ * By the platform's own reading of `kind`, which is what makes a `<track>` a
48
+ * caption at all: missing is `subtitles` and anything it does not know is
49
+ * `metadata`. Read from the video's tracks after the render instead, the count
50
+ * arrived a render late and asked for one more. Choosing one still goes
51
+ * through the video's tracks, which hold them in the same order.
52
+ */
53
+ export declare const captionsAmong: (media: readonly TrackCopy[]) => Caption[];
54
+ /**
55
+ * The cue on screen now, as nodes, or nothing between cues.
56
+ *
57
+ * Nodes rather than a string, because `VTTCue.text` is the cue's *source*:
58
+ * WebVTT carries markup, and a caption file in the wild is full of it. `<v
59
+ * Hildy>` names who is speaking, `<b>` and `<i>` and `<u>` mark emphasis, and
60
+ * `<c.loud>` classes a line. Rendered as text every one of those arrives on
61
+ * screen as visible angle brackets.
62
+ *
63
+ * `getCueAsHTML` is the platform parsing its own format, so nothing here has
64
+ * to know the grammar and no cue text is ever treated as HTML: what comes
65
+ * back is a fragment the browser built, not a string anybody interpolated.
66
+ */
67
+ export declare const activeCue: (track: TextTrack | undefined) => DocumentFragment | undefined;
68
+ /**
69
+ * Listens to one track's cues at a time, so the next one can take it off.
70
+ *
71
+ * Taken off whatever it was on before adding it here. `follow` runs from
72
+ * `loadedmetadata`, which fires again for every source a reader moves to, and
73
+ * a consumer adding a `<track>` later gets another. Added without removing, a
74
+ * playlist of six left six listeners on tracks that between them fire for
75
+ * every cue in the video.
76
+ */
77
+ export declare class CueController implements ReactiveController {
78
+ private readonly listener;
79
+ private track;
80
+ constructor(host: ReactiveControllerHost, listener: () => void);
81
+ follow(track: TextTrack): void;
82
+ hostDisconnected(): void;
83
+ private stop;
84
+ }
85
+ export {};
@@ -0,0 +1,45 @@
1
+ export const captionTracks = (video) => {
2
+ const tracks = video?.textTracks;
3
+ if (!tracks) {
4
+ return [];
5
+ }
6
+ return [...tracks].filter((one) => one.kind === 'subtitles' || one.kind === 'captions');
7
+ };
8
+ export const showCaption = (tracks, index) => {
9
+ tracks.forEach((track, at) => {
10
+ track.mode = at === index ? 'hidden' : 'disabled';
11
+ });
12
+ };
13
+ export const adoptTrack = (track) => {
14
+ if (track.mode === 'showing') {
15
+ track.mode = 'hidden';
16
+ }
17
+ return track.mode === 'hidden';
18
+ };
19
+ export const captionsAmong = (media) => media
20
+ .filter((one) => one.tag === 'track' &&
21
+ (one.attrs.kind === undefined ||
22
+ ['captions', 'subtitles'].includes(one.attrs.kind.toLowerCase())))
23
+ .map((one) => ({ label: one.attrs.label ?? '', language: one.attrs.srclang ?? '' }));
24
+ export const activeCue = (track) => {
25
+ const active = track?.activeCues?.[0];
26
+ return active instanceof VTTCue ? active.getCueAsHTML() : undefined;
27
+ };
28
+ export class CueController {
29
+ constructor(host, listener) {
30
+ this.listener = listener;
31
+ host.addController(this);
32
+ }
33
+ follow(track) {
34
+ this.stop();
35
+ this.track = track;
36
+ track.addEventListener('cuechange', this.listener);
37
+ }
38
+ hostDisconnected() {
39
+ this.stop();
40
+ }
41
+ stop() {
42
+ this.track?.removeEventListener('cuechange', this.listener);
43
+ this.track = undefined;
44
+ }
45
+ }
@@ -0,0 +1,28 @@
1
+ import type { ReactiveController, ReactiveControllerHost } from 'lit';
2
+ /**
3
+ * Into fullscreen and back, and honest about where the element is.
4
+ *
5
+ * The state follows `fullscreenchange` rather than the request, so a refused
6
+ * request leaves a button that correctly reports "not fullscreen".
7
+ */
8
+ export declare class FullscreenController implements ReactiveController {
9
+ private readonly host;
10
+ private readonly report;
11
+ constructor(host: ReactiveControllerHost & HTMLElement, report: (full: boolean) => void);
12
+ /**
13
+ * Into fullscreen and back, and quiet about being refused.
14
+ *
15
+ * `requestFullscreen` rejects rather than returning false, and the two
16
+ * refusals a consumer will actually meet are a Permissions Policy that does
17
+ * not grant `fullscreen` to the frame the player is in, and a call without
18
+ * user activation. Both are `TypeError: Permissions check failed`, which is
19
+ * the same message for two different causes.
20
+ *
21
+ * Caught rather than `void`ed, or a refusal becomes an unhandled rejection
22
+ * naming neither the element nor the reason.
23
+ */
24
+ toggle(): Promise<void>;
25
+ hostConnected(): void;
26
+ hostDisconnected(): void;
27
+ private readonly handleChange;
28
+ }
@@ -0,0 +1,28 @@
1
+ export class FullscreenController {
2
+ constructor(host, report) {
3
+ this.host = host;
4
+ this.report = report;
5
+ this.handleChange = () => {
6
+ this.report(document.fullscreenElement === this.host);
7
+ };
8
+ host.addController(this);
9
+ }
10
+ async toggle() {
11
+ try {
12
+ if (document.fullscreenElement === this.host) {
13
+ await document.exitFullscreen();
14
+ return;
15
+ }
16
+ await this.host.requestFullscreen();
17
+ }
18
+ catch (error) {
19
+ console.warn(`<${this.host.localName}> could not enter fullscreen. If it is inside an iframe, that frame needs allow="fullscreen".`, error);
20
+ }
21
+ }
22
+ hostConnected() {
23
+ document.addEventListener('fullscreenchange', this.handleChange);
24
+ }
25
+ hostDisconnected() {
26
+ document.removeEventListener('fullscreenchange', this.handleChange);
27
+ }
28
+ }
@@ -0,0 +1,34 @@
1
+ import type { ReactiveController, ReactiveControllerHost } from 'lit';
2
+ /**
3
+ * How long the reader has been still, which decides when the bar goes.
4
+ *
5
+ * A wait rather than leaving with the pointer, or a reader moving across the
6
+ * picture to reach a control watches the bar vanish under them. The wait is
7
+ * only ever about *idling*: whether a paused video keeps its bar is the
8
+ * element's decision, and this only says when the reader stopped.
9
+ *
10
+ * The delay is asked for on every restart rather than taken once, because it
11
+ * is a property the consumer can change while the video plays.
12
+ */
13
+ export declare class IdleController implements ReactiveController {
14
+ private readonly delay;
15
+ private readonly report;
16
+ private timer;
17
+ constructor(host: ReactiveControllerHost, delay: () => number, report: (idle: boolean) => void);
18
+ /**
19
+ * Restarts the wait, on anything that counts as the reader being here.
20
+ *
21
+ * Pointer movement and focus both count, and both have to: a reader using the
22
+ * keyboard never moves a pointer, and a bar that only answered the mouse
23
+ * would leave them nothing to look at. Zero turns the wait off and the bar
24
+ * goes immediately; a large number keeps it up for as long as anyone is
25
+ * likely to look.
26
+ */
27
+ readonly stir: () => void;
28
+ /**
29
+ * Leaving is the one case that does not wait: the reader has gone somewhere
30
+ * else, and there is nothing to reach for.
31
+ */
32
+ readonly leave: () => void;
33
+ hostDisconnected(): void;
34
+ }
@@ -0,0 +1,24 @@
1
+ export class IdleController {
2
+ constructor(host, delay, report) {
3
+ this.delay = delay;
4
+ this.report = report;
5
+ this.stir = () => {
6
+ this.report(false);
7
+ clearTimeout(this.timer);
8
+ const delay = this.delay();
9
+ if (delay > 0) {
10
+ this.timer = setTimeout(() => {
11
+ this.report(true);
12
+ }, delay);
13
+ }
14
+ };
15
+ this.leave = () => {
16
+ clearTimeout(this.timer);
17
+ this.report(true);
18
+ };
19
+ host.addController(this);
20
+ }
21
+ hostDisconnected() {
22
+ clearTimeout(this.timer);
23
+ }
24
+ }
@@ -0,0 +1,54 @@
1
+ import type { ReactiveController, ReactiveControllerHost } from 'lit';
2
+ /**
3
+ * How far a skip control moves, in seconds.
4
+ *
5
+ * Ten, which is the number every player that has one uses, and the number the
6
+ * platform names in `seekbackward` and `seekforward` when it hands over a
7
+ * default. A different length here would be correct only on this player.
8
+ */
9
+ export declare const SKIP_SECONDS = 10;
10
+ /** What a headset's buttons do, handed over by the player that owns them. */
11
+ export interface SessionHandlers {
12
+ /**
13
+ * Asks for the next item, or `null` where the consumer has named nothing to
14
+ * skip to: the platform draws the key from whether a handler is set.
15
+ */
16
+ next: (() => void) | null;
17
+ /** And the previous one, under the same rule. */
18
+ previous: (() => void) | null;
19
+ seek: (seconds: number) => void;
20
+ skipBy: (seconds: number) => void;
21
+ toggle: () => void;
22
+ }
23
+ /**
24
+ * Holds the page's media session for one player, and tells the platform what
25
+ * is playing.
26
+ *
27
+ * The handlers are what make a headset's play, pause and skip work at all.
28
+ * Without them a platform falls back to guessing which element was meant,
29
+ * which is right often enough to hide the fault and wrong exactly when there
30
+ * are two.
31
+ */
32
+ export declare class MediaSessionController implements ReactiveController {
33
+ private readonly host;
34
+ constructor(host: ReactiveControllerHost & HTMLElement);
35
+ /**
36
+ * Takes the session.
37
+ *
38
+ * On play rather than on render, which is the ownership rule: a page with two
39
+ * players gives the session to whichever one the reader started, so a
40
+ * headset's buttons land on what they are listening to rather than on
41
+ * whichever came first in the markup.
42
+ */
43
+ claim(metadata: {
44
+ artwork: string;
45
+ title: string;
46
+ }, handlers: SessionHandlers): void;
47
+ /** Tells the platform whether the owner is playing, and nothing if it is not the owner. */
48
+ report(playing: boolean): void;
49
+ /**
50
+ * The page's one media session goes back to nobody, but only if this
51
+ * element is the one holding it.
52
+ */
53
+ hostDisconnected(): void;
54
+ }
@@ -0,0 +1,49 @@
1
+ let owner;
2
+ export const SKIP_SECONDS = 10;
3
+ export class MediaSessionController {
4
+ constructor(host) {
5
+ this.host = host;
6
+ host.addController(this);
7
+ }
8
+ claim(metadata, handlers) {
9
+ if (typeof navigator === 'undefined' || !navigator.mediaSession) {
10
+ return;
11
+ }
12
+ owner = this.host;
13
+ const session = navigator.mediaSession;
14
+ session.metadata = new MediaMetadata({
15
+ artwork: metadata.artwork === '' ? [] : [{ src: metadata.artwork }],
16
+ title: metadata.title,
17
+ });
18
+ session.setActionHandler('play', handlers.toggle);
19
+ session.setActionHandler('pause', handlers.toggle);
20
+ session.setActionHandler('seekto', (details) => {
21
+ if (details.seekTime !== undefined && details.seekTime !== null) {
22
+ handlers.seek(details.seekTime);
23
+ }
24
+ });
25
+ session.setActionHandler('seekbackward', (details) => {
26
+ handlers.skipBy(-(details.seekOffset ?? SKIP_SECONDS));
27
+ });
28
+ session.setActionHandler('seekforward', (details) => {
29
+ handlers.skipBy(details.seekOffset ?? SKIP_SECONDS);
30
+ });
31
+ session.setActionHandler('nexttrack', handlers.next);
32
+ session.setActionHandler('previoustrack', handlers.previous);
33
+ }
34
+ report(playing) {
35
+ if (owner === this.host && typeof navigator !== 'undefined' && navigator.mediaSession) {
36
+ navigator.mediaSession.playbackState = playing ? 'playing' : 'paused';
37
+ }
38
+ }
39
+ hostDisconnected() {
40
+ if (owner !== this.host) {
41
+ return;
42
+ }
43
+ owner = undefined;
44
+ if (typeof navigator !== 'undefined' && navigator.mediaSession) {
45
+ navigator.mediaSession.metadata = null;
46
+ navigator.mediaSession.playbackState = 'none';
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,34 @@
1
+ import type { ReactiveController, ReactiveControllerHost } from 'lit';
2
+ /** What the watch reports, as it learns it. */
3
+ export interface RemoteReport {
4
+ /** Whether anything on the network offers to play this. */
5
+ available: (available: boolean) => void;
6
+ /** Whether it is playing somewhere else right now. */
7
+ connected: (connected: boolean) => void;
8
+ }
9
+ /**
10
+ * Watches for something to play the video on, and stops on the way out.
11
+ *
12
+ * The Remote Playback API is the standard one, and it is what Safari
13
+ * implements for AirPlay and Chrome for Cast: one call covers both, where the
14
+ * older `webkitShowPlaybackTargetPicker` covers only the first. Firefox has
15
+ * neither, and `remote` simply being absent is what turns the control off
16
+ * there.
17
+ *
18
+ * `watchAvailability` returns an id that has to be canceled, or the callback
19
+ * outlives the element that owns it: a callback holding a removed element is a
20
+ * leak with a `@state` write on the end.
21
+ */
22
+ export declare class RemotePlaybackController implements ReactiveController {
23
+ private readonly report;
24
+ private video;
25
+ /** Cancels the availability watch, since it outlives a single render. */
26
+ private watch;
27
+ constructor(host: ReactiveControllerHost, report: RemoteReport);
28
+ /** Starts watching the video, once there is one. */
29
+ attach(video: HTMLVideoElement): Promise<void>;
30
+ /** Opens the platform's own device picker. It has no list of its own. */
31
+ prompt(): Promise<void>;
32
+ hostDisconnected(): void;
33
+ private readonly handleState;
34
+ }
@@ -0,0 +1,38 @@
1
+ export class RemotePlaybackController {
2
+ constructor(host, report) {
3
+ this.report = report;
4
+ this.handleState = () => {
5
+ this.report.connected(this.video?.remote?.state === 'connected');
6
+ };
7
+ host.addController(this);
8
+ }
9
+ async attach(video) {
10
+ this.video = video;
11
+ video.remote?.addEventListener?.('connect', this.handleState);
12
+ video.remote?.addEventListener?.('disconnect', this.handleState);
13
+ const remote = video.remote;
14
+ if (!remote?.watchAvailability) {
15
+ return;
16
+ }
17
+ try {
18
+ this.watch = await remote.watchAvailability((available) => {
19
+ this.report.available(available);
20
+ });
21
+ }
22
+ catch {
23
+ }
24
+ }
25
+ async prompt() {
26
+ try {
27
+ await this.video?.remote?.prompt();
28
+ }
29
+ catch {
30
+ }
31
+ }
32
+ hostDisconnected() {
33
+ if (this.watch !== undefined) {
34
+ void this.video?.remote?.cancelWatchAvailability?.(this.watch);
35
+ this.watch = undefined;
36
+ }
37
+ }
38
+ }
@@ -338,7 +338,6 @@ export declare class HelixHeadlessVideo extends HelixElement {
338
338
  * Whether the reader has been still long enough for the bar to go.
339
339
  */
340
340
  private idle;
341
- private idleTimer?;
342
341
  /**
343
342
  * Whether anything on the network offers to play this.
344
343
  */
@@ -347,8 +346,11 @@ export declare class HelixHeadlessVideo extends HelixElement {
347
346
  * Whether it is playing somewhere else right now.
348
347
  */
349
348
  private remoteConnected;
350
- /** Cancels the availability watch, since it outlives a single render. */
351
- private remoteWatch;
349
+ private readonly cues;
350
+ private readonly fullscreen;
351
+ private readonly idler;
352
+ private readonly remote;
353
+ private readonly session;
352
354
  /** Whether this platform can do a named control at all. */
353
355
  private offers;
354
356
  /** The extras asked for, in order, and only the ones this platform can do. */
@@ -485,17 +487,9 @@ export declare class HelixHeadlessVideo extends HelixElement {
485
487
  private readonly handleError;
486
488
  private readonly handleState;
487
489
  /**
488
- * Takes the page's media session, and tells the platform what is playing.
489
- *
490
- * On play rather than on render, which is the ownership rule: a page with two
491
- * players gives the session to whichever one the reader started, so a
492
- * headset's buttons land on what they are listening to rather than on
493
- * whichever came first in the markup.
494
- *
495
- * The handlers are what make a headset's play, pause and skip work at all.
496
- * Without them a platform falls back to guessing which element was meant,
497
- * which is right often enough to hide the fault and wrong exactly when there
498
- * are two.
490
+ * Takes the page's media session, on play rather than on render: a page
491
+ * with two players gives it to whichever one the reader started. The skip
492
+ * keys are offered only where the consumer named something to skip to.
499
493
  */
500
494
  private claimSession;
501
495
  private readonly handleVolume;
@@ -522,28 +516,7 @@ export declare class HelixHeadlessVideo extends HelixElement {
522
516
  * presses it twice expects twenty seconds rather than an accelerating jump.
523
517
  */
524
518
  private skipBy;
525
- /**
526
- * The tracks a reader could choose between, in the order they were written.
527
- *
528
- * Filtered by kind, because `textTracks` also carries `chapters`, `metadata`
529
- * and `descriptions`, and a menu offering "Chapters" as a subtitle language
530
- * would be offering something that draws no words. Read off the video rather
531
- * than off the slot: a `<track>` added later is in one and not the other, and
532
- * the video is the one that has resolved them.
533
- */
534
- private get captionTracks();
535
- /**
536
- * Shows one track and disables every other, or shows none at `-1`.
537
- *
538
- * Every other, rather than only the one that was on. Two tracks in `hidden`
539
- * both fire `cuechange`, so the rendered cue becomes whichever fired last and
540
- * a reader who switched language gets the two interleaved. Measured as two
541
- * subtitles alternating line by line.
542
- *
543
- * `hidden`, never `showing`. Hidden is the mode where a track still fires
544
- * `cuechange` and still fills `activeCues`, and the browser draws nothing,
545
- * which is exactly what is wanted when something else is doing the drawing.
546
- */
519
+ /** Shows one track and disables every other, or shows none at `-1`. */
547
520
  private showCaption;
548
521
  /** Turns captions on or off, which is what the button means with one track. */
549
522
  private toggleCaptions;
@@ -562,46 +535,7 @@ export declare class HelixHeadlessVideo extends HelixElement {
562
535
  private skip;
563
536
  /** Steps through the speeds offered, which is what one button can do. */
564
537
  private cycleSpeed;
565
- /**
566
- * Starts watching for something to play this on, and stops on the way out.
567
- *
568
- * The Remote Playback API is the standard one, and it is what Safari
569
- * implements for AirPlay and Chrome for Cast: one call covers both, where the
570
- * older `webkitShowPlaybackTargetPicker` covers only the first. Firefox has
571
- * neither, and `remote` simply being absent is what turns the control off
572
- * there.
573
- *
574
- * `watchAvailability` returns an id that has to be canceled, or the callback
575
- * outlives the element that owns it.
576
- */
577
- private watchRemote;
578
- /** Opens the platform's own device picker. It has no list of its own. */
579
- private promptRemote;
580
538
  private togglePip;
581
- /**
582
- * Into fullscreen and back, and quiet about being refused.
583
- *
584
- * `requestFullscreen` rejects rather than returning false, and the two
585
- * refusals a consumer will actually meet are a Permissions Policy that does
586
- * not grant `fullscreen` to the frame the player is in, and a call without
587
- * user activation. Both are `TypeError: Permissions check failed`, which is
588
- * the same message for two different causes.
589
- *
590
- * Caught rather than `void`ed, or a refusal becomes an unhandled rejection
591
- * naming neither the element nor the reason. The state stays honest either
592
- * way, because `aria-pressed` follows `fullscreenchange` rather than this
593
- * call, so a refused request leaves a button that correctly reports "not
594
- * fullscreen".
595
- */
596
- private toggleFullscreen;
597
- /**
598
- * Restarts the wait, on anything that counts as the reader being here.
599
- *
600
- * Pointer movement and focus both count, and both have to: a reader using the
601
- * keyboard never moves a pointer, and a bar that only answered the mouse
602
- * would leave them nothing to look at.
603
- */
604
- private readonly stir;
605
539
  /**
606
540
  * A press on the picture plays or pauses it.
607
541
  *
@@ -623,7 +557,6 @@ export declare class HelixHeadlessVideo extends HelixElement {
623
557
  * mouse left resting until the bar faded.
624
558
  */
625
559
  private readonly handlePicture;
626
- private readonly handleFullscreenChange;
627
560
  /**
628
561
  * The keys every player uses, bound to this element rather than the document.
629
562
  *
@@ -636,22 +569,11 @@ export declare class HelixHeadlessVideo extends HelixElement {
636
569
  * seeking twice for one press.
637
570
  */
638
571
  private readonly handleKeydown;
639
- /** The track currently being listened to, so the next one can take it off. */
640
- private cued;
641
- private readonly handleRemoteState;
642
- connectedCallback(): void;
643
- disconnectedCallback(): void;
644
572
  /** The caption tracks among the copies, named as the menu names them. */
645
573
  private captions;
646
574
  /**
647
- * Finds the caption tracks among the copies, before the render that draws
648
- * them.
649
- *
650
- * By the platform's own reading of `kind`, which is what makes a `<track>` a
651
- * caption at all: missing is `subtitles` and anything it does not know is
652
- * `metadata`. Read from the video's tracks after the render instead, the count
653
- * arrived a render late and asked for one more. Choosing one still goes
654
- * through the video's tracks, which hold them in the same order.
575
+ * Reads the copies, and names the caption tracks among them before the
576
+ * render that draws them.
655
577
  */
656
578
  protected willUpdate(changed: PropertyValues): void;
657
579
  protected firstUpdated(changed: PropertyValues): void;