@editframe/elements 0.33.0-beta → 0.34.5-beta

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 (251) hide show
  1. package/dist/EF_FRAMEGEN.js +5 -3
  2. package/dist/EF_FRAMEGEN.js.map +1 -1
  3. package/dist/_virtual/{_@oxc-project_runtime@0.94.0 → _@oxc-project_runtime@0.95.0}/helpers/decorate.js +1 -1
  4. package/dist/canvas/EFCanvas.d.ts +7 -4
  5. package/dist/canvas/EFCanvas.js +1 -1
  6. package/dist/canvas/EFCanvasItem.d.ts +4 -4
  7. package/dist/canvas/EFCanvasItem.js +1 -1
  8. package/dist/canvas/overlays/SelectionOverlay.d.ts +95 -0
  9. package/dist/canvas/overlays/SelectionOverlay.js +1 -1
  10. package/dist/canvas/selection/SelectionController.js +7 -11
  11. package/dist/canvas/selection/SelectionController.js.map +1 -1
  12. package/dist/elements/EFAudio.d.ts +25 -7
  13. package/dist/elements/EFAudio.js +31 -61
  14. package/dist/elements/EFAudio.js.map +1 -1
  15. package/dist/elements/EFCaptions.d.ts +65 -52
  16. package/dist/elements/EFCaptions.js +186 -400
  17. package/dist/elements/EFCaptions.js.map +1 -1
  18. package/dist/elements/EFImage.d.ts +34 -6
  19. package/dist/elements/EFImage.js +114 -79
  20. package/dist/elements/EFImage.js.map +1 -1
  21. package/dist/elements/EFMedia/AssetIdMediaEngine.js +17 -17
  22. package/dist/elements/EFMedia/AssetIdMediaEngine.js.map +1 -1
  23. package/dist/elements/EFMedia/AssetMediaEngine.js +41 -25
  24. package/dist/elements/EFMedia/AssetMediaEngine.js.map +1 -1
  25. package/dist/elements/EFMedia/BaseMediaEngine.js +4 -4
  26. package/dist/elements/EFMedia/BaseMediaEngine.js.map +1 -1
  27. package/dist/elements/EFMedia/BufferedSeekingInput.js +1 -1
  28. package/dist/elements/EFMedia/BufferedSeekingInput.js.map +1 -1
  29. package/dist/elements/EFMedia/JitMediaEngine.js +31 -17
  30. package/dist/elements/EFMedia/JitMediaEngine.js.map +1 -1
  31. package/dist/elements/EFMedia/shared/AudioSpanUtils.js +3 -3
  32. package/dist/elements/EFMedia/shared/AudioSpanUtils.js.map +1 -1
  33. package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js +17 -9
  34. package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js.map +1 -1
  35. package/dist/elements/EFMedia.d.ts +66 -20
  36. package/dist/elements/EFMedia.js +412 -30
  37. package/dist/elements/EFMedia.js.map +1 -1
  38. package/dist/elements/EFPanZoom.d.ts +4 -4
  39. package/dist/elements/EFPanZoom.js +1 -1
  40. package/dist/elements/EFSourceMixin.js +43 -15
  41. package/dist/elements/EFSourceMixin.js.map +1 -1
  42. package/dist/elements/EFSurface.d.ts +23 -10
  43. package/dist/elements/EFSurface.js +64 -22
  44. package/dist/elements/EFSurface.js.map +1 -1
  45. package/dist/elements/EFTemporal.d.ts +8 -2
  46. package/dist/elements/EFTemporal.js +42 -31
  47. package/dist/elements/EFTemporal.js.map +1 -1
  48. package/dist/elements/EFText.d.ts +5 -4
  49. package/dist/elements/EFText.js +11 -2
  50. package/dist/elements/EFText.js.map +1 -1
  51. package/dist/elements/EFTextSegment.d.ts +4 -4
  52. package/dist/elements/EFTextSegment.js +1 -1
  53. package/dist/elements/EFThumbnailStrip.d.ts +4 -4
  54. package/dist/elements/EFThumbnailStrip.js +1 -1
  55. package/dist/elements/EFTimegroup.d.ts +22 -8
  56. package/dist/elements/EFTimegroup.js +203 -115
  57. package/dist/elements/EFTimegroup.js.map +1 -1
  58. package/dist/elements/EFVideo.d.ts +57 -20
  59. package/dist/elements/EFVideo.js +324 -72
  60. package/dist/elements/EFVideo.js.map +1 -1
  61. package/dist/elements/EFWaveform.d.ts +33 -7
  62. package/dist/elements/EFWaveform.js +103 -59
  63. package/dist/elements/EFWaveform.js.map +1 -1
  64. package/dist/elements/renderTemporalAudio.js +14 -3
  65. package/dist/elements/renderTemporalAudio.js.map +1 -1
  66. package/dist/getRenderInfo.d.ts +2 -2
  67. package/dist/gui/ContextMixin.js +1 -1
  68. package/dist/gui/Controllable.d.ts +2 -0
  69. package/dist/gui/EFActiveRootTemporal.d.ts +4 -4
  70. package/dist/gui/EFActiveRootTemporal.js +1 -1
  71. package/dist/gui/EFConfiguration.d.ts +4 -4
  72. package/dist/gui/EFConfiguration.js +1 -1
  73. package/dist/gui/EFControls.d.ts +2 -2
  74. package/dist/gui/EFControls.js +1 -1
  75. package/dist/gui/EFDial.d.ts +4 -4
  76. package/dist/gui/EFDial.js +1 -1
  77. package/dist/gui/EFFilmstrip.d.ts +3 -2
  78. package/dist/gui/EFFilmstrip.js +1 -1
  79. package/dist/gui/EFFitScale.js +1 -1
  80. package/dist/gui/EFFocusOverlay.d.ts +4 -4
  81. package/dist/gui/EFFocusOverlay.js +1 -1
  82. package/dist/gui/EFOverlayItem.d.ts +4 -4
  83. package/dist/gui/EFOverlayItem.js +1 -1
  84. package/dist/gui/EFOverlayLayer.d.ts +4 -4
  85. package/dist/gui/EFOverlayLayer.js +1 -1
  86. package/dist/gui/EFPause.d.ts +4 -4
  87. package/dist/gui/EFPause.js +1 -1
  88. package/dist/gui/EFPlay.d.ts +4 -4
  89. package/dist/gui/EFPlay.js +1 -1
  90. package/dist/gui/EFPreview.d.ts +4 -4
  91. package/dist/gui/EFPreview.js +1 -1
  92. package/dist/gui/EFResizableBox.d.ts +4 -4
  93. package/dist/gui/EFResizableBox.js +1 -1
  94. package/dist/gui/EFScrubber.d.ts +4 -4
  95. package/dist/gui/EFScrubber.js +1 -1
  96. package/dist/gui/EFTimeDisplay.d.ts +4 -4
  97. package/dist/gui/EFTimeDisplay.js +1 -1
  98. package/dist/gui/EFTimelineRuler.d.ts +4 -4
  99. package/dist/gui/EFTimelineRuler.js +1 -1
  100. package/dist/gui/EFToggleLoop.d.ts +4 -4
  101. package/dist/gui/EFToggleLoop.js +1 -1
  102. package/dist/gui/EFTogglePlay.d.ts +4 -4
  103. package/dist/gui/EFTogglePlay.js +1 -1
  104. package/dist/gui/EFTransformHandles.d.ts +4 -4
  105. package/dist/gui/EFTransformHandles.js +1 -1
  106. package/dist/gui/EFWorkbench.d.ts +5 -4
  107. package/dist/gui/EFWorkbench.js +1 -1
  108. package/dist/gui/PlaybackController.d.ts +10 -2
  109. package/dist/gui/PlaybackController.js +52 -30
  110. package/dist/gui/PlaybackController.js.map +1 -1
  111. package/dist/gui/TWMixin.js +1 -1
  112. package/dist/gui/TWMixin.js.map +1 -1
  113. package/dist/gui/TargetOrContextMixin.js +1 -1
  114. package/dist/gui/hierarchy/EFHierarchy.d.ts +4 -4
  115. package/dist/gui/hierarchy/EFHierarchy.js +1 -1
  116. package/dist/gui/hierarchy/EFHierarchyItem.d.ts +3 -3
  117. package/dist/gui/hierarchy/EFHierarchyItem.js +1 -1
  118. package/dist/gui/timeline/EFTimeline.d.ts +6 -2
  119. package/dist/gui/timeline/EFTimeline.js +1 -1
  120. package/dist/gui/timeline/EFTimelineRow.d.ts +57 -0
  121. package/dist/gui/timeline/EFTimelineRow.js +1 -1
  122. package/dist/gui/timeline/TrimHandles.d.ts +4 -4
  123. package/dist/gui/timeline/TrimHandles.js +1 -1
  124. package/dist/gui/timeline/tracks/AudioTrack.d.ts +2 -0
  125. package/dist/gui/timeline/tracks/AudioTrack.js +1 -1
  126. package/dist/gui/timeline/tracks/CaptionsTrack.d.ts +58 -0
  127. package/dist/gui/timeline/tracks/CaptionsTrack.js +1 -1
  128. package/dist/gui/timeline/tracks/HTMLTrack.d.ts +13 -0
  129. package/dist/gui/timeline/tracks/HTMLTrack.js +1 -1
  130. package/dist/gui/timeline/tracks/ImageTrack.d.ts +14 -0
  131. package/dist/gui/timeline/tracks/ImageTrack.js +1 -1
  132. package/dist/gui/timeline/tracks/TextTrack.d.ts +26 -0
  133. package/dist/gui/timeline/tracks/TextTrack.js +1 -1
  134. package/dist/gui/timeline/tracks/TimegroupTrack.d.ts +47 -0
  135. package/dist/gui/timeline/tracks/TimegroupTrack.js +4 -12
  136. package/dist/gui/timeline/tracks/TimegroupTrack.js.map +1 -1
  137. package/dist/gui/timeline/tracks/TrackItem.d.ts +81 -0
  138. package/dist/gui/timeline/tracks/TrackItem.js +1 -1
  139. package/dist/gui/timeline/tracks/VideoTrack.d.ts +25 -0
  140. package/dist/gui/timeline/tracks/VideoTrack.js +1 -1
  141. package/dist/gui/timeline/tracks/WaveformTrack.d.ts +14 -0
  142. package/dist/gui/timeline/tracks/WaveformTrack.js +1 -1
  143. package/dist/gui/timeline/tracks/ensureTrackItemInit.d.ts +1 -0
  144. package/dist/gui/timeline/tracks/preloadTracks.d.ts +9 -0
  145. package/dist/gui/tree/EFTree.d.ts +5 -4
  146. package/dist/gui/tree/EFTree.js +1 -1
  147. package/dist/gui/tree/EFTreeItem.d.ts +4 -4
  148. package/dist/gui/tree/EFTreeItem.js +1 -1
  149. package/dist/index.d.ts +4 -1
  150. package/dist/preview/AdaptiveResolutionTracker.js +6 -14
  151. package/dist/preview/AdaptiveResolutionTracker.js.map +1 -1
  152. package/dist/preview/FrameController.d.ts +123 -0
  153. package/dist/preview/FrameController.js +216 -0
  154. package/dist/preview/FrameController.js.map +1 -0
  155. package/dist/preview/RenderContext.d.ts +1 -0
  156. package/dist/preview/RenderContext.js +193 -0
  157. package/dist/preview/RenderContext.js.map +1 -0
  158. package/dist/preview/encoding/canvasEncoder.js +166 -0
  159. package/dist/preview/encoding/canvasEncoder.js.map +1 -0
  160. package/dist/preview/encoding/mainThreadEncoder.js +39 -0
  161. package/dist/preview/encoding/mainThreadEncoder.js.map +1 -0
  162. package/dist/preview/encoding/types.d.ts +1 -0
  163. package/dist/preview/encoding/workerEncoder.js +58 -0
  164. package/dist/preview/encoding/workerEncoder.js.map +1 -0
  165. package/dist/preview/logger.js +41 -0
  166. package/dist/preview/logger.js.map +1 -0
  167. package/dist/preview/previewTypes.js +11 -10
  168. package/dist/preview/previewTypes.js.map +1 -1
  169. package/dist/preview/renderTimegroupPreview.js +259 -236
  170. package/dist/preview/renderTimegroupPreview.js.map +1 -1
  171. package/dist/preview/renderTimegroupToCanvas.d.ts +5 -0
  172. package/dist/preview/renderTimegroupToCanvas.js +99 -489
  173. package/dist/preview/renderTimegroupToCanvas.js.map +1 -1
  174. package/dist/preview/renderTimegroupToVideo.d.ts +1 -0
  175. package/dist/preview/renderTimegroupToVideo.js +80 -22
  176. package/dist/preview/renderTimegroupToVideo.js.map +1 -1
  177. package/dist/preview/renderers.js.map +1 -1
  178. package/dist/preview/rendering/inlineImages.js +56 -0
  179. package/dist/preview/rendering/inlineImages.js.map +1 -0
  180. package/dist/preview/rendering/renderToImage.d.ts +1 -0
  181. package/dist/preview/rendering/renderToImage.js +120 -0
  182. package/dist/preview/rendering/renderToImage.js.map +1 -0
  183. package/dist/preview/rendering/renderToImageForeignObject.js +135 -0
  184. package/dist/preview/rendering/renderToImageForeignObject.js.map +1 -0
  185. package/dist/preview/rendering/renderToImageNative.d.ts +1 -0
  186. package/dist/preview/rendering/renderToImageNative.js +129 -0
  187. package/dist/preview/rendering/renderToImageNative.js.map +1 -0
  188. package/dist/preview/rendering/svgSerializer.js +43 -0
  189. package/dist/preview/rendering/svgSerializer.js.map +1 -0
  190. package/dist/preview/rendering/types.d.ts +2 -0
  191. package/dist/preview/statsTrackingStrategy.js +3 -1
  192. package/dist/preview/statsTrackingStrategy.js.map +1 -1
  193. package/dist/preview/workers/WorkerPool.js +8 -57
  194. package/dist/preview/workers/WorkerPool.js.map +1 -1
  195. package/dist/render/EFRenderAPI.d.ts +35 -0
  196. package/dist/render/EFRenderAPI.js +1 -0
  197. package/dist/render/EFRenderAPI.js.map +1 -1
  198. package/dist/sandbox/PlaybackControls.d.ts +1 -0
  199. package/dist/sandbox/ScenarioRunner.d.ts +1 -0
  200. package/dist/sandbox/defineSandbox.d.ts +1 -0
  201. package/dist/sandbox/index.d.ts +3 -0
  202. package/dist/style.css +3 -0
  203. package/dist/transcoding/types/index.d.ts +6 -3
  204. package/package.json +2 -3
  205. package/test/EFVideo.framegen.browsertest.ts +8 -1
  206. package/test/profilingPlugin.ts +1 -3
  207. package/test/setup.ts +23 -1
  208. package/dist/EF_INTERACTIVE.js +0 -7
  209. package/dist/EF_INTERACTIVE.js.map +0 -1
  210. package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +0 -50
  211. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.d.ts +0 -12
  212. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +0 -104
  213. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js.map +0 -1
  214. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +0 -168
  215. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js.map +0 -1
  216. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js +0 -46
  217. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js.map +0 -1
  218. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +0 -49
  219. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js.map +0 -1
  220. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +0 -30
  221. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js.map +0 -1
  222. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +0 -49
  223. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js.map +0 -1
  224. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +0 -47
  225. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js.map +0 -1
  226. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +0 -140
  227. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js.map +0 -1
  228. package/dist/elements/EFMedia/shared/BufferUtils.d.ts +0 -13
  229. package/dist/elements/EFMedia/shared/BufferUtils.js +0 -86
  230. package/dist/elements/EFMedia/shared/BufferUtils.js.map +0 -1
  231. package/dist/elements/EFMedia/shared/MediaTaskUtils.d.ts +0 -17
  232. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js +0 -90
  233. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js.map +0 -1
  234. package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js +0 -80
  235. package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js.map +0 -1
  236. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.js +0 -49
  237. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.js.map +0 -1
  238. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js +0 -58
  239. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js.map +0 -1
  240. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js +0 -71
  241. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js.map +0 -1
  242. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.js +0 -52
  243. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.js.map +0 -1
  244. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js +0 -50
  245. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js.map +0 -1
  246. package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js +0 -109
  247. package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js.map +0 -1
  248. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.d.ts +0 -12
  249. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +0 -97
  250. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js.map +0 -1
  251. package/dist/elements/SampleBuffer.d.ts +0 -19
