@editframe/elements 0.26.3-beta.0 → 0.30.0-beta.13

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 (191) hide show
  1. package/dist/elements/EFSourceMixin.js +1 -1
  2. package/dist/elements/EFSourceMixin.js.map +1 -1
  3. package/dist/elements/EFSurface.d.ts +4 -4
  4. package/dist/elements/EFText.d.ts +52 -0
  5. package/dist/elements/EFText.js +319 -0
  6. package/dist/elements/EFText.js.map +1 -0
  7. package/dist/elements/EFTextSegment.d.ts +30 -0
  8. package/dist/elements/EFTextSegment.js +94 -0
  9. package/dist/elements/EFTextSegment.js.map +1 -0
  10. package/dist/elements/EFThumbnailStrip.d.ts +4 -4
  11. package/dist/elements/EFWaveform.d.ts +4 -4
  12. package/dist/elements/FetchMixin.js +22 -7
  13. package/dist/elements/FetchMixin.js.map +1 -1
  14. package/dist/elements/easingUtils.js +62 -0
  15. package/dist/elements/easingUtils.js.map +1 -0
  16. package/dist/elements/updateAnimations.js +57 -10
  17. package/dist/elements/updateAnimations.js.map +1 -1
  18. package/dist/gui/ContextMixin.js +11 -2
  19. package/dist/gui/ContextMixin.js.map +1 -1
  20. package/dist/gui/EFConfiguration.d.ts +4 -4
  21. package/dist/gui/EFControls.d.ts +2 -2
  22. package/dist/gui/EFDial.d.ts +4 -4
  23. package/dist/gui/EFDial.js +4 -2
  24. package/dist/gui/EFDial.js.map +1 -1
  25. package/dist/gui/EFFilmstrip.d.ts +32 -6
  26. package/dist/gui/EFFilmstrip.js +314 -50
  27. package/dist/gui/EFFilmstrip.js.map +1 -1
  28. package/dist/gui/EFFitScale.js +39 -15
  29. package/dist/gui/EFFitScale.js.map +1 -1
  30. package/dist/gui/EFFocusOverlay.d.ts +4 -4
  31. package/dist/gui/EFPause.d.ts +4 -4
  32. package/dist/gui/EFPlay.d.ts +4 -4
  33. package/dist/gui/EFPreview.d.ts +4 -4
  34. package/dist/gui/EFPreview.js +2 -2
  35. package/dist/gui/EFPreview.js.map +1 -1
  36. package/dist/gui/EFResizableBox.d.ts +4 -4
  37. package/dist/gui/EFResizableBox.js +6 -3
  38. package/dist/gui/EFResizableBox.js.map +1 -1
  39. package/dist/gui/EFScrubber.d.ts +8 -5
  40. package/dist/gui/EFScrubber.js +64 -12
  41. package/dist/gui/EFScrubber.js.map +1 -1
  42. package/dist/gui/EFTimeDisplay.d.ts +4 -4
  43. package/dist/gui/EFToggleLoop.d.ts +4 -4
  44. package/dist/gui/EFTogglePlay.d.ts +4 -4
  45. package/dist/gui/EFWorkbench.d.ts +4 -4
  46. package/dist/gui/EFWorkbench.js +16 -3
  47. package/dist/gui/EFWorkbench.js.map +1 -1
  48. package/dist/gui/TWMixin.js +1 -1
  49. package/dist/gui/TWMixin.js.map +1 -1
  50. package/dist/index.d.ts +3 -1
  51. package/dist/index.js +3 -1
  52. package/dist/index.js.map +1 -1
  53. package/dist/style.css +7 -120
  54. package/package.json +3 -3
  55. package/scripts/build-css.js +5 -9
  56. package/test/constants.ts +8 -0
  57. package/test/recordReplayProxyPlugin.js +76 -10
  58. package/test/setup.ts +32 -0
  59. package/test/useMSW.ts +3 -0
  60. package/test/useTranscodeMSW.ts +191 -0
  61. package/tsdown.config.ts +7 -5
  62. package/types.json +1 -1
  63. package/src/elements/ContextProxiesController.ts +0 -124
  64. package/src/elements/CrossUpdateController.ts +0 -22
  65. package/src/elements/EFAudio.browsertest.ts +0 -706
  66. package/src/elements/EFAudio.ts +0 -56
  67. package/src/elements/EFCaptions.browsertest.ts +0 -1960
  68. package/src/elements/EFCaptions.ts +0 -823
  69. package/src/elements/EFImage.browsertest.ts +0 -120
  70. package/src/elements/EFImage.ts +0 -113
  71. package/src/elements/EFMedia/AssetIdMediaEngine.test.ts +0 -224
  72. package/src/elements/EFMedia/AssetIdMediaEngine.ts +0 -110
  73. package/src/elements/EFMedia/AssetMediaEngine.browsertest.ts +0 -140
  74. package/src/elements/EFMedia/AssetMediaEngine.ts +0 -385
  75. package/src/elements/EFMedia/BaseMediaEngine.browsertest.ts +0 -400
  76. package/src/elements/EFMedia/BaseMediaEngine.ts +0 -505
  77. package/src/elements/EFMedia/BufferedSeekingInput.browsertest.ts +0 -386
  78. package/src/elements/EFMedia/BufferedSeekingInput.ts +0 -430
  79. package/src/elements/EFMedia/JitMediaEngine.browsertest.ts +0 -226
  80. package/src/elements/EFMedia/JitMediaEngine.ts +0 -256
  81. package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.ts +0 -679
  82. package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.ts +0 -117
  83. package/src/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.ts +0 -246
  84. package/src/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.browsertest.ts +0 -59
  85. package/src/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.ts +0 -27
  86. package/src/elements/EFMedia/audioTasks/makeAudioInputTask.browsertest.ts +0 -55
  87. package/src/elements/EFMedia/audioTasks/makeAudioInputTask.ts +0 -53
  88. package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.ts +0 -207
  89. package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.ts +0 -72
  90. package/src/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.ts +0 -32
  91. package/src/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.ts +0 -29
  92. package/src/elements/EFMedia/audioTasks/makeAudioTasksVideoOnly.browsertest.ts +0 -95
  93. package/src/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.ts +0 -184
  94. package/src/elements/EFMedia/shared/AudioSpanUtils.ts +0 -129
  95. package/src/elements/EFMedia/shared/BufferUtils.ts +0 -342
  96. package/src/elements/EFMedia/shared/GlobalInputCache.ts +0 -77
  97. package/src/elements/EFMedia/shared/MediaTaskUtils.ts +0 -44
  98. package/src/elements/EFMedia/shared/PrecisionUtils.ts +0 -46
  99. package/src/elements/EFMedia/shared/RenditionHelpers.browsertest.ts +0 -246
  100. package/src/elements/EFMedia/shared/RenditionHelpers.ts +0 -56
  101. package/src/elements/EFMedia/shared/ThumbnailExtractor.ts +0 -227
  102. package/src/elements/EFMedia/tasks/makeMediaEngineTask.browsertest.ts +0 -167
  103. package/src/elements/EFMedia/tasks/makeMediaEngineTask.ts +0 -88
  104. package/src/elements/EFMedia/videoTasks/MainVideoInputCache.ts +0 -76
  105. package/src/elements/EFMedia/videoTasks/ScrubInputCache.ts +0 -61
  106. package/src/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.ts +0 -114
  107. package/src/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.ts +0 -35
  108. package/src/elements/EFMedia/videoTasks/makeScrubVideoInputTask.ts +0 -52
  109. package/src/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.ts +0 -124
  110. package/src/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.ts +0 -44
  111. package/src/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.ts +0 -32
  112. package/src/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.ts +0 -370
  113. package/src/elements/EFMedia/videoTasks/makeVideoBufferTask.ts +0 -109
  114. package/src/elements/EFMedia.browsertest.ts +0 -872
  115. package/src/elements/EFMedia.ts +0 -341
  116. package/src/elements/EFSourceMixin.ts +0 -60
  117. package/src/elements/EFSurface.browsertest.ts +0 -151
  118. package/src/elements/EFSurface.ts +0 -142
  119. package/src/elements/EFTemporal.browsertest.ts +0 -215
  120. package/src/elements/EFTemporal.ts +0 -800
  121. package/src/elements/EFThumbnailStrip.browsertest.ts +0 -585
  122. package/src/elements/EFThumbnailStrip.media-engine.browsertest.ts +0 -714
  123. package/src/elements/EFThumbnailStrip.ts +0 -906
  124. package/src/elements/EFTimegroup.browsertest.ts +0 -934
  125. package/src/elements/EFTimegroup.ts +0 -882
  126. package/src/elements/EFVideo.browsertest.ts +0 -1482
  127. package/src/elements/EFVideo.ts +0 -564
  128. package/src/elements/EFWaveform.ts +0 -547
  129. package/src/elements/FetchContext.browsertest.ts +0 -401
  130. package/src/elements/FetchMixin.ts +0 -38
  131. package/src/elements/SampleBuffer.ts +0 -94
  132. package/src/elements/TargetController.browsertest.ts +0 -230
  133. package/src/elements/TargetController.ts +0 -224
  134. package/src/elements/TimegroupController.ts +0 -26
  135. package/src/elements/durationConverter.ts +0 -35
  136. package/src/elements/parseTimeToMs.ts +0 -9
  137. package/src/elements/printTaskStatus.ts +0 -16
  138. package/src/elements/renderTemporalAudio.ts +0 -108
  139. package/src/elements/updateAnimations.browsertest.ts +0 -1884
  140. package/src/elements/updateAnimations.ts +0 -217
  141. package/src/elements/util.ts +0 -24
  142. package/src/gui/ContextMixin.browsertest.ts +0 -860
  143. package/src/gui/ContextMixin.ts +0 -562
  144. package/src/gui/Controllable.browsertest.ts +0 -258
  145. package/src/gui/Controllable.ts +0 -41
  146. package/src/gui/EFConfiguration.ts +0 -40
  147. package/src/gui/EFControls.browsertest.ts +0 -389
  148. package/src/gui/EFControls.ts +0 -195
  149. package/src/gui/EFDial.browsertest.ts +0 -84
  150. package/src/gui/EFDial.ts +0 -172
  151. package/src/gui/EFFilmstrip.browsertest.ts +0 -712
  152. package/src/gui/EFFilmstrip.ts +0 -1349
  153. package/src/gui/EFFitScale.ts +0 -152
  154. package/src/gui/EFFocusOverlay.ts +0 -79
  155. package/src/gui/EFPause.browsertest.ts +0 -202
  156. package/src/gui/EFPause.ts +0 -73
  157. package/src/gui/EFPlay.browsertest.ts +0 -202
  158. package/src/gui/EFPlay.ts +0 -73
  159. package/src/gui/EFPreview.ts +0 -74
  160. package/src/gui/EFResizableBox.browsertest.ts +0 -79
  161. package/src/gui/EFResizableBox.ts +0 -898
  162. package/src/gui/EFScrubber.ts +0 -151
  163. package/src/gui/EFTimeDisplay.browsertest.ts +0 -237
  164. package/src/gui/EFTimeDisplay.ts +0 -55
  165. package/src/gui/EFToggleLoop.ts +0 -35
  166. package/src/gui/EFTogglePlay.ts +0 -70
  167. package/src/gui/EFWorkbench.ts +0 -115
  168. package/src/gui/PlaybackController.ts +0 -527
  169. package/src/gui/TWMixin.css +0 -6
  170. package/src/gui/TWMixin.ts +0 -61
  171. package/src/gui/TargetOrContextMixin.ts +0 -185
  172. package/src/gui/currentTimeContext.ts +0 -5
  173. package/src/gui/durationContext.ts +0 -3
  174. package/src/gui/efContext.ts +0 -6
  175. package/src/gui/fetchContext.ts +0 -5
  176. package/src/gui/focusContext.ts +0 -7
  177. package/src/gui/focusedElementContext.ts +0 -5
  178. package/src/gui/playingContext.ts +0 -5
  179. package/src/otel/BridgeSpanExporter.ts +0 -150
  180. package/src/otel/setupBrowserTracing.ts +0 -73
  181. package/src/otel/tracingHelpers.ts +0 -251
  182. package/src/transcoding/cache/RequestDeduplicator.test.ts +0 -170
  183. package/src/transcoding/cache/RequestDeduplicator.ts +0 -65
  184. package/src/transcoding/cache/URLTokenDeduplicator.test.ts +0 -182
  185. package/src/transcoding/cache/URLTokenDeduplicator.ts +0 -101
  186. package/src/transcoding/types/index.ts +0 -312
  187. package/src/transcoding/utils/MediaUtils.ts +0 -63
  188. package/src/transcoding/utils/UrlGenerator.ts +0 -68
  189. package/src/transcoding/utils/constants.ts +0 -36
  190. package/src/utils/LRUCache.test.ts +0 -274
  191. package/src/utils/LRUCache.ts +0 -696
