@editframe/elements 0.21.0-beta.0 → 0.23.7-beta.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 (142) hide show
  1. package/dist/EF_FRAMEGEN.js +2 -3
  2. package/dist/attachContextRoot.d.ts +1 -0
  3. package/dist/attachContextRoot.js +9 -0
  4. package/dist/elements/ContextProxiesController.d.ts +1 -2
  5. package/dist/elements/EFAudio.js +2 -2
  6. package/dist/elements/EFCaptions.d.ts +1 -3
  7. package/dist/elements/EFCaptions.js +59 -51
  8. package/dist/elements/EFImage.js +2 -2
  9. package/dist/elements/EFMedia/AssetIdMediaEngine.js +1 -2
  10. package/dist/elements/EFMedia/AssetMediaEngine.js +1 -3
  11. package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +1 -1
  12. package/dist/elements/EFMedia/BufferedSeekingInput.js +2 -4
  13. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +4 -7
  14. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +1 -2
  15. package/dist/elements/EFMedia/shared/AudioSpanUtils.js +5 -9
  16. package/dist/elements/EFMedia/shared/BufferUtils.js +1 -3
  17. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +4 -7
  18. package/dist/elements/EFMedia.d.ts +19 -0
  19. package/dist/elements/EFMedia.js +19 -2
  20. package/dist/elements/EFSourceMixin.js +1 -1
  21. package/dist/elements/EFSurface.js +1 -1
  22. package/dist/elements/EFTemporal.browsertest.d.ts +11 -0
  23. package/dist/elements/EFTemporal.d.ts +10 -0
  24. package/dist/elements/EFTemporal.js +82 -5
  25. package/dist/elements/EFThumbnailStrip.js +9 -16
  26. package/dist/elements/EFTimegroup.browsertest.d.ts +3 -3
  27. package/dist/elements/EFTimegroup.d.ts +35 -14
  28. package/dist/elements/EFTimegroup.js +73 -120
  29. package/dist/elements/EFVideo.d.ts +10 -0
  30. package/dist/elements/EFVideo.js +15 -2
  31. package/dist/elements/EFWaveform.js +10 -18
  32. package/dist/elements/SampleBuffer.js +1 -2
  33. package/dist/elements/TargetController.js +2 -2
  34. package/dist/elements/renderTemporalAudio.d.ts +10 -0
  35. package/dist/elements/renderTemporalAudio.js +35 -0
  36. package/dist/elements/updateAnimations.js +7 -10
  37. package/dist/gui/ContextMixin.d.ts +5 -5
  38. package/dist/gui/ContextMixin.js +151 -117
  39. package/dist/gui/Controllable.browsertest.d.ts +0 -0
  40. package/dist/gui/Controllable.d.ts +15 -0
  41. package/dist/gui/Controllable.js +9 -0
  42. package/dist/gui/EFConfiguration.js +1 -1
  43. package/dist/gui/EFControls.browsertest.d.ts +11 -0
  44. package/dist/gui/EFControls.d.ts +18 -4
  45. package/dist/gui/EFControls.js +67 -25
  46. package/dist/gui/EFDial.browsertest.d.ts +0 -0
  47. package/dist/gui/EFDial.d.ts +18 -0
  48. package/dist/gui/EFDial.js +141 -0
  49. package/dist/gui/EFFilmstrip.browsertest.d.ts +11 -0
  50. package/dist/gui/EFFilmstrip.d.ts +12 -2
  51. package/dist/gui/EFFilmstrip.js +140 -34
  52. package/dist/gui/EFFitScale.js +2 -4
  53. package/dist/gui/EFFocusOverlay.js +1 -1
  54. package/dist/gui/EFPause.browsertest.d.ts +0 -0
  55. package/dist/gui/EFPause.d.ts +23 -0
  56. package/dist/gui/EFPause.js +59 -0
  57. package/dist/gui/EFPlay.browsertest.d.ts +0 -0
  58. package/dist/gui/EFPlay.d.ts +23 -0
  59. package/dist/gui/EFPlay.js +59 -0
  60. package/dist/gui/EFPreview.d.ts +4 -0
  61. package/dist/gui/EFPreview.js +15 -6
  62. package/dist/gui/EFResizableBox.browsertest.d.ts +0 -0
  63. package/dist/gui/EFResizableBox.d.ts +34 -0
  64. package/dist/gui/EFResizableBox.js +547 -0
  65. package/dist/gui/EFScrubber.d.ts +9 -3
  66. package/dist/gui/EFScrubber.js +7 -7
  67. package/dist/gui/EFTimeDisplay.d.ts +7 -1
  68. package/dist/gui/EFTimeDisplay.js +5 -5
  69. package/dist/gui/EFToggleLoop.d.ts +9 -3
  70. package/dist/gui/EFToggleLoop.js +6 -4
  71. package/dist/gui/EFTogglePlay.d.ts +12 -4
  72. package/dist/gui/EFTogglePlay.js +24 -19
  73. package/dist/gui/EFWorkbench.js +1 -1
  74. package/dist/gui/PlaybackController.d.ts +67 -0
  75. package/dist/gui/PlaybackController.js +310 -0
  76. package/dist/gui/TWMixin.js +1 -1
  77. package/dist/gui/TargetOrContextMixin.d.ts +10 -0
  78. package/dist/gui/TargetOrContextMixin.js +98 -0
  79. package/dist/gui/efContext.d.ts +2 -2
  80. package/dist/index.d.ts +4 -0
  81. package/dist/index.js +5 -1
  82. package/dist/otel/setupBrowserTracing.d.ts +1 -1
  83. package/dist/otel/setupBrowserTracing.js +6 -4
  84. package/dist/otel/tracingHelpers.js +1 -2
  85. package/dist/style.css +1 -1
  86. package/package.json +5 -5
  87. package/src/elements/ContextProxiesController.ts +10 -10
  88. package/src/elements/EFAudio.ts +1 -0
  89. package/src/elements/EFCaptions.browsertest.ts +128 -58
  90. package/src/elements/EFCaptions.ts +60 -34
  91. package/src/elements/EFImage.browsertest.ts +1 -2
  92. package/src/elements/EFMedia/JitMediaEngine.browsertest.ts +3 -0
  93. package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.ts +1 -1
  94. package/src/elements/EFMedia.browsertest.ts +8 -15
  95. package/src/elements/EFMedia.ts +38 -7
  96. package/src/elements/EFSurface.browsertest.ts +2 -6
  97. package/src/elements/EFSurface.ts +1 -0
  98. package/src/elements/EFTemporal.browsertest.ts +58 -1
  99. package/src/elements/EFTemporal.ts +140 -4
  100. package/src/elements/EFThumbnailStrip.browsertest.ts +2 -8
  101. package/src/elements/EFThumbnailStrip.ts +1 -0
  102. package/src/elements/EFTimegroup.browsertest.ts +6 -7
  103. package/src/elements/EFTimegroup.ts +163 -244
  104. package/src/elements/EFVideo.browsertest.ts +143 -47
  105. package/src/elements/EFVideo.ts +26 -0
  106. package/src/elements/FetchContext.browsertest.ts +7 -2
  107. package/src/elements/TargetController.browsertest.ts +1 -0
  108. package/src/elements/TargetController.ts +1 -0
  109. package/src/elements/renderTemporalAudio.ts +108 -0
  110. package/src/elements/updateAnimations.browsertest.ts +181 -6
  111. package/src/elements/updateAnimations.ts +6 -6
  112. package/src/gui/ContextMixin.browsertest.ts +274 -27
  113. package/src/gui/ContextMixin.ts +230 -175
  114. package/src/gui/Controllable.browsertest.ts +258 -0
  115. package/src/gui/Controllable.ts +41 -0
  116. package/src/gui/EFControls.browsertest.ts +294 -80
  117. package/src/gui/EFControls.ts +139 -28
  118. package/src/gui/EFDial.browsertest.ts +84 -0
  119. package/src/gui/EFDial.ts +172 -0
  120. package/src/gui/EFFilmstrip.browsertest.ts +712 -0
  121. package/src/gui/EFFilmstrip.ts +213 -23
  122. package/src/gui/EFPause.browsertest.ts +202 -0
  123. package/src/gui/EFPause.ts +73 -0
  124. package/src/gui/EFPlay.browsertest.ts +202 -0
  125. package/src/gui/EFPlay.ts +73 -0
  126. package/src/gui/EFPreview.ts +20 -5
  127. package/src/gui/EFResizableBox.browsertest.ts +79 -0
  128. package/src/gui/EFResizableBox.ts +898 -0
  129. package/src/gui/EFScrubber.ts +7 -5
  130. package/src/gui/EFTimeDisplay.browsertest.ts +19 -19
  131. package/src/gui/EFTimeDisplay.ts +3 -1
  132. package/src/gui/EFToggleLoop.ts +6 -5
  133. package/src/gui/EFTogglePlay.ts +30 -23
  134. package/src/gui/PlaybackController.ts +522 -0
  135. package/src/gui/TWMixin.css +3 -0
  136. package/src/gui/TargetOrContextMixin.ts +185 -0
  137. package/src/gui/efContext.ts +2 -2
  138. package/src/otel/setupBrowserTracing.ts +17 -12
  139. package/test/cache-integration-verification.browsertest.ts +1 -1
  140. package/types.json +1 -1
  141. package/dist/elements/ContextProxiesController.js +0 -49
  142. /package/dist/_virtual/{_@oxc-project_runtime@0.93.0 → _@oxc-project_runtime@0.94.0}/helpers/decorate.js +0 -0
