@fusion.dev/helix-headless 0.25.1 → 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.
- package/custom-elements.json +4966 -755
- package/dist/accordion/root/accordion-root.d.ts +5 -6
- package/dist/accordion/root/accordion-root.js +13 -36
- package/dist/announcement/root/announcement-root.js +1 -1
- package/dist/avatar/root/avatar-root.d.ts +17 -3
- package/dist/avatar/root/avatar-root.js +27 -8
- package/dist/blockquote/root/blockquote-root.js +1 -1
- package/dist/button/root/button-root.js +1 -1
- package/dist/carousel/root/carousel-root.js +2 -2
- package/dist/chat/root/chat-root.js +1 -1
- package/dist/checkbox/root/checkbox-root.js +2 -2
- package/dist/checkbox-group/root/checkbox-group-root.js +2 -2
- package/dist/color-input/root/color-input-root.d.ts +12 -14
- package/dist/color-input/root/color-input-root.js +4 -52
- package/dist/color-picker/root/color-picker-root.js +2 -2
- package/dist/combobox/root/combobox-root.js +11 -14
- package/dist/command/root/command-root.js +2 -3
- package/dist/data-table/root/data-table-root.js +1 -1
- package/dist/date-input/root/date-input-root.d.ts +5 -77
- package/dist/date-input/root/date-input-root.js +16 -108
- package/dist/date-picker/root/date-picker-root.js +2 -2
- package/dist/divider/root/divider-root.js +1 -1
- package/dist/drawer/root/drawer-root.js +1 -1
- package/dist/drilldown/item/drilldown-item.js +1 -1
- package/dist/file-input/root/file-input-root.js +4 -7
- package/dist/filter-input/field/filter-field.d.ts +1 -1
- package/dist/filter-input/root/filter-input-root.d.ts +2 -2
- package/dist/filter-input/root/filter-input-root.js +12 -15
- package/dist/heatmap/root/heatmap-root.js +1 -1
- package/dist/image/root/image-root.d.ts +7 -0
- package/dist/image/root/image-root.js +6 -2
- package/dist/input/root/input-root.js +3 -3
- package/dist/listbox/root/listbox-root.js +3 -3
- package/dist/megamenu/root/megamenu-root.d.ts +12 -2
- package/dist/megamenu/root/megamenu-root.js +20 -15
- package/dist/menu/item/menu-item.js +1 -1
- package/dist/menu/root/menu-root.js +3 -10
- package/dist/navigation/root/navigation-root.d.ts +1 -2
- package/dist/navigation/root/navigation-root.js +3 -9
- package/dist/number-input/root/number-input-root.js +5 -5
- package/dist/object-inspector/root/object-inspector-root.js +4 -4
- package/dist/outline/root/outline-root.d.ts +0 -1
- package/dist/outline/root/outline-root.js +6 -12
- package/dist/pin-input/root/pin-input-root.js +2 -2
- package/dist/popover/root/popover-root.js +2 -10
- package/dist/radio/root/radio-root.js +1 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +1 -1
- package/dist/scroll-area/root/scroll-area-root.js +1 -1
- package/dist/select/root/select-root.js +8 -9
- package/dist/slider/root/slider-root.js +2 -2
- package/dist/sparkline/root/sparkline-root.d.ts +2 -1
- package/dist/sparkline/root/sparkline-root.js +2 -2
- package/dist/speed-dial/item/speed-dial-item.js +1 -1
- package/dist/speed-dial/root/speed-dial-root.d.ts +2 -2
- package/dist/speed-dial/root/speed-dial-root.js +4 -7
- package/dist/switch/root/switch-root.js +3 -3
- package/dist/table/column/table-column.js +1 -1
- package/dist/tabs/root/tabs-root.d.ts +2 -17
- package/dist/tabs/root/tabs-root.js +3 -21
- package/dist/tabs/tab/tab.js +1 -1
- package/dist/textarea/root/textarea-root.js +3 -3
- package/dist/time-input/root/time-input-root.d.ts +5 -64
- package/dist/time-input/root/time-input-root.js +15 -107
- package/dist/time-picker/root/time-picker-root.js +2 -2
- package/dist/toggle/group/toggle-group.d.ts +0 -13
- package/dist/toggle/group/toggle-group.js +3 -23
- package/dist/toggle/root/toggle-root.js +1 -1
- package/dist/tooltip/root/tooltip-root.d.ts +0 -13
- package/dist/tooltip/root/tooltip-root.js +8 -16
- package/dist/tour/root/tour-root.js +6 -6
- package/dist/tour/stop/tour-stop.js +2 -2
- package/dist/video/root/captions.d.ts +85 -0
- package/dist/video/root/captions.js +45 -0
- package/dist/video/root/fullscreen.d.ts +28 -0
- package/dist/video/root/fullscreen.js +28 -0
- package/dist/video/root/idle.d.ts +34 -0
- package/dist/video/root/idle.js +24 -0
- package/dist/video/root/media-session.d.ts +54 -0
- package/dist/video/root/media-session.js +49 -0
- package/dist/video/root/remote-playback.d.ts +34 -0
- package/dist/video/root/remote-playback.js +38 -0
- package/dist/video/root/video-root.d.ts +11 -89
- package/dist/video/root/video-root.js +45 -139
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -1
- package/dist/video-playlist/menu/video-playlist-menu.js +8 -10
- package/dist/virtual-list/root/virtual-list-root.js +1 -1
- package/package.json +8 -7
- package/types/jsx.d.ts +264 -192
- package/types/vue.d.ts +78 -69
|
@@ -10,6 +10,11 @@ import { nothing } from 'lit';
|
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
import { html } from 'lit/static-html.js';
|
|
12
12
|
import '../../menu/index.js';
|
|
13
|
+
import { activeCue, adoptTrack, CueController, captionsAmong, captionTracks, showCaption, } from './captions.js';
|
|
14
|
+
import { FullscreenController } from './fullscreen.js';
|
|
15
|
+
import { IdleController } from './idle.js';
|
|
16
|
+
import { MediaSessionController, SKIP_SECONDS } from './media-session.js';
|
|
17
|
+
import { RemotePlaybackController } from './remote-playback.js';
|
|
13
18
|
const clock = (seconds) => {
|
|
14
19
|
if (!Number.isFinite(seconds) || seconds < 0) {
|
|
15
20
|
return '0:00';
|
|
@@ -23,8 +28,6 @@ const clock = (seconds) => {
|
|
|
23
28
|
? `${hours}:${String(minutes).padStart(2, '0')}:${padded}`
|
|
24
29
|
: `${minutes}:${padded}`;
|
|
25
30
|
};
|
|
26
|
-
let owner;
|
|
27
|
-
const SKIP_SECONDS = 10;
|
|
28
31
|
let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
29
32
|
constructor() {
|
|
30
33
|
super(...arguments);
|
|
@@ -63,6 +66,22 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
63
66
|
this.idle = false;
|
|
64
67
|
this.remoteAvailable = false;
|
|
65
68
|
this.remoteConnected = false;
|
|
69
|
+
this.cues = new CueController(this, () => this.handleCue());
|
|
70
|
+
this.fullscreen = new FullscreenController(this, (full) => {
|
|
71
|
+
this.full = full;
|
|
72
|
+
});
|
|
73
|
+
this.idler = new IdleController(this, () => this.idleDelay, (idle) => {
|
|
74
|
+
this.idle = idle;
|
|
75
|
+
});
|
|
76
|
+
this.remote = new RemotePlaybackController(this, {
|
|
77
|
+
available: (available) => {
|
|
78
|
+
this.remoteAvailable = available;
|
|
79
|
+
},
|
|
80
|
+
connected: (connected) => {
|
|
81
|
+
this.remoteConnected = connected;
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
this.session = new MediaSessionController(this);
|
|
66
85
|
this.media = [];
|
|
67
86
|
this.mediaRead = false;
|
|
68
87
|
this.handleMedia = (event) => {
|
|
@@ -82,13 +101,8 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
82
101
|
}
|
|
83
102
|
const track = video.textTracks[0];
|
|
84
103
|
if (track) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
this.captioned = track.mode === 'hidden';
|
|
89
|
-
this.cued?.removeEventListener('cuechange', this.handleCue);
|
|
90
|
-
this.cued = track;
|
|
91
|
-
track.addEventListener('cuechange', this.handleCue);
|
|
104
|
+
this.captioned = adoptTrack(track);
|
|
105
|
+
this.cues.follow(track);
|
|
92
106
|
this.handleCue();
|
|
93
107
|
}
|
|
94
108
|
};
|
|
@@ -117,9 +131,7 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
117
131
|
if (event.type === 'play') {
|
|
118
132
|
this.claimSession();
|
|
119
133
|
}
|
|
120
|
-
|
|
121
|
-
navigator.mediaSession.playbackState = this.playing ? 'playing' : 'paused';
|
|
122
|
-
}
|
|
134
|
+
this.session.report(this.playing);
|
|
123
135
|
this.dispatchEvent(new Event(event.type, { bubbles: false, composed: false }));
|
|
124
136
|
};
|
|
125
137
|
this.handleVolume = () => {
|
|
@@ -131,32 +143,19 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
131
143
|
this.silent = video.muted;
|
|
132
144
|
};
|
|
133
145
|
this.handleCue = () => {
|
|
134
|
-
const track = this.
|
|
135
|
-
|
|
136
|
-
this.cue = active instanceof VTTCue ? active.getCueAsHTML() : undefined;
|
|
137
|
-
};
|
|
138
|
-
this.stir = () => {
|
|
139
|
-
this.idle = false;
|
|
140
|
-
clearTimeout(this.idleTimer);
|
|
141
|
-
if (this.idleDelay > 0) {
|
|
142
|
-
this.idleTimer = setTimeout(() => {
|
|
143
|
-
this.idle = true;
|
|
144
|
-
}, this.idleDelay);
|
|
145
|
-
}
|
|
146
|
+
const track = captionTracks(this.video)[this.captionIndex] ?? this.video?.textTracks[0];
|
|
147
|
+
this.cue = activeCue(track);
|
|
146
148
|
};
|
|
147
149
|
this.handlePicture = () => {
|
|
148
150
|
if (this.controls) {
|
|
149
151
|
return;
|
|
150
152
|
}
|
|
151
153
|
if (this.idle) {
|
|
152
|
-
this.stir();
|
|
154
|
+
this.idler.stir();
|
|
153
155
|
return;
|
|
154
156
|
}
|
|
155
157
|
this.toggle();
|
|
156
158
|
};
|
|
157
|
-
this.handleFullscreenChange = () => {
|
|
158
|
-
this.full = document.fullscreenElement === this;
|
|
159
|
-
};
|
|
160
159
|
this.handleKeydown = (event) => {
|
|
161
160
|
if (this.controls) {
|
|
162
161
|
return;
|
|
@@ -204,7 +203,7 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
204
203
|
break;
|
|
205
204
|
}
|
|
206
205
|
case 'f': {
|
|
207
|
-
void this.
|
|
206
|
+
void this.fullscreen.toggle();
|
|
208
207
|
break;
|
|
209
208
|
}
|
|
210
209
|
default: {
|
|
@@ -213,9 +212,6 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
213
212
|
}
|
|
214
213
|
event.preventDefault();
|
|
215
214
|
};
|
|
216
|
-
this.handleRemoteState = () => {
|
|
217
|
-
this.remoteConnected = this.video?.remote?.state === 'connected';
|
|
218
|
-
};
|
|
219
215
|
this.captions = [];
|
|
220
216
|
}
|
|
221
217
|
get localFile() {
|
|
@@ -343,7 +339,7 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
343
339
|
}
|
|
344
340
|
}
|
|
345
341
|
get video() {
|
|
346
|
-
return this.
|
|
342
|
+
return this.partNamed('video');
|
|
347
343
|
}
|
|
348
344
|
play() {
|
|
349
345
|
void this.video?.play().catch(() => { });
|
|
@@ -402,31 +398,14 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
402
398
|
});
|
|
403
399
|
}
|
|
404
400
|
claimSession() {
|
|
405
|
-
if (typeof navigator === 'undefined' || !navigator.mediaSession) {
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
owner = this;
|
|
409
|
-
const session = navigator.mediaSession;
|
|
410
|
-
session.metadata = new MediaMetadata({
|
|
411
|
-
artwork: this.poster === '' ? [] : [{ src: this.poster }],
|
|
412
|
-
title: this.label,
|
|
413
|
-
});
|
|
414
|
-
session.setActionHandler('play', () => this.toggle());
|
|
415
|
-
session.setActionHandler('pause', () => this.toggle());
|
|
416
|
-
session.setActionHandler('seekto', (details) => {
|
|
417
|
-
if (details.seekTime !== undefined && details.seekTime !== null) {
|
|
418
|
-
this.seek(details.seekTime);
|
|
419
|
-
}
|
|
420
|
-
});
|
|
421
401
|
const skips = `${this.extraControls} ${this.overflowControls}`.split(/\s+/);
|
|
422
|
-
session.
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
this.skipBy(
|
|
402
|
+
this.session.claim({ artwork: this.poster, title: this.label }, {
|
|
403
|
+
next: skips.includes('next') ? () => this.skip(false) : null,
|
|
404
|
+
previous: skips.includes('previous') ? () => this.skip(true) : null,
|
|
405
|
+
seek: (seconds) => this.seek(seconds),
|
|
406
|
+
skipBy: (seconds) => this.skipBy(seconds),
|
|
407
|
+
toggle: () => this.toggle(),
|
|
427
408
|
});
|
|
428
|
-
session.setActionHandler('nexttrack', skips.includes('next') ? () => this.skip(false) : null);
|
|
429
|
-
session.setActionHandler('previoustrack', skips.includes('previous') ? () => this.skip(true) : null);
|
|
430
409
|
}
|
|
431
410
|
skipBy(seconds) {
|
|
432
411
|
const video = this.video;
|
|
@@ -435,24 +414,14 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
435
414
|
}
|
|
436
415
|
this.seek(video.currentTime + seconds);
|
|
437
416
|
}
|
|
438
|
-
get captionTracks() {
|
|
439
|
-
const tracks = this.video?.textTracks;
|
|
440
|
-
if (!tracks) {
|
|
441
|
-
return [];
|
|
442
|
-
}
|
|
443
|
-
return [...tracks].filter((one) => one.kind === 'subtitles' || one.kind === 'captions');
|
|
444
|
-
}
|
|
445
417
|
showCaption(index) {
|
|
446
|
-
|
|
447
|
-
tracks.forEach((track, at) => {
|
|
448
|
-
track.mode = at === index ? 'hidden' : 'disabled';
|
|
449
|
-
});
|
|
418
|
+
showCaption(captionTracks(this.video), index);
|
|
450
419
|
this.captionIndex = index;
|
|
451
420
|
this.captioned = index >= 0;
|
|
452
421
|
this.cue = undefined;
|
|
453
422
|
}
|
|
454
423
|
toggleCaptions() {
|
|
455
|
-
if (this.
|
|
424
|
+
if (captionTracks(this.video).length === 0) {
|
|
456
425
|
return;
|
|
457
426
|
}
|
|
458
427
|
this.showCaption(this.captioned ? -1 : 0);
|
|
@@ -474,26 +443,6 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
474
443
|
video.playbackRate = next;
|
|
475
444
|
this.rate = next;
|
|
476
445
|
}
|
|
477
|
-
async watchRemote() {
|
|
478
|
-
const remote = this.video?.remote;
|
|
479
|
-
if (!remote?.watchAvailability) {
|
|
480
|
-
return;
|
|
481
|
-
}
|
|
482
|
-
try {
|
|
483
|
-
this.remoteWatch = await remote.watchAvailability((available) => {
|
|
484
|
-
this.remoteAvailable = available;
|
|
485
|
-
});
|
|
486
|
-
}
|
|
487
|
-
catch {
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
async promptRemote() {
|
|
491
|
-
try {
|
|
492
|
-
await this.video?.remote?.prompt();
|
|
493
|
-
}
|
|
494
|
-
catch {
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
446
|
async togglePip() {
|
|
498
447
|
const video = this.video;
|
|
499
448
|
if (!video) {
|
|
@@ -505,40 +454,6 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
505
454
|
}
|
|
506
455
|
await video.requestPictureInPicture();
|
|
507
456
|
}
|
|
508
|
-
async toggleFullscreen() {
|
|
509
|
-
try {
|
|
510
|
-
if (document.fullscreenElement === this) {
|
|
511
|
-
await document.exitFullscreen();
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
await this.requestFullscreen();
|
|
515
|
-
}
|
|
516
|
-
catch (error) {
|
|
517
|
-
console.warn(`<${this.localName}> could not enter fullscreen. If it is inside an iframe, that frame needs allow="fullscreen".`, error);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
connectedCallback() {
|
|
521
|
-
super.connectedCallback();
|
|
522
|
-
document.addEventListener('fullscreenchange', this.handleFullscreenChange);
|
|
523
|
-
}
|
|
524
|
-
disconnectedCallback() {
|
|
525
|
-
super.disconnectedCallback();
|
|
526
|
-
clearTimeout(this.idleTimer);
|
|
527
|
-
this.cued?.removeEventListener('cuechange', this.handleCue);
|
|
528
|
-
this.cued = undefined;
|
|
529
|
-
document.removeEventListener('fullscreenchange', this.handleFullscreenChange);
|
|
530
|
-
if (this.remoteWatch !== undefined) {
|
|
531
|
-
void this.video?.remote?.cancelWatchAvailability?.(this.remoteWatch);
|
|
532
|
-
this.remoteWatch = undefined;
|
|
533
|
-
}
|
|
534
|
-
if (owner === this) {
|
|
535
|
-
owner = undefined;
|
|
536
|
-
if (typeof navigator !== 'undefined' && navigator.mediaSession) {
|
|
537
|
-
navigator.mediaSession.metadata = null;
|
|
538
|
-
navigator.mediaSession.playbackState = 'none';
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
457
|
willUpdate(changed) {
|
|
543
458
|
super.willUpdate(changed);
|
|
544
459
|
if (!this.mediaRead && this.children !== undefined && !this.hydrating) {
|
|
@@ -546,11 +461,7 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
546
461
|
this.media = this.copiesOf([...this.children].filter((child) => child.slot === ''));
|
|
547
462
|
}
|
|
548
463
|
if (changed.has('media')) {
|
|
549
|
-
this.captions = this.media
|
|
550
|
-
.filter((one) => one.tag === 'track' &&
|
|
551
|
-
(one.attrs.kind === undefined ||
|
|
552
|
-
['captions', 'subtitles'].includes(one.attrs.kind.toLowerCase())))
|
|
553
|
-
.map((one) => ({ label: one.attrs.label ?? '', language: one.attrs.srclang ?? '' }));
|
|
464
|
+
this.captions = captionsAmong(this.media);
|
|
554
465
|
this.captionCount = this.captions.length;
|
|
555
466
|
}
|
|
556
467
|
}
|
|
@@ -564,9 +475,7 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
564
475
|
}
|
|
565
476
|
this.silent = video.muted;
|
|
566
477
|
this.loudness = video.volume;
|
|
567
|
-
|
|
568
|
-
video.remote?.addEventListener?.('disconnect', this.handleRemoteState);
|
|
569
|
-
void this.watchRemote();
|
|
478
|
+
void this.remote.attach(video);
|
|
570
479
|
}
|
|
571
480
|
}
|
|
572
481
|
updated(changed) {
|
|
@@ -584,7 +493,7 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
584
493
|
type="button"
|
|
585
494
|
aria-label="Play on another device"
|
|
586
495
|
aria-pressed=${this.remoteConnected ? 'true' : 'false'}
|
|
587
|
-
@click=${() => void this.
|
|
496
|
+
@click=${() => void this.remote.prompt()}
|
|
588
497
|
>
|
|
589
498
|
${drawIcon(airplay)}
|
|
590
499
|
</button>`;
|
|
@@ -710,7 +619,7 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
710
619
|
return html `<${this.tag('menu-item')} part="entry"
|
|
711
620
|
exportparts="item: entry-item, mark: entry-mark, start: entry-start"
|
|
712
621
|
value="remote"
|
|
713
|
-
@helix-select=${() => void this.
|
|
622
|
+
@helix-select=${() => void this.remote.prompt()}
|
|
714
623
|
>
|
|
715
624
|
${drawIcon(airplay, { slot: 'start' })}
|
|
716
625
|
Play on another device
|
|
@@ -840,7 +749,7 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
840
749
|
type="button"
|
|
841
750
|
aria-label=${this.full ? 'Exit fullscreen' : 'Fullscreen'}
|
|
842
751
|
aria-pressed=${this.full ? 'true' : 'false'}
|
|
843
|
-
@click=${() => void this.
|
|
752
|
+
@click=${() => void this.fullscreen.toggle()}
|
|
844
753
|
>
|
|
845
754
|
${drawIcon(this.full ? cornersIn : cornersOut)}
|
|
846
755
|
</button>
|
|
@@ -853,12 +762,9 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
853
762
|
role=${this.controls ? nothing : 'group'}
|
|
854
763
|
aria-label=${this.controls ? nothing : this.label || 'Video'}
|
|
855
764
|
@keydown=${this.handleKeydown}
|
|
856
|
-
@pointermove=${this.stir}
|
|
857
|
-
@pointerleave=${
|
|
858
|
-
|
|
859
|
-
this.idle = true;
|
|
860
|
-
}}
|
|
861
|
-
@focusin=${this.stir}
|
|
765
|
+
@pointermove=${this.idler.stir}
|
|
766
|
+
@pointerleave=${this.idler.leave}
|
|
767
|
+
@focusin=${this.idler.stir}
|
|
862
768
|
>
|
|
863
769
|
<video
|
|
864
770
|
part="video"
|
|
@@ -41,7 +41,6 @@ import '../../menu/index.js';
|
|
|
41
41
|
* @csspart trigger - The button that opens it.
|
|
42
42
|
*/
|
|
43
43
|
export declare class HelixHeadlessVideoPlaylistMenu extends HelixElement {
|
|
44
|
-
#private;
|
|
45
44
|
/**
|
|
46
45
|
* The menu's accessible name, and its trigger's.
|
|
47
46
|
*
|
|
@@ -56,8 +55,10 @@ export declare class HelixHeadlessVideoPlaylistMenu extends HelixElement {
|
|
|
56
55
|
* opening downward from there opens off the player.
|
|
57
56
|
*/
|
|
58
57
|
placement: string;
|
|
58
|
+
private observer;
|
|
59
59
|
connectedCallback(): void;
|
|
60
60
|
disconnectedCallback(): void;
|
|
61
|
+
private foundPlaylist;
|
|
61
62
|
/** The playlist this menu belongs to, found upward through the slots. */
|
|
62
63
|
private get playlist();
|
|
63
64
|
/** The playlist's entries, in the order it holds them. */
|
|
@@ -24,7 +24,6 @@ let HelixHeadlessVideoPlaylistMenu = class HelixHeadlessVideoPlaylistMenu extend
|
|
|
24
24
|
this.dispatchEvent(new HelixSelectEvent({ value }));
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
-
#observer;
|
|
28
27
|
connectedCallback() {
|
|
29
28
|
super.connectedCallback();
|
|
30
29
|
this.updateComplete.then(() => this.watch());
|
|
@@ -32,26 +31,25 @@ let HelixHeadlessVideoPlaylistMenu = class HelixHeadlessVideoPlaylistMenu extend
|
|
|
32
31
|
disconnectedCallback() {
|
|
33
32
|
super.disconnectedCallback();
|
|
34
33
|
this.removeEventListener('helix-before-open', this.reread);
|
|
35
|
-
this
|
|
36
|
-
this
|
|
34
|
+
this.observer?.disconnect();
|
|
35
|
+
this.observer = undefined;
|
|
37
36
|
}
|
|
38
|
-
#playlist;
|
|
39
37
|
get playlist() {
|
|
40
|
-
return this
|
|
38
|
+
return this.foundPlaylist;
|
|
41
39
|
}
|
|
42
40
|
get entries() {
|
|
43
41
|
const playlist = this.playlist;
|
|
44
42
|
return playlist ? [...playlist.querySelectorAll(ITEMS)] : [];
|
|
45
43
|
}
|
|
46
44
|
watch() {
|
|
47
|
-
this
|
|
48
|
-
const playlist = this
|
|
49
|
-
if (!playlist || this
|
|
45
|
+
this.foundPlaylist ??= closestInstance(this, HelixHeadlessVideoPlaylist) ?? undefined;
|
|
46
|
+
const playlist = this.playlist;
|
|
47
|
+
if (!playlist || this.observer) {
|
|
50
48
|
return;
|
|
51
49
|
}
|
|
52
50
|
this.addEventListener('helix-before-open', this.reread);
|
|
53
|
-
this
|
|
54
|
-
this
|
|
51
|
+
this.observer = new MutationObserver(this.reread);
|
|
52
|
+
this.observer.observe(playlist, { childList: true, subtree: true });
|
|
55
53
|
this.reread();
|
|
56
54
|
}
|
|
57
55
|
render() {
|
|
@@ -16,7 +16,7 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
|
|
|
16
16
|
this.measured = false;
|
|
17
17
|
this.rows = [];
|
|
18
18
|
this.virtualize = new VirtualizeController(this, {
|
|
19
|
-
container: () => this.
|
|
19
|
+
container: () => this.partNamed('viewport'),
|
|
20
20
|
count: () => this.rows.length,
|
|
21
21
|
estimate: () => this.estimate,
|
|
22
22
|
measured: () => this.measured,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fusion.dev/helix-headless",
|
|
3
3
|
"description": "Headless component tier. Structure, accessibility, state, and form participation. No styling.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.30.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ross Sheppard <ross.sheppard@fusion.dev>",
|
|
7
7
|
"repository": {
|
|
@@ -41,21 +41,22 @@
|
|
|
41
41
|
"test:dom": "bun test dom.spec",
|
|
42
42
|
"test:pure": "bun test pure.spec",
|
|
43
43
|
"test:ssr": "bun test ssr.spec",
|
|
44
|
-
"typecheck": "bun run element-events && tsc -p tsconfig.json --noEmit"
|
|
44
|
+
"typecheck": "bun run element-events && tsc -p tsconfig.json --noEmit && bun run typecheck:examples",
|
|
45
|
+
"typecheck:examples": "tsc -p tsconfig.examples.json"
|
|
45
46
|
},
|
|
46
47
|
"bugs": "https://github.com/project-fusion/fusion/issues",
|
|
47
48
|
"dependencies": {
|
|
48
|
-
"@fusion.dev/helix-core": "0.
|
|
49
|
-
"@fusion.dev/helix-icons": "0.
|
|
49
|
+
"@fusion.dev/helix-core": "0.30.0",
|
|
50
|
+
"@fusion.dev/helix-icons": "0.30.0",
|
|
50
51
|
"uqr": "^0.1.3"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
53
54
|
"@custom-elements-manifest/analyzer": "^0.11.0",
|
|
54
|
-
"@fusion.dev/helix-cem": "0.
|
|
55
|
-
"@fusion.dev/helix-testing": "0.
|
|
55
|
+
"@fusion.dev/helix-cem": "0.30.0",
|
|
56
|
+
"@fusion.dev/helix-testing": "0.30.0",
|
|
56
57
|
"@fusion.dev/scripts": "0.0.0-dev",
|
|
57
58
|
"@happy-dom/global-registrator": "^20.0.0",
|
|
58
|
-
"@lit-labs/ssr": "^
|
|
59
|
+
"@lit-labs/ssr": "^4.1.0",
|
|
59
60
|
"@types/bun": "^1.3.0",
|
|
60
61
|
"lit": "^3.2.1"
|
|
61
62
|
},
|