@@ -1,230 +0,0 @@
1
- import { html, LitElement } from "lit";
2
- import { customElement, property, state } from "lit/decorators.js";
3
- import { afterEach, describe, expect, test } from "vitest";
4
- import { EFTargetable, TargetController } from "./TargetController.ts";
5
-
6
- let id = 0;
7
-
8
- const nextId = () => {
9
- return `targetable-test-${id++}`;
10
- };
11
-
12
- @customElement("targetable-test")
13
- class TargetableTest extends EFTargetable(LitElement) {
14
- @property()
15
- value = "initial";
16
-
17
- render() {
18
- return html`<div>${this.value}</div>`;
19
- }
20
- }
21
-
22
- @customElement("targeter-test")
23
- class TargeterTest extends LitElement {
24
- // @ts-expect-error this controller is needed, but never referenced
25
- // biome-ignore lint/correctness/noUnusedPrivateClassMembers: Used for side effects
26
- private targetController: TargetController = new TargetController(this);
27
-
28
- @state()
29
- targetElement: Element | null = null;
30
-
31
- @property()
32
- target = "";
33
-
34
- render() {
35
- const target = this.targetElement;
36
- return html`
37
- <div>
38
- ${target ? html`Found: ${target.tagName}` : html`Finding target...`}
39
- </div>
40
- `;
41
- }
42
- }
43
-
44
- describe("target", () => {
45
- afterEach(() => {
46
- // Clean up all test elements from the document body
47
- document.body.innerHTML = "";
48
- });
49
-
50
- test("should be able to get the target element", async () => {
51
- const target = document.createElement("targetable-test");
52
- const element = document.createElement("targeter-test");
53
- document.body.appendChild(target);
54
- document.body.appendChild(element);
55
-
56
- const id = nextId();
57
- target.id = id;
58
- element.target = id;
59
-
60
- await element.updateComplete;
61
- expect(element.targetElement).toBe(target);
62
- });
63
-
64
- test("should update when document changes", async () => {
65
- const target = document.createElement("targetable-test");
66
- const element = document.createElement("targeter-test");
67
- document.body.appendChild(element);
68
-
69
- const id = nextId();
70
- element.target = id;
71
-
72
- expect(element.targetElement).toBe(null);
73
-
74
- target.id = id;
75
- document.body.appendChild(target);
76
- await element.updateComplete;
77
- expect(element.targetElement).toBe(target);
78
- });
79
-
80
- test("should update when attribute changes", async () => {
81
- const target = document.createElement("targetable-test");
82
- const element = document.createElement("targeter-test");
83
- document.body.appendChild(element);
84
- document.body.appendChild(target);
85
-
86
- const id = nextId();
87
- target.id = id;
88
- element.target = id;
89
-
90
- await element.updateComplete;
91
- expect(element.targetElement).toBe(target);
92
-
93
- target.id = nextId();
94
- await element.updateComplete;
95
- expect(element.targetElement).toBe(null);
96
- });
97
-
98
- test("should update when target is set before id exists", async () => {
99
- const target = document.createElement("targetable-test");
100
- const element = document.createElement("targeter-test");
101
- document.body.appendChild(target);
102
- document.body.appendChild(element);
103
-
104
- const id = nextId();
105
- element.target = id;
106
- expect(element.targetElement).toBe(null);
107
-
108
- target.id = id;
109
- await element.updateComplete;
110
- expect(element.targetElement).toBe(target);
111
- });
112
-
113
- test("should update when target changes to match existing id", async () => {
114
- const target = document.createElement("targetable-test");
115
- const element = document.createElement("targeter-test");
116
- document.body.appendChild(target);
117
- document.body.appendChild(element);
118
-
119
- const id = nextId();
120
- target.id = id;
121
- expect(element.targetElement).toBe(null);
122
-
123
- element.target = id;
124
- await element.updateComplete;
125
- expect(element.targetElement).toBe(target);
126
- });
127
-
128
- test("should handle target being cleared", async () => {
129
- const target = document.createElement("targetable-test");
130
- const element = document.createElement("targeter-test");
131
- document.body.appendChild(target);
132
- document.body.appendChild(element);
133
-
134
- const id = nextId();
135
- target.id = id;
136
- element.target = id;
137
-
138
- await element.updateComplete;
139
- expect(element.targetElement).toBe(target);
140
-
141
- element.target = "";
142
- await element.updateComplete;
143
- expect(element.targetElement).toBe(null);
144
- });
145
-
146
- test("should handle multiple elements targeting the same id", async () => {
147
- const target = document.createElement("targetable-test");
148
- const element1 = document.createElement("targeter-test");
149
- const element2 = document.createElement("targeter-test");
150
- document.body.appendChild(target);
151
- document.body.appendChild(element1);
152
- document.body.appendChild(element2);
153
-
154
- const id = nextId();
155
- target.id = id;
156
- element1.target = id;
157
- element2.target = id;
158
-
159
- await Promise.all([element1.updateComplete, element2.updateComplete]);
160
- expect(element1.targetElement).toBe(target);
161
- expect(element2.targetElement).toBe(target);
162
- });
163
-
164
- test("should handle element removal from DOM", async () => {
165
- const target = document.createElement("targetable-test");
166
- const element = document.createElement("targeter-test");
167
- document.body.appendChild(target);
168
- document.body.appendChild(element);
169
-
170
- const id = nextId();
171
- target.id = id;
172
- element.target = id;
173
-
174
- await element.updateComplete;
175
- expect(element.targetElement).toBe(target);
176
-
177
- document.body.removeChild(target);
178
- await element.updateComplete;
179
- expect(element.targetElement).toBe(null);
180
- });
181
-
182
- test("should handle rapid target id changes", async () => {
183
- const target = document.createElement("targetable-test");
184
- const element = document.createElement("targeter-test");
185
- document.body.appendChild(target);
186
- document.body.appendChild(element);
187
-
188
- const id1 = nextId();
189
- const id2 = nextId();
190
- const id3 = nextId();
191
-
192
- target.id = id1;
193
- element.target = id1;
194
- await element.updateComplete;
195
- expect(element.targetElement).toBe(target);
196
-
197
- target.id = id2;
198
- target.id = id3; // Immediately change again
199
- await element.updateComplete;
200
- expect(element.targetElement).toBe(null);
201
- });
202
-
203
- test("should not trigger unnecessary updates when setting same id multiple times", async () => {
204
- const target = document.createElement("targetable-test");
205
- const element = document.createElement("targeter-test");
206
- document.body.appendChild(target);
207
- document.body.appendChild(element);
208
-
209
- const id = nextId();
210
- target.id = id;
211
- element.target = id;
212
-
213
- await element.updateComplete;
214
- expect(element.targetElement).toBe(target);
215
-
216
- // Set the same ID again
217
- target.id = id;
218
- await element.updateComplete;
219
-
220
- // The target element should remain stable
221
- expect(element.targetElement).toBe(target);
222
- });
223
- });
224
-
225
- declare global {
226
- interface HTMLElementTagNameMap {
227
- "targetable-test": TargetableTest & Element;
228
- "targeter-test": TargeterTest & Element;
229
- }
230
- }
@@ -1,224 +0,0 @@
1
- import { LitElement, type ReactiveController } from "lit";
2
-
3
- type Constructor<T = {}> = new (...args: any[]) => T;
4
-
5
- // Symbol to identify elements that can be targeted
6
- const EF_TARGETABLE = Symbol("EF_TARGETABLE");
7
-
8
- class TargetRegistry {
9
- private idMap = new Map<string, LitElement>();
10
- private callbacks = new Map<
11
- string,
12
- Set<(target: LitElement | undefined) => void>
13
- >();
14
-
15
- subscribe(id: string, callback: (target: LitElement | undefined) => void) {
16
- this.callbacks.set(id, this.callbacks.get(id) ?? new Set());
17
- this.callbacks.get(id)?.add(callback);
18
- }
19
-
20
- unsubscribe(
21
- id: string | null,
22
- callback: (target: LitElement | undefined) => void,
23
- ) {
24
- if (id === null) {
25
- return;
26
- }
27
- this.callbacks.get(id)?.delete(callback);
28
- if (this.callbacks.get(id)?.size === 0) {
29
- this.callbacks.delete(id);
30
- }
31
- }
32
-
33
- get(id: string) {
34
- return this.idMap.get(id);
35
- }
36
-
37
- register(id: string, target: LitElement) {
38
- this.idMap.set(id, target);
39
- for (const callback of this.callbacks.get(id) ?? []) {
40
- callback(target);
41
- }
42
- }
43
-
44
- unregister(id: string, target: LitElement) {
45
- if (this.idMap.get(id) !== target) {
46
- // Avoid unregistering a target that is not the current target
47
- return;
48
- }
49
- for (const callback of this.callbacks.get(id) ?? []) {
50
- callback(undefined);
51
- }
52
- this.idMap.delete(id);
53
- this.callbacks.delete(id);
54
- }
55
- }
56
-
57
- // Map of root nodes to their target registries
58
- const documentRegistries = new WeakMap<Node, TargetRegistry>();
59
-
60
- const getRegistry = (root: Node) => {
61
- let registry = documentRegistries.get(root);
62
- if (!registry) {
63
- registry = new TargetRegistry();
64
- documentRegistries.set(root, registry);
65
- }
66
- return registry;
67
- };
68
-
69
- export declare class TargetableMixinInterface {
70
- id: string;
71
- }
72
-
73
- export const isEFTargetable = (obj: any): obj is TargetableMixinInterface =>
74
- obj[EF_TARGETABLE];
75
-
76
- export const EFTargetable = <T extends Constructor<LitElement>>(
77
- superClass: T,
78
- ) => {
79
- class TargetableElement extends superClass {
80
- #registry: TargetRegistry | null = null;
81
-
82
- static get observedAttributes(): string[] {
83
- // Get parent's observed attributes
84
- const parentAttributes = (superClass as any).observedAttributes || [];
85
- // Add 'id' if not already present
86
- return [...new Set([...parentAttributes, "id"])];
87
- }
88
-
89
- private updateRegistry(oldValue: string, newValue: string) {
90
- if (!this.#registry) return;
91
- if (oldValue === newValue) return;
92
-
93
- if (oldValue) {
94
- this.#registry.unregister(oldValue, this);
95
- }
96
- if (newValue) {
97
- this.#registry.register(newValue, this);
98
- }
99
- }
100
-
101
- connectedCallback() {
102
- super.connectedCallback();
103
- this.#registry = getRegistry(this.getRootNode());
104
- const initialId = this.getAttribute("id");
105
- if (initialId) {
106
- this.updateRegistry("", initialId);
107
- }
108
- }
109
-
110
- attributeChangedCallback(
111
- name: string,
112
- old: string | null,
113
- value: string | null,
114
- ) {
115
- super.attributeChangedCallback(name, old, value);
116
- if (name === "id") {
117
- this.updateRegistry(old ?? "", value ?? "");
118
- }
119
- }
120
-
121
- disconnectedCallback() {
122
- if (this.#registry) {
123
- this.updateRegistry(this.id, "");
124
- this.#registry = null;
125
- }
126
- super.disconnectedCallback();
127
- }
128
- }
129
-
130
- Object.defineProperty(TargetableElement.prototype, EF_TARGETABLE, {
131
- value: true,
132
- });
133
-
134
- return TargetableElement as T;
135
- };
136
-
137
- class TargetUpdateController implements ReactiveController {
138
- constructor(private host: LitElement) {}
139
-
140
- hostConnected() {
141
- this.host.requestUpdate();
142
- }
143
-
144
- hostDisconnected() {
145
- this.host.requestUpdate();
146
- }
147
-
148
- hostUpdate() {
149
- this.host.requestUpdate();
150
- }
151
- }
152
-
153
- export class TargetController implements ReactiveController {
154
- private host: LitElement & { targetElement: Element | null; target: string };
155
- private targetController: ReactiveController | null = null;
156
- private currentTargetString: string | null = null;
157
-
158
- constructor(
159
- host: LitElement & { targetElement: Element | null; target: string },
160
- ) {
161
- this.host = host;
162
- this.host.addController(this);
163
- this.currentTargetString = this.host.target;
164
- if (this.currentTargetString) {
165
- this.registry.subscribe(this.currentTargetString, this.registryCallback);
166
- }
167
- }
168
-
169
- private registryCallback = (target: LitElement | undefined) => {
170
- this.host.targetElement = target ?? null;
171
- };
172
-
173
- private updateTarget() {
174
- const newTarget = this.registry.get(this.host.target);
175
- if (this.host.targetElement !== newTarget) {
176
- this.disconnectFromTarget();
177
- this.host.targetElement = newTarget ?? (null as Element | null);
178
- this.connectToTarget();
179
- this.host.requestUpdate("targetElement");
180
- }
181
- }
182
-
183
- private connectToTarget() {
184
- if (this.host.targetElement instanceof LitElement) {
185
- this.targetController = new TargetUpdateController(this.host);
186
- this.host.targetElement.addController(this.targetController);
187
- }
188
- }
189
-
190
- private disconnectFromTarget() {
191
- if (
192
- this.host.targetElement instanceof LitElement &&
193
- this.targetController
194
- ) {
195
- this.host.targetElement.removeController(this.targetController);
196
- this.targetController = null;
197
- }
198
- }
199
-
200
- private get registry() {
201
- const root = this.host.getRootNode();
202
- return getRegistry(root);
203
- }
204
-
205
- hostDisconnected() {
206
- this.disconnectFromTarget();
207
- }
208
-
209
- hostConnected() {
210
- this.updateTarget();
211
- }
212
-
213
- hostUpdate() {
214
- if (this.currentTargetString !== this.host.target) {
215
- this.registry.unsubscribe(
216
- this.currentTargetString,
217
- this.registryCallback,
218
- );
219
- this.registry.subscribe(this.host.target, this.registryCallback);
220
- this.updateTarget();
221
- this.currentTargetString = this.host.target;
222
- }
223
- }
224
- }
@@ -1,26 +0,0 @@
1
- import type { LitElement, ReactiveController } from "lit";
2
- import type { EFTimegroup } from "./EFTimegroup.js";
3
-
4
- export class TimegroupController implements ReactiveController {
5
- constructor(
6
- private host: EFTimegroup,
7
- private child: { currentTimeMs: number; startTimeMs?: number } & LitElement,
8
- ) {
9
- this.host.addController(this);
10
- }
11
-
12
- remove() {
13
- this.host.removeController(this);
14
- }
15
-
16
- hostDisconnected(): void {
17
- this.host.removeController(this);
18
- }
19
-
20
- hostUpdated(): void {
21
- this.child.requestUpdate();
22
- const newChildTimeMs =
23
- this.host.currentTimeMs - (this.child.startTimeMs ?? 0);
24
- this.child.currentTimeMs = newChildTimeMs;
25
- }
26
- }
@@ -1,35 +0,0 @@
1
- import { parseTimeToMs } from "./parseTimeToMs.js";
2
-
3
- export const durationConverter = {
4
- fromAttribute: (value: string | null) =>
5
- value === null ? null : parseTimeToMs(value),
6
- toAttribute: (value: number | null) => (value === null ? null : `${value}s`),
7
- };
8
-
9
- const positiveDurationConverter = (error: string) => {
10
- return {
11
- fromAttribute: (value: string | null): number | null => {
12
- if (value === null) {
13
- return null;
14
- }
15
- if (value.startsWith("-")) {
16
- throw new Error(error);
17
- }
18
- return parseTimeToMs(value);
19
- },
20
- toAttribute: (value: number | null) =>
21
- value === null ? null : `${value}s`,
22
- };
23
- };
24
-
25
- export const trimDurationConverter = positiveDurationConverter(
26
- "Trimstart & trimend must be a positive value in milliseconds or seconds (1s, 1000ms)",
27
- );
28
-
29
- export const imageDurationConverter = positiveDurationConverter(
30
- "Image duration must be a positive value in milliseconds or seconds (1s, 1000ms)",
31
- );
32
-
33
- export const sourceDurationConverter = positiveDurationConverter(
34
- "Sourcein & sourceout must be a positive value in milliseconds or seconds (1s, 1000ms)",
35
- );
@@ -1,9 +0,0 @@
1
- export const parseTimeToMs = (time: string) => {
2
- if (time.endsWith("ms")) {
3
- return Number.parseFloat(time);
4
- }
5
- if (time.endsWith("s")) {
6
- return Number.parseFloat(time) * 1000;
7
- }
8
- throw new Error("Time must be in milliseconds or seconds (10s, 10000ms)");
9
- };
@@ -1,16 +0,0 @@
1
- import { TaskStatus } from "@lit/task";
2
-
3
- export const printTaskStatus = (status: TaskStatus) => {
4
- switch (status) {
5
- case TaskStatus.INITIAL:
6
- return "INITIAL";
7
- case TaskStatus.ERROR:
8
- return "ERROR";
9
- case TaskStatus.PENDING:
10
- return "PENDING";
11
- case TaskStatus.COMPLETE:
12
- return "COMPLETE";
13
- default:
14
- return "UNKNOWN";
15
- }
16
- };
@@ -1,108 +0,0 @@
1
- import type { EFMedia } from "./EFMedia.js";
2
-
3
- interface TemporalAudioHost {
4
- startTimeMs: number;
5
- endTimeMs: number;
6
- durationMs: number;
7
- getMediaElements(): EFMedia[];
8
- waitForMediaDurations?(): Promise<void>;
9
- }
10
-
11
- export async function renderTemporalAudio(
12
- host: TemporalAudioHost,
13
- fromMs: number,
14
- toMs: number,
15
- ): Promise<AudioBuffer> {
16
- const durationMs = toMs - fromMs;
17
- const duration = durationMs / 1000;
18
- const exactSamples = 48000 * duration;
19
- const aacFrames = exactSamples / 1024;
20
- const alignedFrames = Math.round(aacFrames);
21
- const contextSize = alignedFrames * 1024;
22
-
23
- if (contextSize <= 0) {
24
- throw new Error(
25
- `Duration must be greater than 0 when rendering audio. ${contextSize}ms`,
26
- );
27
- }
28
-
29
- const audioContext = new OfflineAudioContext(2, contextSize, 48000);
30
-
31
- if (host.waitForMediaDurations) {
32
- await host.waitForMediaDurations();
33
- }
34
-
35
- const abortController = new AbortController();
36
-
37
- await Promise.all(
38
- host.getMediaElements().map(async (mediaElement) => {
39
- if (mediaElement.mute) {
40
- return;
41
- }
42
-
43
- const mediaStartsBeforeEnd = mediaElement.startTimeMs <= toMs;
44
- const mediaEndsAfterStart = mediaElement.endTimeMs >= fromMs;
45
- const mediaOverlaps = mediaStartsBeforeEnd && mediaEndsAfterStart;
46
- if (!mediaOverlaps) {
47
- return;
48
- }
49
-
50
- const mediaLocalFromMs = Math.max(0, fromMs - mediaElement.startTimeMs);
51
- const mediaLocalToMs = Math.min(
52
- mediaElement.endTimeMs - mediaElement.startTimeMs,
53
- toMs - mediaElement.startTimeMs,
54
- );
55
-
56
- if (mediaLocalFromMs >= mediaLocalToMs) {
57
- return;
58
- }
59
-
60
- const sourceInMs =
61
- mediaElement.sourceInMs || mediaElement.trimStartMs || 0;
62
- const mediaSourceFromMs = mediaLocalFromMs + sourceInMs;
63
- const mediaSourceToMs = mediaLocalToMs + sourceInMs;
64
-
65
- const audio = await mediaElement.fetchAudioSpanningTime(
66
- mediaSourceFromMs,
67
- mediaSourceToMs,
68
- abortController.signal,
69
- );
70
- if (!audio) {
71
- return;
72
- }
73
-
74
- const bufferSource = audioContext.createBufferSource();
75
- bufferSource.buffer = await audioContext.decodeAudioData(
76
- await audio.blob.arrayBuffer(),
77
- );
78
- bufferSource.connect(audioContext.destination);
79
-
80
- const ctxStartMs = Math.max(0, mediaElement.startTimeMs - fromMs);
81
-
82
- const requestedSourceFromMs = mediaSourceFromMs;
83
- const actualSourceStartMs = audio.startMs;
84
- const offsetInBufferMs = requestedSourceFromMs - actualSourceStartMs;
85
-
86
- const safeOffsetMs = Math.max(0, offsetInBufferMs);
87
-
88
- const requestedDurationMs = mediaSourceToMs - mediaSourceFromMs;
89
- const availableAudioMs = audio.endMs - audio.startMs;
90
- const actualDurationMs = Math.min(
91
- requestedDurationMs,
92
- availableAudioMs - safeOffsetMs,
93
- );
94
-
95
- if (actualDurationMs <= 0) {
96
- return;
97
- }
98
-
99
- bufferSource.start(
100
- ctxStartMs / 1000,
101
- safeOffsetMs / 1000,
102
- actualDurationMs / 1000,
103
- );
104
- }),
105
- );
106
-
107
- return audioContext.startRendering();
108
- }