@@ -1,5 +1,10 @@
1
1
  import { LitElement } from 'lit';
2
- export declare class EFTimeDisplay extends LitElement {
2
+ declare const EFTimeDisplay_base: (new (...args: any[]) => {
3
+ target: string;
4
+ targetElement: import('./Controllable.js').ControllableInterface | null;
5
+ effectiveContext: import('./Controllable.js').ControllableInterface | null;
6
+ }) & typeof LitElement;
7
+ export declare class EFTimeDisplay extends EFTimeDisplay_base {
3
8
  static styles: import('lit').CSSResult;
4
9
  currentTimeMs: number;
5
10
  durationMs: number;
@@ -11,3 +16,4 @@ declare global {
11
16
  "ef-time-display": EFTimeDisplay;
12
17
  }
13
18
  }
19
+ export {};
@@ -1,10 +1,12 @@
1
1
  import { currentTimeContext } from "./currentTimeContext.js";
2
2
  import { durationContext } from "./durationContext.js";
3
- import { __decorate } from "../_virtual/_@oxc-project_runtime@0.93.0/helpers/decorate.js";
3
+ import { __decorate } from "../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js";
4
+ import { efContext } from "./efContext.js";
5
+ import { TargetOrContextMixin } from "./TargetOrContextMixin.js";
4
6
  import { consume } from "@lit/context";
5
7
  import { LitElement, css, html } from "lit";
6
8
  import { customElement } from "lit/decorators.js";
7
- var EFTimeDisplay = class EFTimeDisplay$1 extends LitElement {
9
+ var EFTimeDisplay = class EFTimeDisplay$1 extends TargetOrContextMixin(LitElement, efContext) {
8
10
  constructor(..._args) {
9
11
  super(..._args);
10
12
  this.currentTimeMs = NaN;
@@ -24,9 +26,7 @@ var EFTimeDisplay = class EFTimeDisplay$1 extends LitElement {
24
26
  formatTime(ms) {
25
27
  if (!Number.isFinite(ms) || ms < 0) return "0:00";
26
28
  const totalSeconds = Math.floor(ms / 1e3);
27
- const minutes = Math.floor(totalSeconds / 60);
28
- const seconds = totalSeconds % 60;
29
- return `${minutes}:${seconds.toString().padStart(2, "0")}`;
29
+ return `${Math.floor(totalSeconds / 60)}:${(totalSeconds % 60).toString().padStart(2, "0")}`;
30
30
  }
31
31
  render() {
32
32
  const currentTime = this.currentTimeMs;
@@ -1,8 +1,13 @@
1
1
  import { LitElement } from 'lit';
2
- import { ContextMixinInterface } from './ContextMixin.js';
3
- export declare class EFToggleLoop extends LitElement {
2
+ import { ControllableInterface } from './Controllable.js';
3
+ declare const EFToggleLoop_base: (new (...args: any[]) => {
4
+ target: string;
5
+ targetElement: ControllableInterface | null;
6
+ effectiveContext: ControllableInterface | null;
7
+ }) & typeof LitElement;
8
+ export declare class EFToggleLoop extends EFToggleLoop_base {
4
9
  static styles: import('lit').CSSResult[];
5
- context?: ContextMixinInterface | null;
10
+ get context(): ControllableInterface | null;
6
11
  render(): import('lit-html').TemplateResult<1>;
7
12
  }
8
13
  declare global {
@@ -10,3 +15,4 @@ declare global {
10
15
  "ef-toggle-loop": EFToggleLoop;
11
16
  }
12
17
  }
18
+ export {};
@@ -1,14 +1,17 @@
1
- import { __decorate } from "../_virtual/_@oxc-project_runtime@0.93.0/helpers/decorate.js";
1
+ import { __decorate } from "../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js";
2
2
  import { efContext } from "./efContext.js";
3
- import { consume } from "@lit/context";
3
+ import { TargetOrContextMixin } from "./TargetOrContextMixin.js";
4
4
  import { LitElement, css, html } from "lit";
5
5
  import { customElement } from "lit/decorators.js";
6
- var EFToggleLoop = class EFToggleLoop$1 extends LitElement {
6
+ var EFToggleLoop = class EFToggleLoop$1 extends TargetOrContextMixin(LitElement, efContext) {
7
7
  static {
8
8
  this.styles = [css`
9
9
  :host {}
10
10
  `];
11
11
  }
12
+ get context() {
13
+ return this.effectiveContext;
14
+ }
12
15
  render() {
13
16
  return html`
14
17
  <slot @click=${() => {
@@ -17,6 +20,5 @@ var EFToggleLoop = class EFToggleLoop$1 extends LitElement {
17
20
  `;
18
21
  }
19
22
  };
20
- __decorate([consume({ context: efContext })], EFToggleLoop.prototype, "context", void 0);
21
23
  EFToggleLoop = __decorate([customElement("ef-toggle-loop")], EFToggleLoop);
22
24
  export { EFToggleLoop };
@@ -1,14 +1,22 @@
1
1
  import { LitElement } from 'lit';
2
- import { ContextMixinInterface } from './ContextMixin.js';
3
- export declare class EFTogglePlay extends LitElement {
2
+ import { ControllableInterface } from './Controllable.js';
3
+ declare const EFTogglePlay_base: (new (...args: any[]) => {
4
+ target: string;
5
+ targetElement: ControllableInterface | null;
6
+ effectiveContext: ControllableInterface | null;
7
+ }) & typeof LitElement;
8
+ export declare class EFTogglePlay extends EFTogglePlay_base {
4
9
  static styles: import('lit').CSSResult[];
5
- context?: ContextMixinInterface | null;
6
10
  playing: boolean;
11
+ get efContext(): ControllableInterface | null;
12
+ connectedCallback(): void;
13
+ disconnectedCallback(): void;
7
14
  render(): import('lit-html').TemplateResult<1>;
8
- togglePlay(): void;
15
+ togglePlay: () => void;
9
16
  }
10
17
  declare global {
11
18
  interface HTMLElementTagNameMap {
12
19
  "ef-toggle-play": EFTogglePlay;
13
20
  }
14
21
  }
22
+ export {};
@@ -1,13 +1,20 @@
1
- import { __decorate } from "../_virtual/_@oxc-project_runtime@0.93.0/helpers/decorate.js";
2
- import { efContext } from "./efContext.js";
3
1
  import { playingContext } from "./playingContext.js";
2
+ import { __decorate } from "../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js";
3
+ import { efContext } from "./efContext.js";
4
+ import { attachContextRoot } from "../attachContextRoot.js";
5
+ import { TargetOrContextMixin } from "./TargetOrContextMixin.js";
4
6
  import { consume } from "@lit/context";
5
7
  import { LitElement, css, html } from "lit";
6
- import { customElement } from "lit/decorators.js";
7
- var EFTogglePlay = class EFTogglePlay$1 extends LitElement {
8
+ import { customElement, state } from "lit/decorators.js";
9
+ attachContextRoot();
10
+ var EFTogglePlay = class EFTogglePlay$1 extends TargetOrContextMixin(LitElement, efContext) {
8
11
  constructor(..._args) {
9
12
  super(..._args);
10
13
  this.playing = false;
14
+ this.togglePlay = () => {
15
+ if (this.efContext) if (this.playing) this.efContext.pause();
16
+ else this.efContext.play();
17
+ };
11
18
  }
12
19
  static {
13
20
  this.styles = [css`
@@ -17,30 +24,28 @@ var EFTogglePlay = class EFTogglePlay$1 extends LitElement {
17
24
  }
18
25
  `];
19
26
  }
27
+ get efContext() {
28
+ return this.effectiveContext;
29
+ }
30
+ connectedCallback() {
31
+ super.connectedCallback();
32
+ this.addEventListener("click", this.togglePlay);
33
+ }
34
+ disconnectedCallback() {
35
+ super.disconnectedCallback();
36
+ this.removeEventListener("click", this.togglePlay);
37
+ }
20
38
  render() {
21
39
  return html`
22
- <div
23
- @click=${() => {
24
- if (this.context) if (this.playing) this.context.pause();
25
- else this.context.play();
26
- }}
27
- >
40
+ <div>
28
41
  ${this.playing ? html`<slot name="pause"></slot>` : html`<slot name="play"></slot>`}
29
42
  </div>
30
43
  `;
31
44
  }
32
- togglePlay() {
33
- if (this.context) if (this.playing) this.context.pause();
34
- else this.context.play();
35
- }
36
45
  };
37
- __decorate([consume({
38
- context: efContext,
39
- subscribe: true
40
- })], EFTogglePlay.prototype, "context", void 0);
41
46
  __decorate([consume({
42
47
  context: playingContext,
43
48
  subscribe: true
44
- })], EFTogglePlay.prototype, "playing", void 0);
49
+ }), state()], EFTogglePlay.prototype, "playing", void 0);
45
50
  EFTogglePlay = __decorate([customElement("ef-toggle-play")], EFTogglePlay);
46
51
  export { EFTogglePlay };
@@ -1,4 +1,4 @@
1
- import { __decorate } from "../_virtual/_@oxc-project_runtime@0.93.0/helpers/decorate.js";
1
+ import { __decorate } from "../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js";
2
2
  import { ContextMixin } from "./ContextMixin.js";
3
3
  import { TWMixin } from "./TWMixin2.js";
4
4
  import { LitElement, css, html } from "lit";
@@ -0,0 +1,67 @@
1
+ import { Task } from '@lit/task';
2
+ import { ReactiveController, ReactiveControllerHost } from 'lit';
3
+ interface PlaybackHost extends HTMLElement, ReactiveControllerHost {
4
+ currentTimeMs: number;
5
+ durationMs: number;
6
+ endTimeMs: number;
7
+ frameTask: {
8
+ run(): void;
9
+ taskComplete: Promise<unknown>;
10
+ };
11
+ renderAudio?(fromMs: number, toMs: number): Promise<AudioBuffer>;
12
+ waitForMediaDurations?(): Promise<void>;
13
+ saveTimeToLocalStorage?(time: number): void;
14
+ loadTimeFromLocalStorage?(): number | undefined;
15
+ requestUpdate(property?: string): void;
16
+ updateComplete: Promise<boolean>;
17
+ playing: boolean;
18
+ loop: boolean;
19
+ play(): void;
20
+ pause(): void;
21
+ playbackController?: PlaybackController;
22
+ parentTimegroup?: any;
23
+ rootTimegroup?: any;
24
+ }
25
+ export type PlaybackControllerUpdateEvent = {
26
+ property: "playing" | "loop" | "currentTimeMs";
27
+ value: boolean | number;
28
+ };
29
+ /**
30
+ * Manages playback state and audio-driven timing for root temporal elements
31
+ *
32
+ * Created automatically when a temporal element becomes a root (no parent timegroup)
33
+ * Provides playback contexts (playing, loop, currentTimeMs, durationMs) to descendants
34
+ * Handles:
35
+ * - Audio-driven playback with Web Audio API
36
+ * - Seek and frame rendering throttling
37
+ * - Time state management with pending seek handling
38
+ * - Playback loop behavior
39
+ *
40
+ * Works with any temporal element (timegroups or standalone media) via PlaybackHost interface
41
+ */
42
+ export declare class PlaybackController implements ReactiveController {
43
+ #private;
44
+ seekTask: Task<readonly [number | undefined], number | undefined>;
45
+ constructor(host: PlaybackHost);
46
+ get currentTime(): number;
47
+ set currentTime(time: number);
48
+ get playing(): boolean;
49
+ setPlaying(value: boolean): void;
50
+ get loop(): boolean;
51
+ setLoop(value: boolean): void;
52
+ get currentTimeMs(): number;
53
+ setCurrentTimeMs(value: number): void;
54
+ play(): void;
55
+ pause(): void;
56
+ hostConnected(): void;
57
+ hostDisconnected(): void;
58
+ hostUpdated(): void;
59
+ runThrottledFrameTask(): Promise<void>;
60
+ addListener(listener: (event: PlaybackControllerUpdateEvent) => void): void;
61
+ removeListener(listener: (event: PlaybackControllerUpdateEvent) => void): void;
62
+ remove(): void;
63
+ private maybeLoopPlayback;
64
+ private stopPlayback;
65
+ private startPlayback;
66
+ }
67
+ export {};
@@ -0,0 +1,310 @@
1
+ import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
2
+ import { currentTimeContext } from "./currentTimeContext.js";
3
+ import { durationContext } from "./durationContext.js";
4
+ import { loopContext, playingContext } from "./playingContext.js";
5
+ import { ContextProvider } from "@lit/context";
6
+ import { Task, TaskStatus } from "@lit/task";
7
+ var PlaybackController = class {
8
+ #host;
9
+ #playing = false;
10
+ #loop = false;
11
+ #listeners = /* @__PURE__ */ new Set();
12
+ #playingProvider;
13
+ #loopProvider;
14
+ #currentTimeMsProvider;
15
+ #durationMsProvider;
16
+ #FPS = 30;
17
+ #MS_PER_FRAME = 1e3 / this.#FPS;
18
+ #playbackAudioContext = null;
19
+ #playbackAnimationFrameRequest = null;
20
+ #AUDIO_PLAYBACK_SLICE_MS = 47 * 1024 / 48e3 * 1e3;
21
+ #frameTaskInProgress = false;
22
+ #pendingFrameTaskRun = false;
23
+ #processingPendingFrameTask = false;
24
+ #currentTime = void 0;
25
+ #seekInProgress = false;
26
+ #pendingSeekTime;
27
+ #processingPendingSeek = false;
28
+ #loopingPlayback = false;
29
+ #playbackWrapTimeSeconds = 0;
30
+ constructor(host) {
31
+ this.#host = host;
32
+ host.addController(this);
33
+ this.seekTask = new Task(this.#host, {
34
+ autoRun: false,
35
+ args: () => [this.#pendingSeekTime ?? this.#currentTime],
36
+ onComplete: () => {},
37
+ task: async ([targetTime]) => {
38
+ await this.#host.waitForMediaDurations?.();
39
+ const newTime = Math.max(0, Math.min(targetTime ?? 0, this.#host.durationMs / 1e3));
40
+ this.#currentTime = newTime;
41
+ this.#host.requestUpdate("currentTime");
42
+ this.#currentTimeMsProvider.setValue(this.currentTimeMs);
43
+ this.#notifyListeners({
44
+ property: "currentTimeMs",
45
+ value: this.currentTimeMs
46
+ });
47
+ await this.runThrottledFrameTask();
48
+ this.#host.saveTimeToLocalStorage?.(newTime);
49
+ this.#seekInProgress = false;
50
+ return newTime;
51
+ }
52
+ });
53
+ this.#playingProvider = new ContextProvider(host, {
54
+ context: playingContext,
55
+ initialValue: this.#playing
56
+ });
57
+ this.#loopProvider = new ContextProvider(host, {
58
+ context: loopContext,
59
+ initialValue: this.#loop
60
+ });
61
+ this.#currentTimeMsProvider = new ContextProvider(host, {
62
+ context: currentTimeContext,
63
+ initialValue: host.currentTimeMs
64
+ });
65
+ this.#durationMsProvider = new ContextProvider(host, {
66
+ context: durationContext,
67
+ initialValue: host.durationMs
68
+ });
69
+ }
70
+ get currentTime() {
71
+ return this.#currentTime ?? 0;
72
+ }
73
+ set currentTime(time) {
74
+ time = Math.max(0, Math.min(this.#host.durationMs / 1e3, time));
75
+ if (Number.isNaN(time)) return;
76
+ if (time === this.#currentTime && !this.#processingPendingSeek) return;
77
+ if (this.#pendingSeekTime === time) return;
78
+ if (this.#seekInProgress) {
79
+ this.#pendingSeekTime = time;
80
+ this.#currentTime = time;
81
+ return;
82
+ }
83
+ this.#currentTime = time;
84
+ this.#seekInProgress = true;
85
+ this.seekTask.run().finally(() => {
86
+ if (this.#pendingSeekTime !== void 0 && this.#pendingSeekTime !== time) {
87
+ const pendingTime = this.#pendingSeekTime;
88
+ this.#pendingSeekTime = void 0;
89
+ this.#processingPendingSeek = true;
90
+ try {
91
+ this.currentTime = pendingTime;
92
+ } finally {
93
+ this.#processingPendingSeek = false;
94
+ }
95
+ } else this.#pendingSeekTime = void 0;
96
+ });
97
+ }
98
+ get playing() {
99
+ return this.#playing;
100
+ }
101
+ setPlaying(value) {
102
+ if (this.#playing === value) return;
103
+ this.#playing = value;
104
+ this.#playingProvider.setValue(value);
105
+ this.#host.requestUpdate("playing");
106
+ this.#notifyListeners({
107
+ property: "playing",
108
+ value
109
+ });
110
+ if (value) this.startPlayback();
111
+ else this.stopPlayback();
112
+ }
113
+ get loop() {
114
+ return this.#loop;
115
+ }
116
+ setLoop(value) {
117
+ if (this.#loop === value) return;
118
+ this.#loop = value;
119
+ this.#loopProvider.setValue(value);
120
+ this.#host.requestUpdate("loop");
121
+ this.#notifyListeners({
122
+ property: "loop",
123
+ value
124
+ });
125
+ }
126
+ get currentTimeMs() {
127
+ return this.currentTime * 1e3;
128
+ }
129
+ setCurrentTimeMs(value) {
130
+ this.currentTime = value / 1e3;
131
+ }
132
+ #updatePlaybackTime(timeMs) {
133
+ const timeSec = timeMs / 1e3;
134
+ if (this.#currentTime === timeSec) return;
135
+ this.#currentTime = timeSec;
136
+ this.#host.requestUpdate("currentTime");
137
+ this.#currentTimeMsProvider.setValue(timeMs);
138
+ this.#notifyListeners({
139
+ property: "currentTimeMs",
140
+ value: timeMs
141
+ });
142
+ this.runThrottledFrameTask();
143
+ }
144
+ play() {
145
+ this.setPlaying(true);
146
+ }
147
+ pause() {
148
+ this.setPlaying(false);
149
+ }
150
+ hostConnected() {
151
+ if (this.#playing) this.startPlayback();
152
+ else this.#host.waitForMediaDurations?.().then(() => {
153
+ const maybeLoadedTime = this.#host.loadTimeFromLocalStorage?.();
154
+ if (maybeLoadedTime !== void 0) this.currentTime = maybeLoadedTime;
155
+ else if (this.#currentTime === void 0) this.#currentTime = 0;
156
+ if (EF_INTERACTIVE && this.seekTask.status === TaskStatus.INITIAL) this.seekTask.run();
157
+ });
158
+ }
159
+ hostDisconnected() {
160
+ this.pause();
161
+ }
162
+ hostUpdated() {
163
+ this.#durationMsProvider.setValue(this.#host.durationMs);
164
+ this.#currentTimeMsProvider.setValue(this.currentTimeMs);
165
+ }
166
+ async runThrottledFrameTask() {
167
+ if (this.#frameTaskInProgress) {
168
+ this.#pendingFrameTaskRun = true;
169
+ while (this.#frameTaskInProgress) await this.#host.frameTask.taskComplete;
170
+ return;
171
+ }
172
+ this.#frameTaskInProgress = true;
173
+ try {
174
+ await this.#host.frameTask.run();
175
+ } catch (error) {
176
+ console.error("Frame task error:", error);
177
+ } finally {
178
+ this.#frameTaskInProgress = false;
179
+ if (this.#pendingFrameTaskRun && !this.#processingPendingFrameTask) {
180
+ this.#pendingFrameTaskRun = false;
181
+ this.#processingPendingFrameTask = true;
182
+ try {
183
+ await this.runThrottledFrameTask();
184
+ } finally {
185
+ this.#processingPendingFrameTask = false;
186
+ }
187
+ } else this.#pendingFrameTaskRun = false;
188
+ }
189
+ }
190
+ addListener(listener) {
191
+ this.#listeners.add(listener);
192
+ }
193
+ removeListener(listener) {
194
+ this.#listeners.delete(listener);
195
+ }
196
+ #notifyListeners(event) {
197
+ for (const listener of this.#listeners) listener(event);
198
+ }
199
+ remove() {
200
+ this.stopPlayback();
201
+ this.#listeners.clear();
202
+ this.#host.removeController(this);
203
+ }
204
+ #syncPlayheadToAudioContext(startMs) {
205
+ const audioContextTime = this.#playbackAudioContext?.currentTime ?? 0;
206
+ const endMs = this.#host.endTimeMs;
207
+ let rawTimeMs;
208
+ if (this.#playbackWrapTimeSeconds > 0 && audioContextTime >= this.#playbackWrapTimeSeconds) rawTimeMs = (audioContextTime - this.#playbackWrapTimeSeconds) * 1e3 % endMs;
209
+ else {
210
+ rawTimeMs = startMs + audioContextTime * 1e3;
211
+ if (this.#loopingPlayback && rawTimeMs >= endMs) rawTimeMs = rawTimeMs % endMs;
212
+ }
213
+ const nextTimeMs = Math.round(rawTimeMs / this.#MS_PER_FRAME) * this.#MS_PER_FRAME;
214
+ this.#updatePlaybackTime(nextTimeMs);
215
+ if (!this.#loopingPlayback && nextTimeMs >= endMs) {
216
+ this.maybeLoopPlayback();
217
+ return;
218
+ }
219
+ this.#playbackAnimationFrameRequest = requestAnimationFrame(() => {
220
+ this.#syncPlayheadToAudioContext(startMs);
221
+ });
222
+ }
223
+ async maybeLoopPlayback() {
224
+ if (this.#loop) {
225
+ this.setCurrentTimeMs(0);
226
+ requestAnimationFrame(() => {
227
+ this.startPlayback();
228
+ });
229
+ } else {
230
+ this.setCurrentTimeMs(0);
231
+ this.pause();
232
+ }
233
+ }
234
+ async stopPlayback() {
235
+ if (this.#playbackAudioContext) {
236
+ if (this.#playbackAudioContext.state !== "closed") await this.#playbackAudioContext.close();
237
+ }
238
+ if (this.#playbackAnimationFrameRequest) cancelAnimationFrame(this.#playbackAnimationFrameRequest);
239
+ this.#playbackAudioContext = null;
240
+ this.#playbackAnimationFrameRequest = null;
241
+ }
242
+ async startPlayback() {
243
+ await this.stopPlayback();
244
+ const host = this.#host;
245
+ if (!host) return;
246
+ if (host.waitForMediaDurations) await host.waitForMediaDurations();
247
+ const currentMs = this.currentTimeMs;
248
+ const fromMs = currentMs;
249
+ const toMs = host.endTimeMs;
250
+ if (fromMs >= toMs) {
251
+ this.pause();
252
+ return;
253
+ }
254
+ let bufferCount = 0;
255
+ this.#playbackAudioContext = new AudioContext({ latencyHint: "playback" });
256
+ this.#loopingPlayback = this.#loop;
257
+ this.#playbackWrapTimeSeconds = 0;
258
+ if (this.#playbackAnimationFrameRequest) cancelAnimationFrame(this.#playbackAnimationFrameRequest);
259
+ this.#syncPlayheadToAudioContext(currentMs);
260
+ const playbackContext = this.#playbackAudioContext;
261
+ if (playbackContext.state === "suspended") {
262
+ console.warn("AudioContext is suspended, media playback will not work until user has interacted with page.");
263
+ this.setPlaying(false);
264
+ return;
265
+ }
266
+ await playbackContext.suspend();
267
+ let logicalTimeMs = currentMs;
268
+ let audioContextTimeMs = 0;
269
+ let hasWrapped = false;
270
+ const fillBuffer = async () => {
271
+ if (bufferCount > 2) return;
272
+ if (await queueBufferSource()) fillBuffer();
273
+ };
274
+ const queueBufferSource = async () => {
275
+ if (hasWrapped && !this.#loopingPlayback) return false;
276
+ const startMs = logicalTimeMs;
277
+ const endMs = Math.min(logicalTimeMs + this.#AUDIO_PLAYBACK_SLICE_MS, toMs);
278
+ const willReachEnd = endMs >= toMs;
279
+ if (!host.renderAudio) return false;
280
+ const audioBuffer = await host.renderAudio(startMs, endMs);
281
+ bufferCount++;
282
+ const source = playbackContext.createBufferSource();
283
+ source.buffer = audioBuffer;
284
+ source.connect(playbackContext.destination);
285
+ source.start(audioContextTimeMs / 1e3);
286
+ const sliceDurationMs = endMs - startMs;
287
+ source.onended = () => {
288
+ bufferCount--;
289
+ if (willReachEnd) if (!this.#loopingPlayback) this.maybeLoopPlayback();
290
+ else fillBuffer();
291
+ else fillBuffer();
292
+ };
293
+ audioContextTimeMs += sliceDurationMs;
294
+ if (willReachEnd && this.#loopingPlayback) {
295
+ hasWrapped = true;
296
+ this.#playbackWrapTimeSeconds = (toMs - fromMs) / 1e3;
297
+ logicalTimeMs = 0;
298
+ } else logicalTimeMs = endMs;
299
+ return true;
300
+ };
301
+ try {
302
+ await fillBuffer();
303
+ await playbackContext.resume();
304
+ } catch (error) {
305
+ if (error instanceof Error && (error.name === "InvalidStateError" || error.message.includes("closed"))) return;
306
+ throw error;
307
+ }
308
+ }
309
+ };
310
+ export { PlaybackController };
@@ -1,2 +1,2 @@
1
- var TWMixin_default = "*,:before,:after{box-sizing:border-box;border:0 solid #e5e7eb}:before,:after{--tw-content:\"\"}html,:host{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{line-height:inherit;margin:0}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-feature-settings:normal;font-variation-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:#0000;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{margin:0;padding:0;list-style:none}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder{opacity:1;color:#9ca3af}textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.left-0{left:0}.top-0{top:0}.isolate{isolation:isolate}.z-10{z-index:10}.z-20,.z-\\[20\\]{z-index:20}.z-\\[5\\]{z-index:5}.col-span-2{grid-column:span 2/span 2}.mx-2{margin-left:.5rem;margin-right:.5rem}.mb-\\[1px\\]{margin-bottom:1px}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.grid{display:grid}.contents{display:contents}.hidden{display:none}.size-full{width:100%;height:100%}.h-\\[1\\.1rem\\]{height:1.1rem}.h-\\[200px\\]{height:200px}.h-\\[270px\\]{height:270px}.h-\\[300px\\]{height:300px}.h-\\[360px\\]{height:360px}.h-\\[500px\\]{height:500px}.h-\\[5px\\]{height:5px}.h-full{height:100%}.w-1{width:.25rem}.w-\\[1000px\\]{width:1000px}.w-\\[2px\\]{width:2px}.w-\\[480px\\]{width:480px}.w-\\[600px\\]{width:600px}.w-\\[640px\\]{width:640px}.w-full{width:100%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.cursor-crosshair{cursor:crosshair}.resize{resize:both}.place-content-center{place-content:center}.items-center{align-items:center}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.whitespace-nowrap{white-space:nowrap}.text-nowrap{text-wrap:nowrap}.rounded{border-radius:.25rem}.border{border-width:1px}.border-r-2{border-right-width:2px}.border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity))}.border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity))}.border-green-200{--tw-border-opacity:1;border-color:rgb(187 247 208/var(--tw-border-opacity))}.border-green-500{--tw-border-opacity:1;border-color:rgb(34 197 94/var(--tw-border-opacity))}.border-purple-200{--tw-border-opacity:1;border-color:rgb(233 213 255/var(--tw-border-opacity))}.border-red-700{--tw-border-opacity:1;border-color:rgb(185 28 28/var(--tw-border-opacity))}.border-slate-500{--tw-border-opacity:1;border-color:rgb(100 116 139/var(--tw-border-opacity))}.border-slate-600{--tw-border-opacity:1;border-color:rgb(71 85 105/var(--tw-border-opacity))}.border-yellow-500{--tw-border-opacity:1;border-color:rgb(234 179 8/var(--tw-border-opacity))}.border-b-slate-600{--tw-border-opacity:1;border-bottom-color:rgb(71 85 105/var(--tw-border-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-blue-200{--tw-bg-opacity:1;background-color:rgb(191 219 254/var(--tw-bg-opacity))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity))}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(187 247 208/var(--tw-bg-opacity))}.bg-green-50{--tw-bg-opacity:1;background-color:rgb(240 253 244/var(--tw-bg-opacity))}.bg-lime-400{--tw-bg-opacity:1;background-color:rgb(163 230 53/var(--tw-bg-opacity))}.bg-purple-50{--tw-bg-opacity:1;background-color:rgb(250 245 255/var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity))}.bg-slate-200{--tw-bg-opacity:1;background-color:rgb(226 232 240/var(--tw-bg-opacity))}.bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}.bg-slate-500{--tw-bg-opacity:1;background-color:rgb(100 116 139/var(--tw-bg-opacity))}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity))}.bg-yellow-200{--tw-bg-opacity:1;background-color:rgb(254 240 138/var(--tw-bg-opacity))}.bg-yellow-400{--tw-bg-opacity:1;background-color:rgb(250 204 21/var(--tw-bg-opacity))}.bg-opacity-20{--tw-bg-opacity:.2}.object-contain{-o-object-fit:contain;object-fit:contain}.p-4{padding:1rem}.p-\\[1px\\]{padding:1px}.px-0{padding-left:0;padding-right:0}.px-0\\.5{padding-left:.125rem;padding-right:.125rem}.pb-0{padding-bottom:0}.pl-1{padding-left:.25rem}.pl-2{padding-left:.5rem}.pr-0{padding-right:0}.pr-1{padding-right:.25rem}.pt-\\[8px\\]{padding-top:8px}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-\\[8px\\]{font-size:8px}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.ordinal{--tw-ordinal:ordinal;font-variant-numeric:var(--tw-ordinal)var(--tw-slashed-zero)var(--tw-numeric-figure)var(--tw-numeric-spacing)var(--tw-numeric-fraction)}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-green-200{--tw-text-opacity:1;color:rgb(187 247 208/var(--tw-text-opacity))}.text-green-900{--tw-text-opacity:1;color:rgb(20 83 45/var(--tw-text-opacity))}.line-through{text-decoration-line:line-through}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-slate-300{--tw-shadow-color:#cbd5e1;--tw-shadow:var(--tw-shadow-colored)}.shadow-slate-600{--tw-shadow-color:#475569;--tw-shadow:var(--tw-shadow-colored)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.filter{filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter,backdrop-filter;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.hover\\:bg-slate-400:hover{--tw-bg-opacity:1;background-color:rgb(148 163 184/var(--tw-bg-opacity))}.peer:hover~.peer-hover\\:border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184/var(--tw-border-opacity))}.peer:hover~.peer-hover\\:bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}.data-\\[focused\\]\\:bg-slate-400[data-focused]{--tw-bg-opacity:1;background-color:rgb(148 163 184/var(--tw-bg-opacity))}.peer[data-focused]~.peer-data-\\[focused\\]\\:border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184/var(--tw-border-opacity))}.peer[data-focused]~.peer-data-\\[focused\\]\\:bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}";
1
+ var TWMixin_default = "*,:before,:after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border:0 solid #e5e7eb}:before,:after{--tw-content:\"\"}html,:host{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{line-height:inherit;margin:0}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-feature-settings:normal;font-variation-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:#0000;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{margin:0;padding:0;list-style:none}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder{opacity:1;color:#9ca3af}textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.left-0{left:0}.top-0{top:0}.isolate{isolation:isolate}.z-10{z-index:10}.z-20,.z-\\[20\\]{z-index:20}.z-\\[5\\]{z-index:5}.col-span-2{grid-column:span 2/span 2}.mx-2{margin-left:.5rem;margin-right:.5rem}.mb-\\[1px\\]{margin-bottom:1px}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.grid{display:grid}.contents{display:contents}.hidden{display:none}.size-full{width:100%;height:100%}.h-\\[1\\.1rem\\]{height:1.1rem}.h-\\[200px\\]{height:200px}.h-\\[270px\\]{height:270px}.h-\\[300px\\]{height:300px}.h-\\[360px\\]{height:360px}.h-\\[500px\\]{height:500px}.h-\\[5px\\]{height:5px}.h-full{height:100%}.w-1{width:.25rem}.w-\\[1000px\\]{width:1000px}.w-\\[2px\\]{width:2px}.w-\\[480px\\]{width:480px}.w-\\[600px\\]{width:600px}.w-\\[640px\\]{width:640px}.w-full{width:100%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.cursor-crosshair{cursor:crosshair}.resize{resize:both}.place-content-center{place-content:center}.items-center{align-items:center}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.whitespace-nowrap{white-space:nowrap}.text-nowrap{text-wrap:nowrap}.rounded{border-radius:.25rem}.border{border-width:1px}.border-r-2{border-right-width:2px}.border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity,1))}.border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.border-green-200{--tw-border-opacity:1;border-color:rgb(187 247 208/var(--tw-border-opacity,1))}.border-green-500{--tw-border-opacity:1;border-color:rgb(34 197 94/var(--tw-border-opacity,1))}.border-purple-200{--tw-border-opacity:1;border-color:rgb(233 213 255/var(--tw-border-opacity,1))}.border-red-700{--tw-border-opacity:1;border-color:rgb(185 28 28/var(--tw-border-opacity,1))}.border-slate-500{--tw-border-opacity:1;border-color:rgb(100 116 139/var(--tw-border-opacity,1))}.border-slate-600{--tw-border-opacity:1;border-color:rgb(71 85 105/var(--tw-border-opacity,1))}.border-yellow-500{--tw-border-opacity:1;border-color:rgb(234 179 8/var(--tw-border-opacity,1))}.border-b-slate-600{--tw-border-opacity:1;border-bottom-color:rgb(71 85 105/var(--tw-border-opacity,1))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.bg-blue-200{--tw-bg-opacity:1;background-color:rgb(191 219 254/var(--tw-bg-opacity,1))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(187 247 208/var(--tw-bg-opacity,1))}.bg-green-50{--tw-bg-opacity:1;background-color:rgb(240 253 244/var(--tw-bg-opacity,1))}.bg-lime-400{--tw-bg-opacity:1;background-color:rgb(163 230 53/var(--tw-bg-opacity,1))}.bg-purple-50{--tw-bg-opacity:1;background-color:rgb(250 245 255/var(--tw-bg-opacity,1))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.bg-slate-200{--tw-bg-opacity:1;background-color:rgb(226 232 240/var(--tw-bg-opacity,1))}.bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity,1))}.bg-slate-500{--tw-bg-opacity:1;background-color:rgb(100 116 139/var(--tw-bg-opacity,1))}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity,1))}.bg-yellow-200{--tw-bg-opacity:1;background-color:rgb(254 240 138/var(--tw-bg-opacity,1))}.bg-yellow-400{--tw-bg-opacity:1;background-color:rgb(250 204 21/var(--tw-bg-opacity,1))}.bg-opacity-20{--tw-bg-opacity:.2}.object-contain{-o-object-fit:contain;object-fit:contain}.p-4{padding:1rem}.p-\\[1px\\]{padding:1px}.px-0\\.5{padding-left:.125rem;padding-right:.125rem}.pb-0{padding-bottom:0}.pl-1{padding-left:.25rem}.pl-2{padding-left:.5rem}.pr-0{padding-right:0}.pr-1{padding-right:.25rem}.pt-\\[8px\\]{padding-top:8px}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-\\[8px\\]{font-size:8px}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.ordinal{--tw-ordinal:ordinal;font-variant-numeric:var(--tw-ordinal)var(--tw-slashed-zero)var(--tw-numeric-figure)var(--tw-numeric-spacing)var(--tw-numeric-fraction)}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.text-green-200{--tw-text-opacity:1;color:rgb(187 247 208/var(--tw-text-opacity,1))}.text-green-900{--tw-text-opacity:1;color:rgb(20 83 45/var(--tw-text-opacity,1))}.line-through{text-decoration-line:line-through}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-slate-300{--tw-shadow-color:#cbd5e1;--tw-shadow:var(--tw-shadow-colored)}.shadow-slate-600{--tw-shadow-color:#475569;--tw-shadow:var(--tw-shadow-colored)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.filter{filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter,backdrop-filter;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.hover\\:bg-slate-400:hover{--tw-bg-opacity:1;background-color:rgb(148 163 184/var(--tw-bg-opacity,1))}.peer:hover~.peer-hover\\:border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184/var(--tw-border-opacity,1))}.peer:hover~.peer-hover\\:bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity,1))}.data-\\[focused\\]\\:bg-slate-400[data-focused]{--tw-bg-opacity:1;background-color:rgb(148 163 184/var(--tw-bg-opacity,1))}.peer[data-focused]~.peer-data-\\[focused\\]\\:border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184/var(--tw-border-opacity,1))}.peer[data-focused]~.peer-data-\\[focused\\]\\:bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity,1))}";
2
2
  export { TWMixin_default as default };
@@ -0,0 +1,10 @@
1
+ import { Context } from '@lit/context';
2
+ import { LitElement } from 'lit';
3
+ import { ControllableInterface } from './Controllable.js';
4
+ type Constructor<T = {}> = new (...args: any[]) => T;
5
+ export declare function TargetOrContextMixin<T extends Constructor<LitElement>>(superClass: T, contextToProxy: Context<any, any>): Constructor<{
6
+ target: string;
7
+ targetElement: ControllableInterface | null;
8
+ effectiveContext: ControllableInterface | null;
9
+ }> & T;
10
+ export {};