@@ -1,6 +1,6 @@
1
- import * as lit32 from "lit";
1
+ import * as lit28 from "lit";
2
2
  import { LitElement } from "lit";
3
- import * as lit_html31 from "lit-html";
3
+ import * as lit_html27 from "lit-html";
4
4
 
5
5
  //#region src/elements/EFPanZoom.d.ts
6
6
  interface PanZoomTransform {
@@ -9,7 +9,7 @@ interface PanZoomTransform {
9
9
  scale: number;
10
10
  }
11
11
  declare class EFPanZoom extends LitElement {
12
- static styles: lit32.CSSResult[];
12
+ static styles: lit28.CSSResult[];
13
13
  x: number;
14
14
  y: number;
15
15
  scale: number;
@@ -89,7 +89,7 @@ declare class EFPanZoom extends LitElement {
89
89
  * @param padding - Padding factor (0-1), e.g., 0.1 = 10% padding on each side. Default: 0.05
90
90
  */
91
91
  fitToContent(padding?: number): void;
92
- render(): lit_html31.TemplateResult<1>;
92
+ render(): lit_html27.TemplateResult<1>;
93
93
  }
94
94
  //#endregion
95
95
  export { EFPanZoom, PanZoomTransform };
@@ -1,4 +1,4 @@
1
- import { __decorate } from "../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js";
1
+ import { __decorate } from "../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
2
2
  import { panZoomTransformContext } from "../gui/panZoomTransformContext.js";
3
3
  import { provide } from "@lit/context";
4
4
  import { LitElement, css, html } from "lit";
@@ -1,5 +1,4 @@
1
- import { __decorate } from "../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js";
2
- import { Task } from "@lit/task";
1
+ import { __decorate } from "../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
3
2
  import { property } from "lit/decorators/property.js";
4
3
 
5
4
  //#region src/elements/EFSourceMixin.ts
@@ -8,26 +7,55 @@ function EFSourceMixin(superClass, options) {
8
7
  constructor(..._args) {
9
8
  super(..._args);
10
9
  this.src = "";
11
- this.md5SumLoader = new Task(this, {
12
- autoRun: false,
13
- args: () => [this.src],
14
- task: async ([src], { signal }) => {
15
- let normalizedSrc = src.startsWith("/") ? src.slice(1) : src;
16
- normalizedSrc = normalizedSrc.replace(/^\/+/, "");
17
- const md5Path = `/api/v1/isobmff_files/local/md5?src=${encodeURIComponent(normalizedSrc)}`;
18
- const response = await fetch(md5Path, { signal });
19
- if (!response.ok) return;
20
- return (await response.json()).md5 ?? void 0;
10
+ this.md5SumLoader = new Proxy({
11
+ run: () => this.loadMd5Sum(),
12
+ _host: this
13
+ }, { get(target, prop) {
14
+ if (prop === "value") return target._host.#md5Value;
15
+ if (prop === "taskComplete") {
16
+ const host = target._host;
17
+ return host.#md5Promise || Promise.resolve(host.#md5Value);
21
18
  }
22
- });
19
+ return target[prop];
20
+ } });
23
21
  }
24
22
  get apiHost() {
25
23
  return this.closest("ef-configuration")?.apiHost ?? this.closest("ef-workbench")?.apiHost ?? this.closest("ef-preview")?.apiHost;
26
24
  }
25
+ #md5Value = void 0;
26
+ #md5Promise = null;
27
+ #md5LastSrc = null;
27
28
  productionSrc() {
28
- if (!this.md5SumLoader.value) throw new Error(`MD5 sum not available for ${this}. Cannot generate production URL`);
29
+ if (!this.#md5Value) throw new Error(`MD5 sum not available for ${this}. Cannot generate production URL`);
29
30
  if (!this.apiHost) throw new Error(`apiHost not available for ${this}. Cannot generate production URL`);
30
- return `${this.apiHost}/api/v1/${options.assetType}/${this.md5SumLoader.value}`;
31
+ return `${this.apiHost}/api/v1/${options.assetType}/${this.#md5Value}`;
32
+ }
33
+ /**
34
+ * Load MD5 sum for the current source
35
+ */
36
+ async loadMd5Sum(signal) {
37
+ if (this.#md5LastSrc === this.src && this.#md5Value) return this.#md5Value;
38
+ if (this.#md5Promise && this.#md5LastSrc === this.src) return this.#md5Promise;
39
+ this.#md5LastSrc = this.src;
40
+ this.#md5Promise = this.#doLoadMd5(this.src, signal);
41
+ try {
42
+ this.#md5Value = await this.#md5Promise;
43
+ return this.#md5Value;
44
+ } catch (error) {
45
+ if (error instanceof DOMException && error.name === "AbortError") throw error;
46
+ console.error("EFSourceMixin md5Sum error", error);
47
+ return;
48
+ } finally {
49
+ this.#md5Promise = null;
50
+ }
51
+ }
52
+ async #doLoadMd5(src, signal) {
53
+ let normalizedSrc = src.startsWith("/") ? src.slice(1) : src;
54
+ normalizedSrc = normalizedSrc.replace(/^\/+/, "");
55
+ const md5Path = `/api/v1/isobmff_files/local/md5?src=${encodeURIComponent(normalizedSrc)}`;
56
+ const response = await fetch(md5Path, { signal });
57
+ if (!response.ok) return;
58
+ return (await response.json()).md5 ?? void 0;
31
59
  }
32
60
  }
33
61
  __decorate([property({ type: String })], EFSourceElement.prototype, "src", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"EFSourceMixin.js","names":[],"sources":["../../src/elements/EFSourceMixin.ts"],"sourcesContent":["import { Task } from \"@lit/task\";\nimport type { LitElement } from \"lit\";\nimport { property } from \"lit/decorators/property.js\";\n\nexport declare class EFSourceMixinInterface {\n apiHost?: string;\n productionSrc(): string;\n src: string;\n}\n\ninterface EFSourceMixinOptions {\n assetType: string;\n}\ntype Constructor<T = {}> = new (...args: any[]) => T;\nexport function EFSourceMixin<T extends Constructor<LitElement>>(\n superClass: T,\n options: EFSourceMixinOptions,\n) {\n class EFSourceElement extends superClass {\n get apiHost() {\n const apiHost =\n this.closest(\"ef-configuration\")?.apiHost ??\n this.closest(\"ef-workbench\")?.apiHost ??\n this.closest(\"ef-preview\")?.apiHost;\n\n // Return undefined instead of defaulting to external URL\n // This allows components to use current origin when apiHost is not set\n return apiHost;\n }\n\n @property({ type: String })\n src = \"\";\n\n productionSrc() {\n if (!this.md5SumLoader.value) {\n throw new Error(\n `MD5 sum not available for ${this}. Cannot generate production URL`,\n );\n }\n\n if (!this.apiHost) {\n throw new Error(\n `apiHost not available for ${this}. Cannot generate production URL`,\n );\n }\n\n return `${this.apiHost}/api/v1/${options.assetType}/${this.md5SumLoader.value}`;\n }\n\n md5SumLoader = new Task(this, {\n autoRun: false,\n args: () => [this.src] as const,\n task: async ([src], { signal }) => {\n // Normalize the path: remove leading slash and any double slashes\n let normalizedSrc = src.startsWith(\"/\")\n ? src.slice(1)\n : src;\n normalizedSrc = normalizedSrc.replace(/^\\/+/, \"\");\n // Use production API format for local files\n const md5Path = `/api/v1/isobmff_files/local/md5?src=${encodeURIComponent(normalizedSrc)}`;\n const response = await fetch(md5Path, { signal });\n if (!response.ok) {\n return undefined;\n }\n const data = await response.json();\n return data.md5 ?? undefined;\n },\n });\n }\n\n return EFSourceElement as Constructor<EFSourceMixinInterface> & T;\n}\n"],"mappings":";;;;;AAcA,SAAgB,cACd,YACA,SACA;CACA,MAAM,wBAAwB,WAAW;;;cAajC;uBAkBS,IAAI,KAAK,MAAM;IAC5B,SAAS;IACT,YAAY,CAAC,KAAK,IAAI;IACtB,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa;KAEjC,IAAI,gBAAgB,IAAI,WAAW,IAAI,GACnC,IAAI,MAAM,EAAE,GACZ;AACJ,qBAAgB,cAAc,QAAQ,QAAQ,GAAG;KAEjD,MAAM,UAAU,uCAAuC,mBAAmB,cAAc;KACxF,MAAM,WAAW,MAAM,MAAM,SAAS,EAAE,QAAQ,CAAC;AACjD,SAAI,CAAC,SAAS,GACZ;AAGF,aADa,MAAM,SAAS,MAAM,EACtB,OAAO;;IAEtB,CAAC;;EAhDF,IAAI,UAAU;AAQZ,UANE,KAAK,QAAQ,mBAAmB,EAAE,WAClC,KAAK,QAAQ,eAAe,EAAE,WAC9B,KAAK,QAAQ,aAAa,EAAE;;EAUhC,gBAAgB;AACd,OAAI,CAAC,KAAK,aAAa,MACrB,OAAM,IAAI,MACR,6BAA6B,KAAK,kCACnC;AAGH,OAAI,CAAC,KAAK,QACR,OAAM,IAAI,MACR,6BAA6B,KAAK,kCACnC;AAGH,UAAO,GAAG,KAAK,QAAQ,UAAU,QAAQ,UAAU,GAAG,KAAK,aAAa;;;aAhBzE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAwC7B,QAAO"}
1
+ {"version":3,"file":"EFSourceMixin.js","names":["#md5Value","#md5Promise","#md5LastSrc","#doLoadMd5"],"sources":["../../src/elements/EFSourceMixin.ts"],"sourcesContent":["import type { LitElement } from \"lit\";\nimport { property } from \"lit/decorators/property.js\";\n\nexport declare class EFSourceMixinInterface {\n apiHost?: string;\n productionSrc(): string;\n src: string;\n}\n\ninterface EFSourceMixinOptions {\n assetType: string;\n}\ntype Constructor<T = {}> = new (...args: any[]) => T;\nexport function EFSourceMixin<T extends Constructor<LitElement>>(\n superClass: T,\n options: EFSourceMixinOptions,\n) {\n class EFSourceElement extends superClass {\n get apiHost() {\n const apiHost =\n this.closest(\"ef-configuration\")?.apiHost ??\n this.closest(\"ef-workbench\")?.apiHost ??\n this.closest(\"ef-preview\")?.apiHost;\n\n // Return undefined instead of defaulting to external URL\n // This allows components to use current origin when apiHost is not set\n return apiHost;\n }\n\n @property({ type: String })\n src = \"\";\n\n #md5Value: string | undefined = undefined;\n #md5Promise: Promise<string | undefined> | null = null;\n #md5LastSrc: string | null = null;\n\n productionSrc() {\n if (!this.#md5Value) {\n throw new Error(\n `MD5 sum not available for ${this}. Cannot generate production URL`,\n );\n }\n\n if (!this.apiHost) {\n throw new Error(\n `apiHost not available for ${this}. Cannot generate production URL`,\n );\n }\n\n return `${this.apiHost}/api/v1/${options.assetType}/${this.#md5Value}`;\n }\n\n /**\n * Load MD5 sum for the current source\n */\n async loadMd5Sum(signal?: AbortSignal): Promise<string | undefined> {\n if (this.#md5LastSrc === this.src && this.#md5Value) {\n return this.#md5Value;\n }\n\n if (this.#md5Promise && this.#md5LastSrc === this.src) {\n return this.#md5Promise;\n }\n\n this.#md5LastSrc = this.src;\n this.#md5Promise = this.#doLoadMd5(this.src, signal);\n\n try {\n this.#md5Value = await this.#md5Promise;\n return this.#md5Value;\n } catch (error) {\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw error;\n }\n console.error(\"EFSourceMixin md5Sum error\", error);\n return undefined;\n } finally {\n this.#md5Promise = null;\n }\n }\n\n async #doLoadMd5(src: string, signal?: AbortSignal): Promise<string | undefined> {\n // Normalize the path: remove leading slash and any double slashes\n let normalizedSrc = src.startsWith(\"/\")\n ? src.slice(1)\n : src;\n normalizedSrc = normalizedSrc.replace(/^\\/+/, \"\");\n // Use production API format for local files\n const md5Path = `/api/v1/isobmff_files/local/md5?src=${encodeURIComponent(normalizedSrc)}`;\n const response = await fetch(md5Path, { signal });\n if (!response.ok) {\n return undefined;\n }\n const data = await response.json();\n return data.md5 ?? undefined;\n }\n\n /**\n * Compatibility wrapper for code expecting md5SumLoader.value\n */\n md5SumLoader = new Proxy({\n run: () => this.loadMd5Sum(),\n _host: this,\n } as {\n run: () => Promise<string | undefined>;\n value: string | undefined;\n taskComplete: Promise<string | undefined>;\n _host: typeof this;\n }, {\n get(target, prop) {\n if (prop === 'value') {\n return (target._host as any).#md5Value;\n }\n if (prop === 'taskComplete') {\n const host = target._host as any;\n return host.#md5Promise || Promise.resolve(host.#md5Value);\n }\n return (target as any)[prop];\n },\n });\n }\n\n return EFSourceElement as Constructor<EFSourceMixinInterface> & T;\n}\n"],"mappings":";;;;AAaA,SAAgB,cACd,YACA,SACA;CACA,MAAM,wBAAwB,WAAW;;;cAajC;uBAsES,IAAI,MAAM;IACvB,WAAW,KAAK,YAAY;IAC5B,OAAO;IACR,EAKE,EACD,IAAI,QAAQ,MAAM;AAChB,QAAI,SAAS,QACX,QAAQ,OAAO,OAAcA;AAE/B,QAAI,SAAS,gBAAgB;KAC3B,MAAM,OAAO,OAAO;AACpB,YAAO,MAAKC,cAAe,QAAQ,QAAQ,MAAKD,SAAU;;AAE5D,WAAQ,OAAe;MAE1B,CAAC;;EArGF,IAAI,UAAU;AAQZ,UANE,KAAK,QAAQ,mBAAmB,EAAE,WAClC,KAAK,QAAQ,eAAe,EAAE,WAC9B,KAAK,QAAQ,aAAa,EAAE;;EAUhC,YAAgC;EAChC,cAAkD;EAClD,cAA6B;EAE7B,gBAAgB;AACd,OAAI,CAAC,MAAKA,SACR,OAAM,IAAI,MACR,6BAA6B,KAAK,kCACnC;AAGH,OAAI,CAAC,KAAK,QACR,OAAM,IAAI,MACR,6BAA6B,KAAK,kCACnC;AAGH,UAAO,GAAG,KAAK,QAAQ,UAAU,QAAQ,UAAU,GAAG,MAAKA;;;;;EAM7D,MAAM,WAAW,QAAmD;AAClE,OAAI,MAAKE,eAAgB,KAAK,OAAO,MAAKF,SACxC,QAAO,MAAKA;AAGd,OAAI,MAAKC,cAAe,MAAKC,eAAgB,KAAK,IAChD,QAAO,MAAKD;AAGd,SAAKC,aAAc,KAAK;AACxB,SAAKD,aAAc,MAAKE,UAAW,KAAK,KAAK,OAAO;AAEpD,OAAI;AACF,UAAKH,WAAY,MAAM,MAAKC;AAC5B,WAAO,MAAKD;YACL,OAAO;AACd,QAAI,iBAAiB,gBAAgB,MAAM,SAAS,aAClD,OAAM;AAER,YAAQ,MAAM,8BAA8B,MAAM;AAClD;aACQ;AACR,UAAKC,aAAc;;;EAIvB,OAAME,UAAW,KAAa,QAAmD;GAE/E,IAAI,gBAAgB,IAAI,WAAW,IAAI,GACnC,IAAI,MAAM,EAAE,GACZ;AACJ,mBAAgB,cAAc,QAAQ,QAAQ,GAAG;GAEjD,MAAM,UAAU,uCAAuC,mBAAmB,cAAc;GACxF,MAAM,WAAW,MAAM,MAAM,SAAS,EAAE,QAAQ,CAAC;AACjD,OAAI,CAAC,SAAS,GACZ;AAGF,WADa,MAAM,SAAS,MAAM,EACtB,OAAO;;;aAjEpB,SAAS,EAAE,MAAM,QAAQ,CAAC;AA6F7B,QAAO"}
@@ -1,29 +1,42 @@
1
+ import { FrameRenderable, FrameState } from "../preview/FrameController.js";
1
2
  import { ContextMixinInterface } from "../gui/ContextMixin.js";
2
- import { Task } from "@lit/task";
3
- import * as lit30 from "lit";
3
+ import * as lit26 from "lit";
4
4
  import { LitElement } from "lit";
5
- import * as lit_html29 from "lit-html";
5
+ import * as lit_html25 from "lit-html";
6
6
  import * as lit_html_directives_ref3 from "lit-html/directives/ref";
7
7
 
8
8
  //#region src/elements/EFSurface.d.ts
9
- declare class EFSurface extends LitElement {
9
+ declare class EFSurface extends LitElement implements FrameRenderable {
10
10
  #private;
11
- static styles: lit30.CSSResult[];
11
+ static styles: lit26.CSSResult[];
12
12
  canvasRef: lit_html_directives_ref3.Ref<HTMLCanvasElement>;
13
13
  targetElement: ContextMixinInterface | null;
14
14
  target: string;
15
- render(): lit_html29.TemplateResult<1>;
15
+ render(): lit_html25.TemplateResult<1>;
16
16
  get rootTimegroup(): any;
17
17
  get currentTimeMs(): number;
18
18
  get durationMs(): number;
19
19
  get startTimeMs(): number;
20
20
  get endTimeMs(): number;
21
+ frameTask: {
22
+ run(): void | Promise<void>;
23
+ taskComplete: Promise<void>;
24
+ };
21
25
  /**
22
- * Minimal integration with EFTimegroup's frame scheduling:
23
- * - Waits for the target video element's frameTask to complete (ensuring it painted)
24
- * - Copies the target's canvas into this element's canvas
26
+ * Query readiness state for a given time.
27
+ * @implements FrameRenderable
25
28
  */
26
- frameTask: Task<readonly [ContextMixinInterface | null], void>;
29
+ getFrameState(_timeMs: number): FrameState;
30
+ /**
31
+ * Async preparation - waits for target element's frameTask.
32
+ * @implements FrameRenderable
33
+ */
34
+ prepareFrame(_timeMs: number, signal: AbortSignal): Promise<void>;
35
+ /**
36
+ * Synchronous render - copies canvas from target element.
37
+ * @implements FrameRenderable
38
+ */
39
+ renderFrame(_timeMs: number): void;
27
40
  protected updated(): void;
28
41
  private getSourceCanvas;
29
42
  private copyFromTarget;
@@ -1,6 +1,5 @@
1
- import { __decorate } from "../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js";
1
+ import { __decorate } from "../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
2
2
  import { TargetController } from "./TargetController.js";
3
- import { Task } from "@lit/task";
4
3
  import { LitElement, css, html } from "lit";
5
4
  import { customElement, property, state } from "lit/decorators.js";
6
5
  import { createRef, ref } from "lit/directives/ref.js";
@@ -12,26 +11,28 @@ let EFSurface = class EFSurface$1 extends LitElement {
12
11
  this.canvasRef = createRef();
13
12
  this.targetElement = null;
14
13
  this.target = "";
15
- this.frameTask = new Task(this, {
16
- autoRun: false,
17
- args: () => [this.targetElement],
18
- task: async ([target], { signal }) => {
19
- signal?.throwIfAborted();
20
- if (!target) return;
21
- try {
22
- const maybeTask = target.frameTask;
23
- if (maybeTask && typeof maybeTask.run === "function") {
24
- maybeTask.run();
25
- await maybeTask.taskComplete;
26
- signal?.throwIfAborted();
27
- }
28
- } catch (error) {
29
- if (error instanceof DOMException && error.name === "AbortError") throw error;
30
- }
31
- signal?.throwIfAborted();
32
- this.copyFromTarget(target);
33
- }
34
- });
14
+ this.frameTask = (() => {
15
+ const self = this;
16
+ const taskObj = {
17
+ run: () => {
18
+ const abortController = new AbortController();
19
+ const timeMs = self.currentTimeMs;
20
+ self.#frameTaskPromise = (async () => {
21
+ try {
22
+ await self.prepareFrame(timeMs, abortController.signal);
23
+ self.renderFrame(timeMs);
24
+ } catch (error) {
25
+ if (error instanceof DOMException && error.name === "AbortError") return;
26
+ throw error;
27
+ }
28
+ })();
29
+ taskObj.taskComplete = self.#frameTaskPromise;
30
+ return self.#frameTaskPromise;
31
+ },
32
+ taskComplete: Promise.resolve()
33
+ };
34
+ return taskObj;
35
+ })();
35
36
  }
36
37
  static {
37
38
  this.styles = [css`
@@ -70,6 +71,47 @@ let EFSurface = class EFSurface$1 extends LitElement {
70
71
  get endTimeMs() {
71
72
  return this.startTimeMs + this.durationMs;
72
73
  }
74
+ /**
75
+ * @deprecated Use FrameRenderable methods (prepareFrame, renderFrame) via FrameController instead.
76
+ * This is a compatibility wrapper that delegates to the new system.
77
+ */
78
+ #frameTaskPromise = Promise.resolve();
79
+ /**
80
+ * Query readiness state for a given time.
81
+ * @implements FrameRenderable
82
+ */
83
+ getFrameState(_timeMs) {
84
+ return {
85
+ needsPreparation: false,
86
+ isReady: !!this.targetElement,
87
+ priority: 10
88
+ };
89
+ }
90
+ /**
91
+ * Async preparation - waits for target element's frameTask.
92
+ * @implements FrameRenderable
93
+ */
94
+ async prepareFrame(_timeMs, signal) {
95
+ if (!this.targetElement) return;
96
+ const maybeTask = this.targetElement.frameTask;
97
+ if (maybeTask && typeof maybeTask.run === "function") try {
98
+ maybeTask.run().catch(() => {});
99
+ await maybeTask.taskComplete;
100
+ } catch (error) {
101
+ if (error instanceof DOMException && error.name === "AbortError") {
102
+ signal.throwIfAborted();
103
+ return;
104
+ }
105
+ }
106
+ signal.throwIfAborted();
107
+ }
108
+ /**
109
+ * Synchronous render - copies canvas from target element.
110
+ * @implements FrameRenderable
111
+ */
112
+ renderFrame(_timeMs) {
113
+ if (this.targetElement) this.copyFromTarget(this.targetElement);
114
+ }
73
115
  updated() {
74
116
  if (this.targetElement) this.copyFromTarget(this.targetElement);
75
117
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EFSurface.js","names":["EFSurface","target: any","root: any"],"sources":["../../src/elements/EFSurface.ts"],"sourcesContent":["import { Task } from \"@lit/task\";\nimport { css, html, LitElement } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { createRef, ref } from \"lit/directives/ref.js\";\nimport type { ContextMixinInterface } from \"../gui/ContextMixin.ts\";\nimport { TargetController } from \"./TargetController.ts\";\n\n@customElement(\"ef-surface\")\nexport class EFSurface extends LitElement {\n static styles = [\n css`\n :host {\n display: block;\n position: relative;\n }\n canvas {\n all: inherit;\n width: 100%;\n height: 100%;\n display: block;\n }\n `,\n ];\n\n canvasRef = createRef<HTMLCanvasElement>();\n\n // @ts-expect-error controller is intentionally not referenced directly\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: Used for side effects\n #targetController: TargetController = new TargetController(this);\n\n @state()\n targetElement: ContextMixinInterface | null = null;\n\n @property({ type: String })\n target = \"\";\n\n render() {\n return html`<canvas ${ref(this.canvasRef)}></canvas>`;\n }\n\n // Provide minimal temporal-like properties so EFTimegroup can schedule us\n get rootTimegroup(): any {\n // Prefer the target element's root timegroup if available\n const target: any = this.targetElement;\n if (target && \"rootTimegroup\" in target) {\n return target.rootTimegroup;\n }\n // Fallback: nearest containing timegroup if any\n let root: any = this.closest(\"ef-timegroup\");\n while (root?.parentTimegroup) {\n root = root.parentTimegroup;\n }\n return root;\n }\n\n get currentTimeMs(): number {\n return this.rootTimegroup?.currentTimeMs ?? 0;\n }\n\n get durationMs(): number {\n return this.rootTimegroup?.durationMs ?? 0;\n }\n\n get startTimeMs(): number {\n return this.rootTimegroup?.startTimeMs ?? 0;\n }\n\n get endTimeMs(): number {\n return this.startTimeMs + this.durationMs;\n }\n\n /**\n * Minimal integration with EFTimegroup's frame scheduling:\n * - Waits for the target video element's frameTask to complete (ensuring it painted)\n * - Copies the target's canvas into this element's canvas\n */\n frameTask = new Task(this, {\n autoRun: false,\n args: () => [this.targetElement] as const,\n task: async ([target], { signal }) => {\n // Check abort before starting\n signal?.throwIfAborted();\n \n if (!target) return;\n\n // Ensure the target has painted its frame for this tick\n try {\n const maybeTask = (target as any).frameTask;\n if (maybeTask && typeof maybeTask.run === \"function\") {\n // Run (idempotent) and then wait for completion\n maybeTask.run();\n await maybeTask.taskComplete;\n // Check abort after async operation\n signal?.throwIfAborted();\n }\n } catch (error) {\n // Re-throw AbortError to propagate cancellation\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw error;\n }\n // Best-effort; continue to attempt copy for other errors\n }\n\n // Check abort before copy operation\n signal?.throwIfAborted();\n \n this.copyFromTarget(target);\n },\n });\n\n protected updated(): void {\n if (this.targetElement) {\n this.copyFromTarget(this.targetElement);\n }\n }\n\n // Target resolution is handled by TargetController. No implicit discovery.\n\n private getSourceCanvas(from: Element): HTMLCanvasElement | null {\n const anyEl = from as any;\n if (\"canvasElement\" in anyEl) {\n return anyEl.canvasElement ?? null;\n }\n const sr = (from as HTMLElement).shadowRoot;\n if (sr) {\n const c = sr.querySelector(\"canvas\");\n return (c as HTMLCanvasElement) ?? null;\n }\n return null;\n }\n\n private copyFromTarget(target: Element) {\n const dst = this.canvasRef.value;\n const src = this.getSourceCanvas(target);\n if (!dst || !src) return;\n if (!src.width || !src.height) return;\n\n // Match source pixel size for a faithful mirror; layout scaling is handled by CSS\n if (dst.width !== src.width || dst.height !== src.height) {\n dst.width = src.width;\n dst.height = src.height;\n }\n\n const ctx = dst.getContext(\"2d\");\n if (!ctx) return;\n ctx.drawImage(src, 0, 0, dst.width, dst.height);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-surface\": EFSurface;\n }\n}\n"],"mappings":";;;;;;;;AAQO,sBAAMA,oBAAkB,WAAW;;;mBAgB5B,WAA8B;uBAOI;gBAGrC;mBA0CG,IAAI,KAAK,MAAM;GACzB,SAAS;GACT,YAAY,CAAC,KAAK,cAAc;GAChC,MAAM,OAAO,CAAC,SAAS,EAAE,aAAa;AAEpC,YAAQ,gBAAgB;AAExB,QAAI,CAAC,OAAQ;AAGb,QAAI;KACF,MAAM,YAAa,OAAe;AAClC,SAAI,aAAa,OAAO,UAAU,QAAQ,YAAY;AAEpD,gBAAU,KAAK;AACf,YAAM,UAAU;AAEhB,cAAQ,gBAAgB;;aAEnB,OAAO;AAEd,SAAI,iBAAiB,gBAAgB,MAAM,SAAS,aAClD,OAAM;;AAMV,YAAQ,gBAAgB;AAExB,SAAK,eAAe,OAAO;;GAE9B,CAAC;;;gBAnGc,CACd,GAAG;;;;;;;;;;;MAYJ;;CAMD,oBAAsC,IAAI,iBAAiB,KAAK;CAQhE,SAAS;AACP,SAAO,IAAI,WAAW,IAAI,KAAK,UAAU,CAAC;;CAI5C,IAAI,gBAAqB;EAEvB,MAAMC,SAAc,KAAK;AACzB,MAAI,UAAU,mBAAmB,OAC/B,QAAO,OAAO;EAGhB,IAAIC,OAAY,KAAK,QAAQ,eAAe;AAC5C,SAAO,MAAM,gBACX,QAAO,KAAK;AAEd,SAAO;;CAGT,IAAI,gBAAwB;AAC1B,SAAO,KAAK,eAAe,iBAAiB;;CAG9C,IAAI,aAAqB;AACvB,SAAO,KAAK,eAAe,cAAc;;CAG3C,IAAI,cAAsB;AACxB,SAAO,KAAK,eAAe,eAAe;;CAG5C,IAAI,YAAoB;AACtB,SAAO,KAAK,cAAc,KAAK;;CA0CjC,AAAU,UAAgB;AACxB,MAAI,KAAK,cACP,MAAK,eAAe,KAAK,cAAc;;CAM3C,AAAQ,gBAAgB,MAAyC;EAC/D,MAAM,QAAQ;AACd,MAAI,mBAAmB,MACrB,QAAO,MAAM,iBAAiB;EAEhC,MAAM,KAAM,KAAqB;AACjC,MAAI,GAEF,QADU,GAAG,cAAc,SAAS,IACD;AAErC,SAAO;;CAGT,AAAQ,eAAe,QAAiB;EACtC,MAAM,MAAM,KAAK,UAAU;EAC3B,MAAM,MAAM,KAAK,gBAAgB,OAAO;AACxC,MAAI,CAAC,OAAO,CAAC,IAAK;AAClB,MAAI,CAAC,IAAI,SAAS,CAAC,IAAI,OAAQ;AAG/B,MAAI,IAAI,UAAU,IAAI,SAAS,IAAI,WAAW,IAAI,QAAQ;AACxD,OAAI,QAAQ,IAAI;AAChB,OAAI,SAAS,IAAI;;EAGnB,MAAM,MAAM,IAAI,WAAW,KAAK;AAChC,MAAI,CAAC,IAAK;AACV,MAAI,UAAU,KAAK,GAAG,GAAG,IAAI,OAAO,IAAI,OAAO;;;YAnHhD,OAAO;YAGP,SAAS,EAAE,MAAM,QAAQ,CAAC;wBA1B5B,cAAc,aAAa"}
1
+ {"version":3,"file":"EFSurface.js","names":["EFSurface","taskObj: { run(): void | Promise<void>; taskComplete: Promise<void> }","#frameTaskPromise","target: any","root: any"],"sources":["../../src/elements/EFSurface.ts"],"sourcesContent":["import { css, html, LitElement } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { createRef, ref } from \"lit/directives/ref.js\";\nimport type { ContextMixinInterface } from \"../gui/ContextMixin.ts\";\nimport type { FrameRenderable, FrameState } from \"../preview/FrameController.js\";\nimport { TargetController } from \"./TargetController.ts\";\n\n@customElement(\"ef-surface\")\nexport class EFSurface extends LitElement implements FrameRenderable {\n static styles = [\n css`\n :host {\n display: block;\n position: relative;\n }\n canvas {\n all: inherit;\n width: 100%;\n height: 100%;\n display: block;\n }\n `,\n ];\n\n canvasRef = createRef<HTMLCanvasElement>();\n\n // @ts-expect-error controller is intentionally not referenced directly\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: Used for side effects\n #targetController: TargetController = new TargetController(this);\n\n @state()\n targetElement: ContextMixinInterface | null = null;\n\n @property({ type: String })\n target = \"\";\n\n render() {\n return html`<canvas ${ref(this.canvasRef)}></canvas>`;\n }\n\n // Provide minimal temporal-like properties so EFTimegroup can schedule us\n get rootTimegroup(): any {\n // Prefer the target element's root timegroup if available\n const target: any = this.targetElement;\n if (target && \"rootTimegroup\" in target) {\n return target.rootTimegroup;\n }\n // Fallback: nearest containing timegroup if any\n let root: any = this.closest(\"ef-timegroup\");\n while (root?.parentTimegroup) {\n root = root.parentTimegroup;\n }\n return root;\n }\n\n get currentTimeMs(): number {\n return this.rootTimegroup?.currentTimeMs ?? 0;\n }\n\n get durationMs(): number {\n return this.rootTimegroup?.durationMs ?? 0;\n }\n\n get startTimeMs(): number {\n return this.rootTimegroup?.startTimeMs ?? 0;\n }\n\n get endTimeMs(): number {\n return this.startTimeMs + this.durationMs;\n }\n\n /**\n * @deprecated Use FrameRenderable methods (prepareFrame, renderFrame) via FrameController instead.\n * This is a compatibility wrapper that delegates to the new system.\n */\n #frameTaskPromise: Promise<void> = Promise.resolve();\n \n frameTask = (() => {\n const self = this;\n const taskObj: { run(): void | Promise<void>; taskComplete: Promise<void> } = {\n run: () => {\n const abortController = new AbortController();\n const timeMs = self.currentTimeMs;\n self.#frameTaskPromise = (async () => {\n try {\n await self.prepareFrame(timeMs, abortController.signal);\n self.renderFrame(timeMs);\n } catch (error) {\n if (error instanceof DOMException && error.name === \"AbortError\") {\n return;\n }\n throw error;\n }\n })();\n taskObj.taskComplete = self.#frameTaskPromise;\n return self.#frameTaskPromise;\n },\n taskComplete: Promise.resolve(),\n };\n return taskObj;\n })();\n\n // ============================================================================\n // FrameRenderable Implementation\n // Centralized frame control - replaces distributed Lit Task system\n // ============================================================================\n\n /**\n * Query readiness state for a given time.\n * @implements FrameRenderable\n */\n getFrameState(_timeMs: number): FrameState {\n // Surface is ready when target element exists\n const hasTarget = !!this.targetElement;\n\n return {\n needsPreparation: false, // Surface just copies, no async prep needed\n isReady: hasTarget,\n priority: 10, // Surface renders last (depends on other elements)\n };\n }\n\n /**\n * Async preparation - waits for target element's frameTask.\n * @implements FrameRenderable\n */\n async prepareFrame(_timeMs: number, signal: AbortSignal): Promise<void> {\n if (!this.targetElement) return;\n\n // Wait for target's frame to be ready\n const maybeTask = (this.targetElement as any).frameTask;\n if (maybeTask && typeof maybeTask.run === \"function\") {\n try {\n maybeTask.run().catch(() => {});\n await maybeTask.taskComplete;\n } catch (error) {\n if (error instanceof DOMException && error.name === \"AbortError\") {\n signal.throwIfAborted();\n return;\n }\n // Best-effort; continue to copy for other errors\n }\n }\n signal.throwIfAborted();\n }\n\n /**\n * Synchronous render - copies canvas from target element.\n * @implements FrameRenderable\n */\n renderFrame(_timeMs: number): void {\n if (this.targetElement) {\n this.copyFromTarget(this.targetElement);\n }\n }\n\n // ============================================================================\n // End FrameRenderable Implementation\n // ============================================================================\n\n protected updated(): void {\n if (this.targetElement) {\n this.copyFromTarget(this.targetElement);\n }\n }\n\n // Target resolution is handled by TargetController. No implicit discovery.\n\n private getSourceCanvas(from: Element): HTMLCanvasElement | null {\n const anyEl = from as any;\n if (\"canvasElement\" in anyEl) {\n return anyEl.canvasElement ?? null;\n }\n const sr = (from as HTMLElement).shadowRoot;\n if (sr) {\n const c = sr.querySelector(\"canvas\");\n return (c as HTMLCanvasElement) ?? null;\n }\n return null;\n }\n\n private copyFromTarget(target: Element) {\n const dst = this.canvasRef.value;\n const src = this.getSourceCanvas(target);\n if (!dst || !src) return;\n if (!src.width || !src.height) return;\n\n // Match source pixel size for a faithful mirror; layout scaling is handled by CSS\n if (dst.width !== src.width || dst.height !== src.height) {\n dst.width = src.width;\n dst.height = src.height;\n }\n\n const ctx = dst.getContext(\"2d\");\n if (!ctx) return;\n ctx.drawImage(src, 0, 0, dst.width, dst.height);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-surface\": EFSurface;\n }\n}\n"],"mappings":";;;;;;;AAQO,sBAAMA,oBAAkB,WAAsC;;;mBAgBvD,WAA8B;uBAOI;gBAGrC;0BA2CU;GACjB,MAAM,OAAO;GACb,MAAMC,UAAwE;IAC5E,WAAW;KACT,MAAM,kBAAkB,IAAI,iBAAiB;KAC7C,MAAM,SAAS,KAAK;AACpB,WAAKC,oBAAqB,YAAY;AACpC,UAAI;AACF,aAAM,KAAK,aAAa,QAAQ,gBAAgB,OAAO;AACvD,YAAK,YAAY,OAAO;eACjB,OAAO;AACd,WAAI,iBAAiB,gBAAgB,MAAM,SAAS,aAClD;AAEF,aAAM;;SAEN;AACJ,aAAQ,eAAe,MAAKA;AAC5B,YAAO,MAAKA;;IAEd,cAAc,QAAQ,SAAS;IAChC;AACD,UAAO;MACL;;;gBA3FY,CACd,GAAG;;;;;;;;;;;MAYJ;;CAMD,oBAAsC,IAAI,iBAAiB,KAAK;CAQhE,SAAS;AACP,SAAO,IAAI,WAAW,IAAI,KAAK,UAAU,CAAC;;CAI5C,IAAI,gBAAqB;EAEvB,MAAMC,SAAc,KAAK;AACzB,MAAI,UAAU,mBAAmB,OAC/B,QAAO,OAAO;EAGhB,IAAIC,OAAY,KAAK,QAAQ,eAAe;AAC5C,SAAO,MAAM,gBACX,QAAO,KAAK;AAEd,SAAO;;CAGT,IAAI,gBAAwB;AAC1B,SAAO,KAAK,eAAe,iBAAiB;;CAG9C,IAAI,aAAqB;AACvB,SAAO,KAAK,eAAe,cAAc;;CAG3C,IAAI,cAAsB;AACxB,SAAO,KAAK,eAAe,eAAe;;CAG5C,IAAI,YAAoB;AACtB,SAAO,KAAK,cAAc,KAAK;;;;;;CAOjC,oBAAmC,QAAQ,SAAS;;;;;CAoCpD,cAAc,SAA6B;AAIzC,SAAO;GACL,kBAAkB;GAClB,SAJgB,CAAC,CAAC,KAAK;GAKvB,UAAU;GACX;;;;;;CAOH,MAAM,aAAa,SAAiB,QAAoC;AACtE,MAAI,CAAC,KAAK,cAAe;EAGzB,MAAM,YAAa,KAAK,cAAsB;AAC9C,MAAI,aAAa,OAAO,UAAU,QAAQ,WACxC,KAAI;AACF,aAAU,KAAK,CAAC,YAAY,GAAG;AAC/B,SAAM,UAAU;WACT,OAAO;AACd,OAAI,iBAAiB,gBAAgB,MAAM,SAAS,cAAc;AAChE,WAAO,gBAAgB;AACvB;;;AAKN,SAAO,gBAAgB;;;;;;CAOzB,YAAY,SAAuB;AACjC,MAAI,KAAK,cACP,MAAK,eAAe,KAAK,cAAc;;CAQ3C,AAAU,UAAgB;AACxB,MAAI,KAAK,cACP,MAAK,eAAe,KAAK,cAAc;;CAM3C,AAAQ,gBAAgB,MAAyC;EAC/D,MAAM,QAAQ;AACd,MAAI,mBAAmB,MACrB,QAAO,MAAM,iBAAiB;EAEhC,MAAM,KAAM,KAAqB;AACjC,MAAI,GAEF,QADU,GAAG,cAAc,SAAS,IACD;AAErC,SAAO;;CAGT,AAAQ,eAAe,QAAiB;EACtC,MAAM,MAAM,KAAK,UAAU;EAC3B,MAAM,MAAM,KAAK,gBAAgB,OAAO;AACxC,MAAI,CAAC,OAAO,CAAC,IAAK;AAClB,MAAI,CAAC,IAAI,SAAS,CAAC,IAAI,OAAQ;AAG/B,MAAI,IAAI,UAAU,IAAI,SAAS,IAAI,WAAW,IAAI,QAAQ;AACxD,OAAI,QAAQ,IAAI;AAChB,OAAI,SAAS,IAAI;;EAGnB,MAAM,MAAM,IAAI,WAAW,KAAK;AAChC,MAAI,CAAC,IAAK;AACV,MAAI,UAAU,KAAK,GAAG,GAAG,IAAI,OAAO,IAAI,OAAO;;;YArKhD,OAAO;YAGP,SAAS,EAAE,MAAM,QAAQ,CAAC;wBA1B5B,cAAc,aAAa"}
@@ -1,6 +1,5 @@
1
1
  import { PlaybackController } from "../gui/PlaybackController.js";
2
2
  import { EFTimegroup } from "./EFTimegroup.js";
3
- import { Task } from "@lit/task";
4
3
  import { LitElement, ReactiveController } from "lit";
5
4
 
6
5
  //#region src/elements/EFTemporal.d.ts
@@ -191,7 +190,14 @@ declare class TemporalMixinInterface {
191
190
  * A convenience property for getting the root timegroup of the media element.
192
191
  */
193
192
  rootTimegroup?: EFTimegroup;
194
- frameTask: Task<readonly unknown[], unknown>;
193
+ /**
194
+ * Frame task interface. Can be a Lit Task or a simple object with run() and taskComplete.
195
+ * @deprecated Prefer using FrameRenderable interface via FrameController.
196
+ */
197
+ frameTask: {
198
+ run(): void | Promise<void>;
199
+ taskComplete: Promise<unknown>;
200
+ };
195
201
  didBecomeRoot(): void;
196
202
  didBecomeChild(): void;
197
203
  updateComplete: Promise<boolean>;
@@ -1,9 +1,7 @@
1
- import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
2
1
  import { PlaybackController } from "../gui/PlaybackController.js";
3
2
  import { durationConverter } from "./durationConverter.js";
4
- import { __decorate } from "../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js";
3
+ import { __decorate } from "../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
5
4
  import { consume, createContext } from "@lit/context";
6
- import { Task } from "@lit/task";
7
5
  import { property, state } from "lit/decorators.js";
8
6
 
9
7
  //#region src/elements/EFTemporal.ts
@@ -124,15 +122,34 @@ function determineCurrentTimeSource(playbackController, rootTimegroup, isRootTim
124
122
  const isEFTemporal = (obj) => obj[EF_TEMPORAL];
125
123
  const EF_TEMPORAL = Symbol("EF_TEMPORAL");
126
124
  const deepGetTemporalElements = (element, temporals = []) => {
127
- for (const child of element.children) {
125
+ const children = getChildrenIncludingSlotted(element);
126
+ for (const child of children) {
128
127
  if (isEFTemporal(child)) temporals.push(child);
129
128
  deepGetTemporalElements(child, temporals);
130
129
  }
131
130
  return temporals;
132
131
  };
132
+ /**
133
+ * Gets all child elements including slotted content for shadow DOM elements.
134
+ * For elements with shadow DOM that contain slots, this returns the assigned
135
+ * elements (slotted content) instead of just the shadow DOM children.
136
+ */
137
+ const getChildrenIncludingSlotted = (element) => {
138
+ if (element.shadowRoot) {
139
+ const slots = element.shadowRoot.querySelectorAll("slot");
140
+ if (slots.length > 0) {
141
+ const assignedElements = [];
142
+ for (const slot of slots) assignedElements.push(...slot.assignedElements());
143
+ for (const child of element.shadowRoot.children) if (child.tagName !== "SLOT") assignedElements.push(child);
144
+ return assignedElements;
145
+ }
146
+ }
147
+ return Array.from(element.children);
148
+ };
133
149
  const deepGetElementsWithFrameTasks = (element, elements = []) => {
134
- for (const child of element.children) {
135
- if ("frameTask" in child && child.frameTask instanceof Task) elements.push(child);
150
+ const children = getChildrenIncludingSlotted(element);
151
+ for (const child of children) {
152
+ if ("frameTask" in child && child.frameTask != null && typeof child.frameTask.run === "function") elements.push(child);
136
153
  deepGetElementsWithFrameTasks(child, elements);
137
154
  }
138
155
  return elements;
@@ -153,7 +170,8 @@ resetTemporalCache();
153
170
  const shallowGetTemporalElements = (element, temporals = []) => {
154
171
  const cachedResult = temporalCache.get(element);
155
172
  if (cachedResult) return cachedResult;
156
- for (const child of element.children) if (isEFTemporal(child)) temporals.push(child);
173
+ const children = getChildrenIncludingSlotted(element);
174
+ for (const child of children) if (isEFTemporal(child)) temporals.push(child);
157
175
  else shallowGetTemporalElements(child, temporals);
158
176
  temporalCache.set(element, temporals);
159
177
  return temporals;
@@ -204,30 +222,18 @@ const EFTemporal = (superClass) => {
204
222
  this._sourceOutMs = void 0;
205
223
  this._startOffsetMs = 0;
206
224
  this.rootTimegroup = this.getRootTimegroup();
207
- this.frameTask = new Task(this, {
208
- autoRun: EF_INTERACTIVE,
209
- args: () => [this.ownCurrentTimeMs],
210
- onError: (error) => {
211
- this.frameTask.taskComplete.catch(() => {});
212
- if (error instanceof DOMException && error.name === "AbortError" || error instanceof Error && (error.name === "AbortError" || error.message?.includes("signal is aborted") || error.message?.includes("The user aborted a request"))) return;
213
- console.error("EFTemporal frameTask error", error);
214
- },
215
- task: async ([], { signal }) => {
216
- let fullyUpdated = await this.updateComplete;
217
- signal?.throwIfAborted();
218
- let loopCount = 0;
219
- const MAX_LOOP_ITERATIONS = 100;
220
- while (!fullyUpdated) {
221
- loopCount++;
222
- if (loopCount > MAX_LOOP_ITERATIONS) {
223
- console.error(`[EFTemporal] frameTask while loop exceeded ${MAX_LOOP_ITERATIONS} iterations, breaking. Element:`, this.tagName, this.id || "unnamed");
224
- break;
225
- }
226
- fullyUpdated = await this.updateComplete;
227
- signal?.throwIfAborted();
228
- }
229
- }
230
- });
225
+ this.frameTask = (() => {
226
+ const self = this;
227
+ const taskObj = {
228
+ run: () => {
229
+ self.#frameTaskPromise = self.updateComplete.then(() => {});
230
+ taskObj.taskComplete = self.#frameTaskPromise;
231
+ return self.#frameTaskPromise;
232
+ },
233
+ taskComplete: Promise.resolve()
234
+ };
235
+ return taskObj;
236
+ })();
231
237
  }
232
238
  #ownCurrentTimeController;
233
239
  #parentTimegroup;
@@ -435,6 +441,11 @@ const EFTemporal = (superClass) => {
435
441
  const leadingTrimMs = this.sourceInMs || this.trimStartMs || 0;
436
442
  return this.ownCurrentTimeMs + leadingTrimMs;
437
443
  }
444
+ /**
445
+ * @deprecated Use FrameRenderable interface via FrameController instead.
446
+ * This is a compatibility wrapper - base class just waits for updateComplete.
447
+ */
448
+ #frameTaskPromise = Promise.resolve();
438
449
  didBecomeRoot() {
439
450
  if (!this.playbackController) {
440
451
  this.playbackController = new PlaybackController(this);