@editframe/elements 0.30.1-beta.0 → 0.31.0-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 (325) hide show
  1. package/dist/EF_FRAMEGEN.d.ts +5 -0
  2. package/dist/EF_FRAMEGEN.js +20 -4
  3. package/dist/EF_FRAMEGEN.js.map +1 -1
  4. package/dist/EF_INTERACTIVE.js.map +1 -1
  5. package/dist/_virtual/rolldown_runtime.js +27 -0
  6. package/dist/canvas/EFCanvas.d.ts +311 -0
  7. package/dist/canvas/EFCanvas.js +1089 -0
  8. package/dist/canvas/EFCanvas.js.map +1 -0
  9. package/dist/canvas/EFCanvasItem.d.ts +55 -0
  10. package/dist/canvas/EFCanvasItem.js +72 -0
  11. package/dist/canvas/EFCanvasItem.js.map +1 -0
  12. package/dist/canvas/api/CanvasAPI.d.ts +115 -0
  13. package/dist/canvas/api/CanvasAPI.js +182 -0
  14. package/dist/canvas/api/CanvasAPI.js.map +1 -0
  15. package/dist/canvas/api/types.d.ts +42 -0
  16. package/dist/canvas/coordinateTransform.js +90 -0
  17. package/dist/canvas/coordinateTransform.js.map +1 -0
  18. package/dist/canvas/getElementBounds.js +40 -0
  19. package/dist/canvas/getElementBounds.js.map +1 -0
  20. package/dist/canvas/overlays/SelectionOverlay.js +265 -0
  21. package/dist/canvas/overlays/SelectionOverlay.js.map +1 -0
  22. package/dist/canvas/overlays/overlayState.js +153 -0
  23. package/dist/canvas/overlays/overlayState.js.map +1 -0
  24. package/dist/canvas/selection/SelectionController.js +105 -0
  25. package/dist/canvas/selection/SelectionController.js.map +1 -0
  26. package/dist/canvas/selection/SelectionModel.d.ts +98 -0
  27. package/dist/canvas/selection/SelectionModel.js +229 -0
  28. package/dist/canvas/selection/SelectionModel.js.map +1 -0
  29. package/dist/canvas/selection/selectionContext.d.ts +31 -0
  30. package/dist/canvas/selection/selectionContext.js +12 -0
  31. package/dist/canvas/selection/selectionContext.js.map +1 -0
  32. package/dist/elements/ContainerInfo.d.ts +29 -0
  33. package/dist/elements/ContainerInfo.js +30 -0
  34. package/dist/elements/ContainerInfo.js.map +1 -0
  35. package/dist/elements/EFAudio.d.ts +13 -3
  36. package/dist/elements/EFAudio.js +64 -10
  37. package/dist/elements/EFAudio.js.map +1 -1
  38. package/dist/elements/EFCaptions.d.ts +18 -16
  39. package/dist/elements/EFCaptions.js +110 -19
  40. package/dist/elements/EFCaptions.js.map +1 -1
  41. package/dist/elements/EFImage.d.ts +16 -6
  42. package/dist/elements/EFImage.js +79 -9
  43. package/dist/elements/EFImage.js.map +1 -1
  44. package/dist/elements/EFMedia/AssetIdMediaEngine.js +51 -4
  45. package/dist/elements/EFMedia/AssetIdMediaEngine.js.map +1 -1
  46. package/dist/elements/EFMedia/AssetMediaEngine.js +125 -52
  47. package/dist/elements/EFMedia/AssetMediaEngine.js.map +1 -1
  48. package/dist/elements/EFMedia/BaseMediaEngine.js +24 -6
  49. package/dist/elements/EFMedia/BaseMediaEngine.js.map +1 -1
  50. package/dist/elements/EFMedia/JitMediaEngine.js +12 -8
  51. package/dist/elements/EFMedia/JitMediaEngine.js.map +1 -1
  52. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +46 -7
  53. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js.map +1 -1
  54. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +98 -73
  55. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js.map +1 -1
  56. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js +28 -5
  57. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js.map +1 -1
  58. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +18 -6
  59. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js.map +1 -1
  60. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +8 -2
  61. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js.map +1 -1
  62. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +31 -6
  63. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js.map +1 -1
  64. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +28 -5
  65. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js.map +1 -1
  66. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +97 -72
  67. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js.map +1 -1
  68. package/dist/elements/EFMedia/shared/AudioSpanUtils.js +3 -1
  69. package/dist/elements/EFMedia/shared/AudioSpanUtils.js.map +1 -1
  70. package/dist/elements/EFMedia/shared/BufferUtils.js +1 -1
  71. package/dist/elements/EFMedia/shared/BufferUtils.js.map +1 -1
  72. package/dist/elements/EFMedia/shared/ThumbnailExtractor.js +25 -14
  73. package/dist/elements/EFMedia/shared/ThumbnailExtractor.js.map +1 -1
  74. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js +47 -16
  75. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js.map +1 -1
  76. package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js +37 -19
  77. package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js.map +1 -1
  78. package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js +65 -21
  79. package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js.map +1 -1
  80. package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js +8 -3
  81. package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js.map +1 -1
  82. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.js +32 -9
  83. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.js.map +1 -1
  84. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js +33 -10
  85. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js.map +1 -1
  86. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js +23 -8
  87. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js.map +1 -1
  88. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.js +34 -10
  89. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.js.map +1 -1
  90. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js +31 -8
  91. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js.map +1 -1
  92. package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js +31 -114
  93. package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js.map +1 -1
  94. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +44 -8
  95. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js.map +1 -1
  96. package/dist/elements/EFMedia.d.ts +18 -7
  97. package/dist/elements/EFMedia.js +23 -3
  98. package/dist/elements/EFMedia.js.map +1 -1
  99. package/dist/elements/EFPanZoom.d.ts +96 -0
  100. package/dist/elements/EFPanZoom.js +290 -0
  101. package/dist/elements/EFPanZoom.js.map +1 -0
  102. package/dist/elements/EFSourceMixin.js +7 -6
  103. package/dist/elements/EFSourceMixin.js.map +1 -1
  104. package/dist/elements/EFSurface.d.ts +6 -6
  105. package/dist/elements/EFSurface.js +7 -2
  106. package/dist/elements/EFSurface.js.map +1 -1
  107. package/dist/elements/EFTemporal.d.ts +2 -1
  108. package/dist/elements/EFTemporal.js +192 -71
  109. package/dist/elements/EFTemporal.js.map +1 -1
  110. package/dist/elements/EFText.d.ts +5 -4
  111. package/dist/elements/EFText.js +102 -13
  112. package/dist/elements/EFText.js.map +1 -1
  113. package/dist/elements/EFTextSegment.d.ts +32 -6
  114. package/dist/elements/EFTextSegment.js +53 -15
  115. package/dist/elements/EFTextSegment.js.map +1 -1
  116. package/dist/elements/EFThumbnailStrip.d.ts +118 -56
  117. package/dist/elements/EFThumbnailStrip.js +522 -358
  118. package/dist/elements/EFThumbnailStrip.js.map +1 -1
  119. package/dist/elements/EFTimegroup.d.ts +223 -27
  120. package/dist/elements/EFTimegroup.js +851 -148
  121. package/dist/elements/EFTimegroup.js.map +1 -1
  122. package/dist/elements/EFVideo.d.ts +42 -5
  123. package/dist/elements/EFVideo.js +165 -11
  124. package/dist/elements/EFVideo.js.map +1 -1
  125. package/dist/elements/EFWaveform.d.ts +6 -6
  126. package/dist/elements/EFWaveform.js +2 -1
  127. package/dist/elements/EFWaveform.js.map +1 -1
  128. package/dist/elements/ElementPositionInfo.d.ts +35 -0
  129. package/dist/elements/ElementPositionInfo.js +49 -0
  130. package/dist/elements/ElementPositionInfo.js.map +1 -0
  131. package/dist/elements/FetchMixin.js +16 -1
  132. package/dist/elements/FetchMixin.js.map +1 -1
  133. package/dist/elements/SessionThumbnailCache.js +152 -0
  134. package/dist/elements/SessionThumbnailCache.js.map +1 -0
  135. package/dist/elements/TargetController.js +3 -1
  136. package/dist/elements/TargetController.js.map +1 -1
  137. package/dist/elements/TimegroupController.js +9 -3
  138. package/dist/elements/TimegroupController.js.map +1 -1
  139. package/dist/elements/findRootTemporal.js +30 -0
  140. package/dist/elements/findRootTemporal.js.map +1 -0
  141. package/dist/elements/renderTemporalAudio.js +18 -5
  142. package/dist/elements/renderTemporalAudio.js.map +1 -1
  143. package/dist/elements/updateAnimations.js +492 -109
  144. package/dist/elements/updateAnimations.js.map +1 -1
  145. package/dist/getRenderInfo.d.ts +2 -2
  146. package/dist/gui/ContextMixin.js +4 -2
  147. package/dist/gui/ContextMixin.js.map +1 -1
  148. package/dist/gui/Controllable.js +74 -1
  149. package/dist/gui/Controllable.js.map +1 -1
  150. package/dist/gui/EFActiveRootTemporal.d.ts +50 -0
  151. package/dist/gui/EFActiveRootTemporal.js +94 -0
  152. package/dist/gui/EFActiveRootTemporal.js.map +1 -0
  153. package/dist/gui/EFConfiguration.d.ts +11 -5
  154. package/dist/gui/EFConfiguration.js.map +1 -1
  155. package/dist/gui/EFControls.d.ts +2 -2
  156. package/dist/gui/EFControls.js +109 -13
  157. package/dist/gui/EFControls.js.map +1 -1
  158. package/dist/gui/EFDial.d.ts +4 -4
  159. package/dist/gui/EFFilmstrip.d.ts +11 -214
  160. package/dist/gui/EFFilmstrip.js +53 -1152
  161. package/dist/gui/EFFilmstrip.js.map +1 -1
  162. package/dist/gui/EFFitScale.d.ts +3 -3
  163. package/dist/gui/EFFitScale.js +39 -12
  164. package/dist/gui/EFFitScale.js.map +1 -1
  165. package/dist/gui/EFFocusOverlay.d.ts +4 -4
  166. package/dist/gui/EFOverlayItem.d.ts +48 -0
  167. package/dist/gui/EFOverlayItem.js +97 -0
  168. package/dist/gui/EFOverlayItem.js.map +1 -0
  169. package/dist/gui/EFOverlayLayer.d.ts +70 -0
  170. package/dist/gui/EFOverlayLayer.js +104 -0
  171. package/dist/gui/EFOverlayLayer.js.map +1 -0
  172. package/dist/gui/EFPause.d.ts +4 -4
  173. package/dist/gui/EFPlay.d.ts +4 -4
  174. package/dist/gui/EFPreview.d.ts +4 -4
  175. package/dist/gui/EFResizableBox.d.ts +12 -16
  176. package/dist/gui/EFResizableBox.js +109 -451
  177. package/dist/gui/EFResizableBox.js.map +1 -1
  178. package/dist/gui/EFScrubber.d.ts +30 -5
  179. package/dist/gui/EFScrubber.js +224 -31
  180. package/dist/gui/EFScrubber.js.map +1 -1
  181. package/dist/gui/EFTimeDisplay.d.ts +4 -4
  182. package/dist/gui/EFTimeDisplay.js +4 -1
  183. package/dist/gui/EFTimeDisplay.js.map +1 -1
  184. package/dist/gui/EFTimelineRuler.d.ts +71 -0
  185. package/dist/gui/EFTimelineRuler.js +320 -0
  186. package/dist/gui/EFTimelineRuler.js.map +1 -0
  187. package/dist/gui/EFToggleLoop.d.ts +4 -4
  188. package/dist/gui/EFTogglePlay.d.ts +4 -4
  189. package/dist/gui/EFTransformHandles.d.ts +91 -0
  190. package/dist/gui/EFTransformHandles.js +393 -0
  191. package/dist/gui/EFTransformHandles.js.map +1 -0
  192. package/dist/gui/EFWorkbench.d.ts +182 -4
  193. package/dist/gui/EFWorkbench.js +2067 -22
  194. package/dist/gui/EFWorkbench.js.map +1 -1
  195. package/dist/gui/FitScaleHelpers.d.ts +31 -0
  196. package/dist/gui/FitScaleHelpers.js +41 -0
  197. package/dist/gui/FitScaleHelpers.js.map +1 -0
  198. package/dist/gui/PlaybackController.d.ts +2 -1
  199. package/dist/gui/PlaybackController.js +46 -15
  200. package/dist/gui/PlaybackController.js.map +1 -1
  201. package/dist/gui/TWMixin.js +1 -1
  202. package/dist/gui/TWMixin.js.map +1 -1
  203. package/dist/gui/hierarchy/EFHierarchy.d.ts +65 -0
  204. package/dist/gui/hierarchy/EFHierarchy.js +338 -0
  205. package/dist/gui/hierarchy/EFHierarchy.js.map +1 -0
  206. package/dist/gui/hierarchy/EFHierarchyItem.d.ts +118 -0
  207. package/dist/gui/hierarchy/EFHierarchyItem.js +551 -0
  208. package/dist/gui/hierarchy/EFHierarchyItem.js.map +1 -0
  209. package/dist/gui/hierarchy/hierarchyContext.d.ts +38 -0
  210. package/dist/gui/hierarchy/hierarchyContext.js +8 -0
  211. package/dist/gui/hierarchy/hierarchyContext.js.map +1 -0
  212. package/dist/gui/icons.js +34 -0
  213. package/dist/gui/icons.js.map +1 -0
  214. package/dist/gui/panZoomTransformContext.js +12 -0
  215. package/dist/gui/panZoomTransformContext.js.map +1 -0
  216. package/dist/gui/previewSettingsContext.js +12 -0
  217. package/dist/gui/previewSettingsContext.js.map +1 -0
  218. package/dist/gui/timeline/EFTimeline.d.ts +270 -0
  219. package/dist/gui/timeline/EFTimeline.js +1369 -0
  220. package/dist/gui/timeline/EFTimeline.js.map +1 -0
  221. package/dist/gui/timeline/EFTimelineRow.js +374 -0
  222. package/dist/gui/timeline/EFTimelineRow.js.map +1 -0
  223. package/dist/gui/timeline/TrimHandles.d.ts +36 -0
  224. package/dist/gui/timeline/TrimHandles.js +204 -0
  225. package/dist/gui/timeline/TrimHandles.js.map +1 -0
  226. package/dist/gui/timeline/flattenHierarchy.js +31 -0
  227. package/dist/gui/timeline/flattenHierarchy.js.map +1 -0
  228. package/dist/gui/timeline/timelineStateContext.d.ts +26 -0
  229. package/dist/gui/timeline/timelineStateContext.js +42 -0
  230. package/dist/gui/timeline/timelineStateContext.js.map +1 -0
  231. package/dist/gui/timeline/tracks/AudioTrack.js +264 -0
  232. package/dist/gui/timeline/tracks/AudioTrack.js.map +1 -0
  233. package/dist/gui/timeline/tracks/CaptionsTrack.js +595 -0
  234. package/dist/gui/timeline/tracks/CaptionsTrack.js.map +1 -0
  235. package/dist/gui/timeline/tracks/HTMLTrack.js +19 -0
  236. package/dist/gui/timeline/tracks/HTMLTrack.js.map +1 -0
  237. package/dist/gui/timeline/tracks/ImageTrack.js +53 -0
  238. package/dist/gui/timeline/tracks/ImageTrack.js.map +1 -0
  239. package/dist/gui/timeline/tracks/TextTrack.js +250 -0
  240. package/dist/gui/timeline/tracks/TextTrack.js.map +1 -0
  241. package/dist/gui/timeline/tracks/TimegroupTrack.js +143 -0
  242. package/dist/gui/timeline/tracks/TimegroupTrack.js.map +1 -0
  243. package/dist/gui/timeline/tracks/TrackItem.js +269 -0
  244. package/dist/gui/timeline/tracks/TrackItem.js.map +1 -0
  245. package/dist/gui/timeline/tracks/VideoTrack.js +265 -0
  246. package/dist/gui/timeline/tracks/VideoTrack.js.map +1 -0
  247. package/dist/gui/timeline/tracks/WaveformTrack.js +19 -0
  248. package/dist/gui/timeline/tracks/WaveformTrack.js.map +1 -0
  249. package/dist/gui/timeline/tracks/ensureTrackItemInit.js +1 -0
  250. package/dist/gui/timeline/tracks/preloadTracks.js +9 -0
  251. package/dist/gui/timeline/tracks/renderTrackChildren.js +119 -0
  252. package/dist/gui/timeline/tracks/renderTrackChildren.js.map +1 -0
  253. package/dist/gui/timeline/tracks/waveformUtils.js +80 -0
  254. package/dist/gui/timeline/tracks/waveformUtils.js.map +1 -0
  255. package/dist/gui/transformCalculations.js +217 -0
  256. package/dist/gui/transformCalculations.js.map +1 -0
  257. package/dist/gui/transformUtils.d.ts +37 -0
  258. package/dist/gui/transformUtils.js +77 -0
  259. package/dist/gui/transformUtils.js.map +1 -0
  260. package/dist/gui/tree/EFTree.d.ts +59 -0
  261. package/dist/gui/tree/EFTree.js +174 -0
  262. package/dist/gui/tree/EFTree.js.map +1 -0
  263. package/dist/gui/tree/EFTreeItem.d.ts +38 -0
  264. package/dist/gui/tree/EFTreeItem.js +146 -0
  265. package/dist/gui/tree/EFTreeItem.js.map +1 -0
  266. package/dist/gui/tree/treeContext.d.ts +60 -0
  267. package/dist/gui/tree/treeContext.js +23 -0
  268. package/dist/gui/tree/treeContext.js.map +1 -0
  269. package/dist/index.d.ts +32 -8
  270. package/dist/index.js +30 -6
  271. package/dist/index.js.map +1 -1
  272. package/dist/node_modules/react/cjs/react-jsx-runtime.development.js +688 -0
  273. package/dist/node_modules/react/cjs/react-jsx-runtime.development.js.map +1 -0
  274. package/dist/node_modules/react/cjs/react.development.js +1521 -0
  275. package/dist/node_modules/react/cjs/react.development.js.map +1 -0
  276. package/dist/node_modules/react/index.js +13 -0
  277. package/dist/node_modules/react/index.js.map +1 -0
  278. package/dist/node_modules/react/jsx-runtime.js +13 -0
  279. package/dist/node_modules/react/jsx-runtime.js.map +1 -0
  280. package/dist/preview/AdaptiveResolutionTracker.js +228 -0
  281. package/dist/preview/AdaptiveResolutionTracker.js.map +1 -0
  282. package/dist/preview/RenderProfiler.js +135 -0
  283. package/dist/preview/RenderProfiler.js.map +1 -0
  284. package/dist/preview/previewSettings.js +131 -0
  285. package/dist/preview/previewSettings.js.map +1 -0
  286. package/dist/preview/previewTypes.js +64 -0
  287. package/dist/preview/previewTypes.js.map +1 -0
  288. package/dist/preview/renderTimegroupPreview.js +656 -0
  289. package/dist/preview/renderTimegroupPreview.js.map +1 -0
  290. package/dist/preview/renderTimegroupToCanvas.d.ts +37 -0
  291. package/dist/preview/renderTimegroupToCanvas.js +840 -0
  292. package/dist/preview/renderTimegroupToCanvas.js.map +1 -0
  293. package/dist/preview/renderTimegroupToVideo.d.ts +39 -0
  294. package/dist/preview/renderTimegroupToVideo.js +274 -0
  295. package/dist/preview/renderTimegroupToVideo.js.map +1 -0
  296. package/dist/preview/renderers.js +16 -0
  297. package/dist/preview/renderers.js.map +1 -0
  298. package/dist/preview/statsTrackingStrategy.js +201 -0
  299. package/dist/preview/statsTrackingStrategy.js.map +1 -0
  300. package/dist/preview/thumbnailCacheSettings.js +52 -0
  301. package/dist/preview/thumbnailCacheSettings.js.map +1 -0
  302. package/dist/preview/workers/WorkerPool.js +178 -0
  303. package/dist/preview/workers/WorkerPool.js.map +1 -0
  304. package/dist/sandbox/PlaybackControls.js +10 -0
  305. package/dist/sandbox/PlaybackControls.js.map +1 -0
  306. package/dist/sandbox/ScenarioRunner.js +1 -0
  307. package/dist/sandbox/index.js +2 -0
  308. package/dist/style.css +66 -69
  309. package/dist/transcoding/types/index.d.ts +2 -1
  310. package/dist/transcoding/utils/UrlGenerator.d.ts +6 -1
  311. package/dist/transcoding/utils/UrlGenerator.js +12 -3
  312. package/dist/transcoding/utils/UrlGenerator.js.map +1 -1
  313. package/dist/utils/LRUCache.js +1 -375
  314. package/dist/utils/LRUCache.js.map +1 -1
  315. package/dist/utils/frameTime.js +14 -0
  316. package/dist/utils/frameTime.js.map +1 -0
  317. package/package.json +3 -3
  318. package/test/profilingPlugin.ts +223 -0
  319. package/test/recordReplayProxyPlugin.js +22 -27
  320. package/test/thumbnail-performance-test.html +116 -0
  321. package/test/visualRegressionUtils.ts +286 -0
  322. package/types.json +1 -1
  323. package/dist/elements/TimegroupController.d.ts +0 -18
  324. package/dist/msToTimeCode.js +0 -17
  325. package/dist/msToTimeCode.js.map +0 -1
@@ -7,7 +7,120 @@ import { Task } from "@lit/task";
7
7
  import { property, state } from "lit/decorators.js";
8
8
 
9
9
  //#region src/elements/EFTemporal.ts
10
+ let isTimegroupCalculatingDurationFn = null;
11
+ const registerIsTimegroupCalculatingDuration = (fn) => {
12
+ isTimegroupCalculatingDurationFn = fn;
13
+ };
14
+ const getIsTimegroupCalculatingDuration = () => {
15
+ if (isTimegroupCalculatingDurationFn) return isTimegroupCalculatingDurationFn;
16
+ let fallbackFn = () => false;
17
+ try {
18
+ const efTimegroupModule = globalThis.__EFTimegroupModule;
19
+ if (efTimegroupModule?.isTimegroupCalculatingDuration) fallbackFn = efTimegroupModule.isTimegroupCalculatingDuration;
20
+ } catch {}
21
+ isTimegroupCalculatingDurationFn = fallbackFn;
22
+ return fallbackFn;
23
+ };
10
24
  const timegroupContext = createContext(Symbol("timeGroupContext"));
25
+ function determineTemporalRole(parentTimegroup) {
26
+ return parentTimegroup === void 0 ? "root" : "child";
27
+ }
28
+ function determineDurationSource(intrinsicDurationMs, explicitDurationMs, parentDurationMs) {
29
+ if (intrinsicDurationMs !== void 0) return {
30
+ source: "intrinsic",
31
+ baseDurationMs: intrinsicDurationMs
32
+ };
33
+ if (explicitDurationMs !== void 0) return {
34
+ source: "explicit",
35
+ baseDurationMs: explicitDurationMs
36
+ };
37
+ if (parentDurationMs !== void 0) return {
38
+ source: "inherited",
39
+ baseDurationMs: parentDurationMs
40
+ };
41
+ return {
42
+ source: "inherited",
43
+ baseDurationMs: 0
44
+ };
45
+ }
46
+ function determineDurationModificationStrategy(trimStartMs, trimEndMs, sourceInMs, sourceOutMs) {
47
+ if (trimStartMs !== void 0 || trimEndMs !== void 0) return {
48
+ strategy: "trimming",
49
+ trimStartMs,
50
+ trimEndMs,
51
+ sourceInMs: void 0,
52
+ sourceOutMs: void 0
53
+ };
54
+ if (sourceInMs !== void 0 || sourceOutMs !== void 0) return {
55
+ strategy: "source-manipulation",
56
+ trimStartMs: void 0,
57
+ trimEndMs: void 0,
58
+ sourceInMs,
59
+ sourceOutMs
60
+ };
61
+ return {
62
+ strategy: "none",
63
+ trimStartMs: void 0,
64
+ trimEndMs: void 0,
65
+ sourceInMs: void 0,
66
+ sourceOutMs: void 0
67
+ };
68
+ }
69
+ function evaluateModifiedDuration(baseDurationMs, modification) {
70
+ if (baseDurationMs === 0) return 0;
71
+ switch (modification.strategy) {
72
+ case "trimming": {
73
+ const trimmedDurationMs = baseDurationMs - (modification.trimStartMs ?? 0) - (modification.trimEndMs ?? 0);
74
+ return Math.max(0, trimmedDurationMs);
75
+ }
76
+ case "source-manipulation": {
77
+ const sourceInMs = modification.sourceInMs ?? 0;
78
+ const sourceOutMs = modification.sourceOutMs ?? baseDurationMs;
79
+ if (sourceInMs >= sourceOutMs) return 0;
80
+ return sourceOutMs - sourceInMs;
81
+ }
82
+ case "none": return baseDurationMs;
83
+ }
84
+ }
85
+ function determineStartTimeStrategy(parentTimegroup) {
86
+ if (!parentTimegroup) return "offset";
87
+ return parentTimegroup.mode === "sequence" ? "sequence" : "offset";
88
+ }
89
+ function evaluateStartTimeForSequence(_element, parentTimegroup, siblingTemporals, ownIndex) {
90
+ if (ownIndex === 0) return parentTimegroup.startTimeMs;
91
+ const previous = siblingTemporals[ownIndex - 1];
92
+ if (!previous) throw new Error("Previous temporal element not found");
93
+ return previous.startTimeMs + previous.durationMs - parentTimegroup.overlapMs;
94
+ }
95
+ function evaluateStartTimeForOffset(parentTimegroup, offsetMs) {
96
+ return parentTimegroup.startTimeMs + offsetMs;
97
+ }
98
+ function evaluateStartTime(element, parentTimegroup, offsetMs, getSiblingTemporals) {
99
+ if (!parentTimegroup) return 0;
100
+ switch (determineStartTimeStrategy(parentTimegroup)) {
101
+ case "sequence": {
102
+ const siblingTemporals = getSiblingTemporals(parentTimegroup);
103
+ const ownIndex = siblingTemporals.indexOf(element);
104
+ if (ownIndex === -1) return 0;
105
+ return evaluateStartTimeForSequence(element, parentTimegroup, siblingTemporals, ownIndex);
106
+ }
107
+ case "offset": return evaluateStartTimeForOffset(parentTimegroup, offsetMs);
108
+ }
109
+ }
110
+ function determineCurrentTimeSource(playbackController, rootTimegroup, isRootTimegroup, localTimeMs, startTimeMs, durationMs) {
111
+ if (playbackController) return {
112
+ source: "playback-controller",
113
+ timeMs: Math.min(Math.max(0, playbackController.currentTimeMs), durationMs)
114
+ };
115
+ if (rootTimegroup && !isRootTimegroup) return {
116
+ source: "root-timegroup",
117
+ timeMs: Math.min(Math.max(0, rootTimegroup.currentTimeMs - startTimeMs), durationMs)
118
+ };
119
+ return {
120
+ source: "local",
121
+ timeMs: Math.min(Math.max(0, localTimeMs), durationMs)
122
+ };
123
+ }
11
124
  const isEFTemporal = (obj) => obj[EF_TEMPORAL];
12
125
  const EF_TEMPORAL = Symbol("EF_TEMPORAL");
13
126
  const deepGetTemporalElements = (element, temporals = []) => {
@@ -46,13 +159,19 @@ const shallowGetTemporalElements = (element, temporals = []) => {
46
159
  return temporals;
47
160
  };
48
161
  var OwnCurrentTimeController = class {
162
+ #lastKnownTimeMs = void 0;
49
163
  constructor(host, temporal) {
50
164
  this.host = host;
51
165
  this.temporal = temporal;
52
166
  host.addController(this);
53
167
  }
54
168
  hostUpdated() {
55
- this.temporal.requestUpdate("ownCurrentTimeMs");
169
+ const currentTimeMs = this.host.currentTimeMs;
170
+ if (this.#lastKnownTimeMs === currentTimeMs) return;
171
+ this.#lastKnownTimeMs = currentTimeMs;
172
+ setTimeout(() => {
173
+ this.temporal.requestUpdate("ownCurrentTimeMs");
174
+ }, 0);
56
175
  }
57
176
  remove() {
58
177
  this.host.removeController(this);
@@ -88,33 +207,68 @@ const EFTemporal = (superClass) => {
88
207
  this.frameTask = new Task(this, {
89
208
  autoRun: EF_INTERACTIVE,
90
209
  args: () => [this.ownCurrentTimeMs],
91
- task: async ([], { signal: _signal }) => {
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 }) => {
92
216
  let fullyUpdated = await this.updateComplete;
93
- while (!fullyUpdated) 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
+ }
94
229
  }
95
230
  });
96
231
  }
232
+ #ownCurrentTimeController;
97
233
  #parentTimegroup;
234
+ #rootTimegroupLocked = false;
98
235
  set parentTimegroup(value) {
99
236
  const oldParent = this.#parentTimegroup;
237
+ const oldRole = determineTemporalRole(oldParent);
238
+ const newRole = determineTemporalRole(value);
100
239
  this.#parentTimegroup = value;
101
- this.ownCurrentTimeController?.remove();
102
- this.rootTimegroup = this.getRootTimegroup();
103
- if (this.rootTimegroup) this.ownCurrentTimeController = new OwnCurrentTimeController(this.rootTimegroup, this);
104
- if (oldParent !== value) if (!value) this.didBecomeRoot();
240
+ this.#ownCurrentTimeController?.remove();
241
+ if (!this.#rootTimegroupLocked) this.rootTimegroup = this.getRootTimegroup();
242
+ if (this.rootTimegroup) this.#ownCurrentTimeController = new OwnCurrentTimeController(this.rootTimegroup, this);
243
+ if (oldRole !== newRole) if (newRole === "root") this.didBecomeRoot();
105
244
  else this.didBecomeChild();
106
245
  }
246
+ /**
247
+ * Lock the rootTimegroup to prevent auto-recalculation.
248
+ * Used for render clones where the root must be fixed.
249
+ * @internal
250
+ */
251
+ lockRootTimegroup() {
252
+ this.#rootTimegroupLocked = true;
253
+ }
107
254
  disconnectedCallback() {
108
255
  super.disconnectedCallback();
109
- this.ownCurrentTimeController?.remove();
256
+ this.#ownCurrentTimeController?.remove();
110
257
  if (this.playbackController) {
111
258
  this.playbackController.remove();
112
259
  this.playbackController = void 0;
113
260
  }
261
+ import("./updateAnimations.js").then(({ cleanupTrackedAnimations }) => {
262
+ cleanupTrackedAnimations(this);
263
+ });
114
264
  }
115
265
  connectedCallback() {
116
266
  super.connectedCallback();
117
- if (!this.parentTimegroup) this.didBecomeRoot();
267
+ this.#ownCurrentTimeController?.remove();
268
+ if (!(this.parentElement?.closest("ef-timegroup") != null) && !this.playbackController) this.updateComplete.then(() => {
269
+ if (!this.isConnected) return;
270
+ if (!this.playbackController) this.didBecomeRoot();
271
+ });
118
272
  }
119
273
  get parentTimegroup() {
120
274
  return this.#parentTimegroup;
@@ -205,28 +359,18 @@ const EFTemporal = (superClass) => {
205
359
  }
206
360
  get intrinsicDurationMs() {}
207
361
  get durationMs() {
208
- const baseDurationMs = this.intrinsicDurationMs ?? this._durationMs ?? this.parentTimegroup?.durationMs ?? 0;
209
- if (baseDurationMs === 0) return 0;
210
- if (this.trimStartMs || this.trimEndMs) {
211
- const trimmedDurationMs = baseDurationMs - (this.trimStartMs ?? 0) - (this.trimEndMs ?? 0);
212
- if (trimmedDurationMs < 0) return 0;
213
- return trimmedDurationMs;
214
- }
215
- if (this.sourceInMs || this.sourceOutMs) {
216
- const sourceInMs = this.sourceInMs ?? 0;
217
- const sourceOutMs = this.sourceOutMs ?? baseDurationMs;
218
- if (sourceInMs >= sourceOutMs) return 0;
219
- return sourceOutMs - sourceInMs;
220
- }
221
- return baseDurationMs;
362
+ const parentDurationMs = getIsTimegroupCalculatingDuration()(this.parentTimegroup) ? void 0 : this.parentTimegroup?.durationMs;
363
+ const durationSource = determineDurationSource(this.intrinsicDurationMs, this._durationMs, parentDurationMs);
364
+ const modification = determineDurationModificationStrategy(this.trimStartMs, this.trimEndMs, this.sourceInMs, this.sourceOutMs);
365
+ return evaluateModifiedDuration(durationSource.baseDurationMs, modification);
222
366
  }
223
367
  get sourceStartMs() {
224
368
  return this.trimStartMs ?? this.sourceInMs ?? 0;
225
369
  }
226
- get offsetMs() {
370
+ #offsetMs() {
227
371
  return this._offsetMs || 0;
228
372
  }
229
- get parentTemporal() {
373
+ #parentTemporal() {
230
374
  let parent = this.parentElement;
231
375
  while (parent && !isEFTemporal(parent)) parent = parent.parentElement;
232
376
  return parent;
@@ -235,45 +379,17 @@ const EFTemporal = (superClass) => {
235
379
  * The start time of the element within its parent timegroup.
236
380
  */
237
381
  get startTimeWithinParentMs() {
238
- if (!this.parentTemporal) return 0;
239
- return this.startTimeMs - this.parentTemporal.startTimeMs;
382
+ const parent = this.#parentTemporal();
383
+ if (!parent) return 0;
384
+ return this.startTimeMs - parent.startTimeMs;
240
385
  }
241
386
  #loop = false;
242
387
  get startTimeMs() {
243
388
  const cachedStartTime = startTimeMsCache.get(this);
244
389
  if (cachedStartTime !== void 0) return cachedStartTime;
245
- const parentTimegroup = this.parentTimegroup;
246
- if (!parentTimegroup) {
247
- startTimeMsCache.set(this, 0);
248
- return 0;
249
- }
250
- switch (parentTimegroup.mode) {
251
- case "sequence": {
252
- const siblingTemorals = shallowGetTemporalElements(parentTimegroup);
253
- const ownIndex = siblingTemorals?.indexOf(this);
254
- if (ownIndex === -1) return 0;
255
- if (ownIndex === 0) {
256
- startTimeMsCache.set(this, parentTimegroup.startTimeMs);
257
- return parentTimegroup.startTimeMs;
258
- }
259
- const previous = siblingTemorals?.[(ownIndex ?? 0) - 1];
260
- if (!previous) {
261
- console.error("Previous temporal element not found", {
262
- ownIndex,
263
- siblingTemorals
264
- });
265
- throw new Error("Previous temporal element not found");
266
- }
267
- startTimeMsCache.set(this, previous.startTimeMs + previous.durationMs - parentTimegroup.overlapMs);
268
- return previous.startTimeMs + previous.durationMs - parentTimegroup.overlapMs;
269
- }
270
- case "fit":
271
- case "contain":
272
- case "fixed":
273
- startTimeMsCache.set(this, parentTimegroup.startTimeMs + this.offsetMs);
274
- return parentTimegroup.startTimeMs + this.offsetMs;
275
- default: throw new Error(`Invalid time mode: ${parentTimegroup.mode}`);
276
- }
390
+ const startTime = evaluateStartTime(this, this.parentTimegroup, this.#offsetMs(), (parent) => shallowGetTemporalElements(parent));
391
+ startTimeMsCache.set(this, startTime);
392
+ return startTime;
277
393
  }
278
394
  get endTimeMs() {
279
395
  return this.startTimeMs + this.durationMs;
@@ -284,9 +400,7 @@ const EFTemporal = (superClass) => {
284
400
  * Compare with `currentTimeMs` to see the current time with respect to the root timegroup
285
401
  */
286
402
  get ownCurrentTimeMs() {
287
- if (this.playbackController) return Math.min(Math.max(0, this.playbackController.currentTimeMs), this.durationMs);
288
- if (this.rootTimegroup && this.rootTimegroup !== this) return Math.min(Math.max(0, this.rootTimegroup.currentTimeMs - this.startTimeMs), this.durationMs);
289
- return Math.min(Math.max(0, this.#currentTimeMs), this.durationMs);
403
+ return determineCurrentTimeSource(this.playbackController, this.rootTimegroup, this.rootTimegroup === this, this.#currentTimeMs, this.startTimeMs, this.durationMs).timeMs;
290
404
  }
291
405
  /**
292
406
  * Element's current time for progress calculation.
@@ -296,14 +410,21 @@ const EFTemporal = (superClass) => {
296
410
  return this.ownCurrentTimeMs;
297
411
  }
298
412
  set currentTimeMs(value) {
299
- if (this.playbackController) {
300
- this.playbackController.currentTime = value / 1e3;
301
- return;
302
- }
303
- if (this.rootTimegroup && this.rootTimegroup !== this) this.rootTimegroup.currentTimeMs = value;
304
- else {
305
- this.#currentTimeMs = value;
306
- this.requestUpdate("currentTimeMs");
413
+ switch (determineTemporalRole(this.parentTimegroup)) {
414
+ case "root":
415
+ if (this.playbackController) this.playbackController.currentTime = value / 1e3;
416
+ else {
417
+ this.#currentTimeMs = value;
418
+ this.requestUpdate("currentTimeMs");
419
+ }
420
+ break;
421
+ case "child":
422
+ if (this.rootTimegroup && this.rootTimegroup !== this) this.rootTimegroup.currentTimeMs = value;
423
+ else {
424
+ this.#currentTimeMs = value;
425
+ this.requestUpdate("currentTimeMs");
426
+ }
427
+ break;
307
428
  }
308
429
  }
309
430
  /**
@@ -377,5 +498,5 @@ const EFTemporal = (superClass) => {
377
498
  };
378
499
 
379
500
  //#endregion
380
- export { EFTemporal, deepGetElementsWithFrameTasks, deepGetTemporalElements, flushStartTimeMsCache, isEFTemporal, resetTemporalCache, shallowGetTemporalElements, timegroupContext };
501
+ export { EFTemporal, deepGetElementsWithFrameTasks, deepGetTemporalElements, flushStartTimeMsCache, isEFTemporal, registerIsTimegroupCalculatingDuration, resetTemporalCache, shallowGetTemporalElements, timegroupContext };
381
502
  //# sourceMappingURL=EFTemporal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EFTemporal.js","names":["temporalCache: Map<Element, TemporalMixinInterface[]>","host: EFTimegroup","temporal: TemporalMixinInterface & LitElement","#parentTimegroup","#loop","#currentTimeMs"],"sources":["../../src/elements/EFTemporal.ts"],"sourcesContent":["import { consume, createContext } from \"@lit/context\";\nimport { Task } from \"@lit/task\";\nimport type { LitElement, ReactiveController } from \"lit\";\nimport { property, state } from \"lit/decorators.js\";\nimport { EF_INTERACTIVE } from \"../EF_INTERACTIVE.js\";\nimport { PlaybackController } from \"../gui/PlaybackController.js\";\nimport { durationConverter } from \"./durationConverter.js\";\nimport type { EFTimegroup } from \"./EFTimegroup.js\";\n\nexport const timegroupContext = createContext<EFTimegroup>(\n Symbol(\"timeGroupContext\"),\n);\n\nexport declare class TemporalMixinInterface {\n playbackController?: PlaybackController;\n playing: boolean;\n loop: boolean;\n play(): void;\n pause(): void;\n\n get hasOwnDuration(): boolean;\n /**\n * Whether the element has a duration set as an attribute.\n */\n get hasExplicitDuration(): boolean;\n\n get sourceStartMs(): number;\n\n /**\n * Used to trim the start of the media.\n *\n * This can be set in either seconds or milliseconds.\n *\n * For example, `trimstart=\"10s\"` is equivalent to `trimstart=\"10000ms\"`.\n *\n * @domAttribute \"trimstart\"\n */\n get trimStartMs(): number | undefined;\n\n /**\n * Used to trim the end of the media.\n *\n * This can be set in either seconds or milliseconds.\n *\n * For example, `trimend=\"10s\"` is equivalent to `trimend=\"10000ms\"`.\n *\n * @domAttribute \"trimend\"\n */\n get trimEndMs(): number;\n\n set trimStartMs(value: number | undefined);\n set trimEndMs(value: number | undefined);\n set trimstart(value: string | undefined);\n set trimend(value: string | undefined);\n\n /**\n * The source in time of the element.\n *\n * This is an amount of time to trim off the beginning of the media.\n *\n * This can be set in either seconds or milliseconds.\n *\n * For example, `sourcein=\"10s\"` is equivalent to `sourcein=\"10000ms\"`.\n *\n * If the sourcein time is greater than the duration of the media, the media\n * will not be played.\n *\n * If the media is 20 seconds long, and the `sourcein` value is set to `10s`, the\n * media will play for 10 seconds, starting at the 10 second mark.\n *\n * Can be used in conjunction with `sourceout` to create a trimmed media.\n *\n * @domAttribute \"sourcein\"\n */\n get sourceInMs(): number | undefined;\n\n /**\n * The source out time of the element.\n *\n * This is the point in time in the media that will be treated as the end of\n * the media.\n *\n * This can be set in either seconds or milliseconds.\n *\n * For example, `sourceout=\"10s\"` is equivalent to `sourceout=\"10000ms\"`.\n *\n * If the sourceout time is greater than the duration of the media, the media\n * will play until the end of the media.\n *\n * If the media is 20 seconds long, and the `sourceout` value is set to `10s`,\n * the media will play for 10 seconds, starting at zero seconds and ending at\n * the 10 second mark.\n *\n * Can be used in conjunction with `sourcein` to create a trimmed media.\n *\n * @domAttribute \"sourceout\"\n */\n get sourceOutMs(): number | undefined;\n\n set sourceInMs(value: number | undefined);\n set sourceOutMs(value: number | undefined);\n set sourcein(value: string | undefined);\n set sourceout(value: string | undefined);\n\n /**\n * @domAttribute \"duration\"\n */\n get durationMs(): number;\n\n get explicitDurationMs(): number | undefined;\n\n get intrinsicDurationMs(): number | undefined;\n\n /**\n * The start time of the element within its root timegroup in milliseconds.\n *\n * This is an absolute time according to the highest scoped timegroup the media element is contained within.\n *\n * The calculated value will depend on the mode of the timegroup and the offset of the media element.\n *\n * If the parent time group is in `sequence` mode, the start time will be the\n * start time of the previous sibling element plus the previous sibling's duration\n * minus the overlap of the previous sibling and the current sibling.\n *\n * If the parent time group is in `contain` or `fixed` mode, the start time will be\n * the start time of the parent time group plus the offset of the media element.\n */\n get startTimeMs(): number;\n /**\n * The end time of the element within its root timegroup in milliseconds.\n *\n * This is an absolute time according to the highest scoped timegroup the media\n * element is contained within. Computed by adding the media's duration to its\n * start time.\n *\n * If the media element has been trimmed, its end time will be calculated according it\n * its trimmed duration, not its original duration.\n */\n get endTimeMs(): number;\n /**\n * The start time of the element within its parent timegroup in milliseconds.\n *\n * This is a relative time according to the closest timegroup the media element\n * is contained within. Unless the media element has been given any kind of specific offset\n * it is common for this time to be zero.\n */\n get startTimeWithinParentMs(): number;\n\n /**\n * The current time of the element in milliseconds.\n *\n * This is a relative time according to the closest timegroup the media element\n * is contained within.\n *\n * This is suitable for determining the percentage of the media that has been\n * played.\n */\n get ownCurrentTimeMs(): number;\n\n /**\n * Element's current time for progress calculation.\n * For timegroups: their timeline currentTimeMs\n * For other temporal elements: their ownCurrentTimeMs\n */\n get currentTimeMs(): number;\n set currentTimeMs(value: number);\n /**\n * The current time of the element in milliseconds, adjusted for trimming.\n *\n * This is suitable for mapping to internal media time codes for audio/video\n * elements.\n *\n * For example, if the media has a `sourcein` value of 10s, when `ownCurrentTimeMs` is 0s,\n * `currentSourceTimeMs` will be 10s.\n *\n * sourcein=10s sourceout=10s\n * / / /\n * |--------|=================|---------|\n * ^\n * |_\n * currentSourceTimeMs === 10s\n * |_\n * ownCurrentTimeMs === 0s\n */\n get currentSourceTimeMs(): number;\n\n set duration(value: string);\n get duration(): string;\n\n /**\n * The offset of the element within its parent timegroup in milliseconds.\n *\n * This can be set in either seconds or milliseconds.\n *\n * For example, `offset=\"10s\"` is equivalent to `offset=\"10000ms\"`.\n *\n * This can be used to create a negative or positive offset for the start time of the media.\n *\n * This will change the start time of the media relative to it's otherwise normal start time.\n *\n * The duration of the element, or it's parent, or the start and end time of it's temporal siblings will not\n * be affected by this offset.\n *\n * @domAttribute \"offset\"\n */\n set offset(value: string);\n get offset(): string;\n\n /**\n * A convenience property for getting the nearest containing timegroup of the media element.\n */\n parentTimegroup?: EFTimegroup;\n\n /**\n * A convenience property for getting the root timegroup of the media element.\n */\n rootTimegroup?: EFTimegroup;\n\n frameTask: Task<readonly unknown[], unknown>;\n\n didBecomeRoot(): void;\n didBecomeChild(): void;\n\n updateComplete: Promise<boolean>;\n}\n\nexport const isEFTemporal = (obj: any): obj is TemporalMixinInterface =>\n obj[EF_TEMPORAL];\n\nconst EF_TEMPORAL = Symbol(\"EF_TEMPORAL\");\n\nexport const deepGetTemporalElements = (\n element: Element,\n temporals: Array<TemporalMixinInterface & HTMLElement> = [],\n) => {\n for (const child of element.children) {\n if (isEFTemporal(child)) {\n temporals.push(child as TemporalMixinInterface & HTMLElement);\n }\n deepGetTemporalElements(child, temporals);\n }\n return temporals;\n};\n\nexport const deepGetElementsWithFrameTasks = (\n element: Element,\n elements: Array<TemporalMixinInterface & HTMLElement> = [],\n) => {\n for (const child of element.children) {\n if (\"frameTask\" in child && child.frameTask instanceof Task) {\n elements.push(child as TemporalMixinInterface & HTMLElement);\n }\n deepGetElementsWithFrameTasks(child, elements);\n }\n return elements;\n};\n\nlet temporalCache: Map<Element, TemporalMixinInterface[]>;\nlet temporalCacheResetScheduled = false;\nexport const resetTemporalCache = () => {\n temporalCache = new Map();\n if (\n typeof requestAnimationFrame !== \"undefined\" &&\n !temporalCacheResetScheduled\n ) {\n temporalCacheResetScheduled = true;\n requestAnimationFrame(() => {\n temporalCacheResetScheduled = false;\n resetTemporalCache();\n });\n }\n};\nresetTemporalCache();\n\nexport const shallowGetTemporalElements = (\n element: Element,\n temporals: TemporalMixinInterface[] = [],\n) => {\n const cachedResult = temporalCache.get(element);\n if (cachedResult) {\n return cachedResult;\n }\n for (const child of element.children) {\n if (isEFTemporal(child)) {\n temporals.push(child);\n } else {\n shallowGetTemporalElements(child, temporals);\n }\n }\n temporalCache.set(element, temporals);\n return temporals;\n};\n\nexport class OwnCurrentTimeController implements ReactiveController {\n constructor(\n private host: EFTimegroup,\n private temporal: TemporalMixinInterface & LitElement,\n ) {\n host.addController(this);\n }\n\n hostUpdated() {\n this.temporal.requestUpdate(\"ownCurrentTimeMs\");\n }\n\n remove() {\n this.host.removeController(this);\n }\n}\n\ntype Constructor<T = {}> = new (...args: any[]) => T;\n\nlet startTimeMsCache = new WeakMap<Element, number>();\nlet startTimeMsCacheResetScheduled = false;\nconst resetStartTimeMsCache = () => {\n startTimeMsCache = new WeakMap();\n if (\n typeof requestAnimationFrame !== \"undefined\" &&\n !startTimeMsCacheResetScheduled\n ) {\n startTimeMsCacheResetScheduled = true;\n requestAnimationFrame(() => {\n startTimeMsCacheResetScheduled = false;\n resetStartTimeMsCache();\n });\n }\n};\nresetStartTimeMsCache();\n\nexport const flushStartTimeMsCache = () => {\n startTimeMsCache = new WeakMap();\n};\n\nexport const EFTemporal = <T extends Constructor<LitElement>>(\n superClass: T,\n) => {\n class TemporalMixinClass extends superClass {\n ownCurrentTimeController?: OwnCurrentTimeController;\n\n #parentTimegroup?: EFTimegroup;\n @consume({ context: timegroupContext, subscribe: true })\n set parentTimegroup(value: EFTimegroup | undefined) {\n const oldParent = this.#parentTimegroup;\n this.#parentTimegroup = value;\n\n this.ownCurrentTimeController?.remove();\n this.rootTimegroup = this.getRootTimegroup();\n if (this.rootTimegroup) {\n this.ownCurrentTimeController = new OwnCurrentTimeController(\n this.rootTimegroup,\n this as InstanceType<Constructor<TemporalMixinInterface> & T>,\n );\n }\n\n // Only trigger callbacks if parent status actually changed\n if (oldParent !== value) {\n if (!value) {\n this.didBecomeRoot();\n } else {\n this.didBecomeChild();\n }\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.ownCurrentTimeController?.remove();\n\n if (this.playbackController) {\n this.playbackController.remove();\n this.playbackController = undefined;\n }\n }\n\n connectedCallback() {\n super.connectedCallback();\n // Initialize playback controller for root elements\n // The parentTimegroup setter may have already called this, but the guard prevents double-creation\n if (!this.parentTimegroup) {\n this.didBecomeRoot();\n }\n }\n\n get parentTimegroup() {\n return this.#parentTimegroup;\n }\n\n playbackController?: PlaybackController;\n\n get playing(): boolean {\n if (!this.playbackController) {\n return false;\n }\n return this.playbackController.playing;\n }\n\n set playing(value: boolean) {\n if (!this.playbackController) {\n console.warn(\"Cannot set playing on non-root temporal element\", this);\n return;\n }\n this.playbackController.setPlaying(value);\n }\n\n play(): void {\n if (!this.playbackController) {\n console.warn(\"play() called on non-root temporal element\", this);\n return;\n }\n this.playbackController.play();\n }\n\n pause(): void {\n if (!this.playbackController) {\n console.warn(\"pause() called on non-root temporal element\", this);\n return;\n }\n this.playbackController.pause();\n }\n\n @property({ type: Boolean, reflect: true, attribute: \"loop\" })\n get loop(): boolean {\n return this.playbackController?.loop ?? this.#loop;\n }\n\n set loop(value: boolean) {\n const oldValue = this.#loop;\n this.#loop = value;\n if (this.playbackController) {\n this.playbackController.setLoop(value);\n }\n this.requestUpdate(\"loop\", oldValue);\n }\n\n @property({\n type: String,\n attribute: \"offset\",\n converter: durationConverter,\n })\n private _offsetMs = 0;\n\n @property({\n type: Number,\n attribute: \"duration\",\n converter: durationConverter,\n })\n private _durationMs?: number;\n\n set duration(value: string | undefined) {\n if (value !== undefined) {\n this.setAttribute(\"duration\", value);\n } else {\n this.removeAttribute(\"duration\");\n }\n }\n\n @property({\n type: Number,\n attribute: \"trimstart\",\n converter: durationConverter,\n })\n _trimStartMs: number | undefined = undefined;\n\n get trimStartMs() {\n if (this._trimStartMs === undefined) {\n return undefined;\n }\n return Math.min(\n Math.max(this._trimStartMs, 0),\n this.intrinsicDurationMs ?? 0,\n );\n }\n\n set trimStartMs(value: number | undefined) {\n this._trimStartMs = value;\n }\n\n @property({\n type: Number,\n attribute: \"trimend\",\n converter: durationConverter,\n })\n _trimEndMs: number | undefined = undefined;\n\n get trimEndMs() {\n if (this._trimEndMs === undefined) {\n return undefined;\n }\n return Math.min(this._trimEndMs, this.intrinsicDurationMs ?? 0);\n }\n\n set trimEndMs(value: number | undefined) {\n this._trimEndMs = value;\n }\n\n @property({\n type: Number,\n attribute: \"sourcein\",\n converter: durationConverter,\n })\n _sourceInMs: number | undefined = undefined;\n\n get sourceInMs() {\n if (this._sourceInMs === undefined) {\n return undefined;\n }\n return Math.max(this._sourceInMs, 0);\n }\n\n set sourceInMs(value: number | undefined) {\n this._sourceInMs = value;\n }\n\n @property({\n type: Number,\n attribute: \"sourceout\",\n converter: durationConverter,\n })\n _sourceOutMs: number | undefined = undefined;\n\n get sourceOutMs() {\n if (this._sourceOutMs === undefined) {\n return undefined;\n }\n if (\n this.intrinsicDurationMs &&\n this._sourceOutMs > this.intrinsicDurationMs\n ) {\n return this.intrinsicDurationMs;\n }\n return Math.max(this._sourceOutMs, 0);\n }\n\n set sourceOutMs(value: number | undefined) {\n this._sourceOutMs = value;\n }\n\n @property({\n type: Number,\n attribute: \"startoffset\",\n converter: durationConverter,\n })\n private _startOffsetMs = 0;\n public get startOffsetMs(): number {\n return this._startOffsetMs;\n }\n\n @state()\n rootTimegroup?: EFTimegroup = this.getRootTimegroup();\n\n private getRootTimegroup(): EFTimegroup | undefined {\n let parent =\n this.tagName === \"EF-TIMEGROUP\" ? this : this.parentTimegroup;\n while (parent?.parentTimegroup) {\n parent = parent.parentTimegroup;\n }\n return parent as EFTimegroup | undefined;\n }\n\n get hasExplicitDuration() {\n return this._durationMs !== undefined;\n }\n\n get explicitDurationMs() {\n if (this.hasExplicitDuration) {\n return this._durationMs;\n }\n return undefined;\n }\n\n get hasOwnDuration() {\n return this.intrinsicDurationMs !== undefined || this.hasExplicitDuration;\n }\n\n get intrinsicDurationMs() {\n return undefined;\n }\n\n get durationMs() {\n // Get the base duration - either intrinsic or explicit\n const baseDurationMs =\n this.intrinsicDurationMs ??\n this._durationMs ??\n this.parentTimegroup?.durationMs ??\n 0;\n\n if (baseDurationMs === 0) {\n return 0;\n }\n\n // Apply trimming logic to any duration source\n if (this.trimStartMs || this.trimEndMs) {\n const trimmedDurationMs =\n baseDurationMs - (this.trimStartMs ?? 0) - (this.trimEndMs ?? 0);\n if (trimmedDurationMs < 0) {\n return 0;\n }\n return trimmedDurationMs;\n }\n\n if (this.sourceInMs || this.sourceOutMs) {\n const sourceInMs = this.sourceInMs ?? 0;\n const sourceOutMs = this.sourceOutMs ?? baseDurationMs;\n if (sourceInMs >= sourceOutMs) {\n return 0;\n }\n return sourceOutMs - sourceInMs;\n }\n\n return baseDurationMs;\n }\n\n get sourceStartMs() {\n return this.trimStartMs ?? this.sourceInMs ?? 0;\n }\n\n get offsetMs() {\n return this._offsetMs || 0;\n }\n\n get parentTemporal() {\n let parent = this.parentElement;\n while (parent && !isEFTemporal(parent)) {\n parent = parent.parentElement;\n }\n return parent;\n }\n\n /**\n * The start time of the element within its parent timegroup.\n */\n get startTimeWithinParentMs() {\n if (!this.parentTemporal) {\n return 0;\n }\n return this.startTimeMs - this.parentTemporal.startTimeMs;\n }\n\n #loop = false;\n\n get startTimeMs(): number {\n const cachedStartTime = startTimeMsCache.get(this);\n if (cachedStartTime !== undefined) {\n return cachedStartTime;\n }\n const parentTimegroup = this.parentTimegroup;\n if (!parentTimegroup) {\n startTimeMsCache.set(this, 0);\n return 0;\n }\n switch (parentTimegroup.mode) {\n case \"sequence\": {\n const siblingTemorals = shallowGetTemporalElements(parentTimegroup);\n const ownIndex = siblingTemorals?.indexOf(\n this as InstanceType<Constructor<TemporalMixinInterface> & T>,\n );\n if (ownIndex === -1) {\n return 0;\n }\n if (ownIndex === 0) {\n startTimeMsCache.set(this, parentTimegroup.startTimeMs);\n return parentTimegroup.startTimeMs;\n }\n const previous = siblingTemorals?.[(ownIndex ?? 0) - 1];\n if (!previous) {\n console.error(\"Previous temporal element not found\", {\n ownIndex,\n siblingTemorals,\n });\n throw new Error(\"Previous temporal element not found\");\n }\n startTimeMsCache.set(\n this,\n previous.startTimeMs +\n previous.durationMs -\n parentTimegroup.overlapMs,\n );\n return (\n previous.startTimeMs +\n previous.durationMs -\n parentTimegroup.overlapMs\n );\n }\n case \"fit\":\n case \"contain\":\n case \"fixed\":\n startTimeMsCache.set(\n this,\n parentTimegroup.startTimeMs + this.offsetMs,\n );\n return parentTimegroup.startTimeMs + this.offsetMs;\n default:\n throw new Error(`Invalid time mode: ${parentTimegroup.mode}`);\n }\n }\n\n get endTimeMs(): number {\n return this.startTimeMs + this.durationMs;\n }\n\n #currentTimeMs = 0;\n\n /**\n * The current time of the element within itself.\n * Compare with `currentTimeMs` to see the current time with respect to the root timegroup\n */\n get ownCurrentTimeMs(): number {\n // If we have a playback controller, read from it\n if (this.playbackController) {\n return Math.min(\n Math.max(0, this.playbackController.currentTimeMs),\n this.durationMs,\n );\n }\n\n if (\n this.rootTimegroup &&\n this.rootTimegroup !== (this as any as EFTimegroup)\n ) {\n return Math.min(\n Math.max(0, this.rootTimegroup.currentTimeMs - this.startTimeMs),\n this.durationMs,\n );\n }\n // We are the root (or no root), use stored time\n return Math.min(Math.max(0, this.#currentTimeMs), this.durationMs);\n }\n\n /**\n * Element's current time for progress calculation.\n * Non-timegroup temporal elements use their local time (ownCurrentTimeMs)\n */\n get currentTimeMs() {\n return this.ownCurrentTimeMs;\n }\n\n set currentTimeMs(value: number) {\n // If we have a playback controller, delegate to it\n if (this.playbackController) {\n this.playbackController.currentTime = value / 1000;\n return;\n }\n\n // If we have a root timegroup, delegate to it\n if (\n this.rootTimegroup &&\n this.rootTimegroup !== (this as any as EFTimegroup)\n ) {\n this.rootTimegroup.currentTimeMs = value;\n } else {\n // We are the root, store the time locally\n this.#currentTimeMs = value;\n this.requestUpdate(\"currentTimeMs\");\n }\n }\n\n /**\n * Used to calculate the internal currentTimeMs of the element. This is useful\n * for mapping to internal media time codes for audio/video elements.\n */\n get currentSourceTimeMs() {\n const leadingTrimMs = this.sourceInMs || this.trimStartMs || 0;\n return this.ownCurrentTimeMs + leadingTrimMs;\n }\n\n frameTask = new Task(this, {\n autoRun: EF_INTERACTIVE,\n args: () => [this.ownCurrentTimeMs] as const,\n task: async ([], { signal: _signal }) => {\n let fullyUpdated = await this.updateComplete;\n while (!fullyUpdated) {\n fullyUpdated = await this.updateComplete;\n }\n },\n });\n\n didBecomeRoot() {\n if (!this.playbackController) {\n this.playbackController = new PlaybackController(this as any);\n if (this.#loop) {\n this.playbackController.setLoop(this.#loop);\n }\n }\n }\n\n didBecomeChild() {\n if (this.playbackController) {\n this.playbackController.remove();\n this.playbackController = undefined;\n }\n }\n }\n\n Object.defineProperty(TemporalMixinClass.prototype, EF_TEMPORAL, {\n value: true,\n });\n\n return TemporalMixinClass as unknown as Constructor<TemporalMixinInterface> &\n T;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"EFTemporal.js","names":["isTimegroupCalculatingDurationFn:\n | ((timegroup: EFTimegroup | undefined) => boolean)\n | null","fallbackFn: (timegroup: EFTimegroup | undefined) => boolean","temporalCache: Map<Element, TemporalMixinInterface[]>","host: EFTimegroup","temporal: TemporalMixinInterface & LitElement","#lastKnownTimeMs","#parentTimegroup","#ownCurrentTimeController","#rootTimegroupLocked","#loop","#parentTemporal","#offsetMs","#currentTimeMs"],"sources":["../../src/elements/EFTemporal.ts"],"sourcesContent":["import { consume, createContext } from \"@lit/context\";\nimport { Task } from \"@lit/task\";\nimport type { LitElement, ReactiveController } from \"lit\";\nimport { property, state } from \"lit/decorators.js\";\nimport { EF_INTERACTIVE } from \"../EF_INTERACTIVE.js\";\nimport { PlaybackController } from \"../gui/PlaybackController.js\";\nimport { durationConverter } from \"./durationConverter.js\";\nimport type { EFTimegroup } from \"./EFTimegroup.js\";\n// Lazy import to break circular dependency: EFTemporal -> EFTimegroup -> EFMedia -> EFTemporal\n// isTimegroupCalculatingDuration is only used at runtime in a getter, so we can import it lazily\n// Use a module-level variable that gets set when EFTimegroup module loads\nlet isTimegroupCalculatingDurationFn:\n | ((timegroup: EFTimegroup | undefined) => boolean)\n | null = null;\n\n// This function will be called by EFTimegroup when it loads to register the function\nexport const registerIsTimegroupCalculatingDuration = (\n fn: (timegroup: EFTimegroup | undefined) => boolean,\n) => {\n isTimegroupCalculatingDurationFn = fn;\n};\n\nconst getIsTimegroupCalculatingDuration = (): ((\n timegroup: EFTimegroup | undefined,\n) => boolean) => {\n if (isTimegroupCalculatingDurationFn) {\n return isTimegroupCalculatingDurationFn as (\n timegroup: EFTimegroup | undefined,\n ) => boolean;\n }\n\n // If not registered yet, try to import synchronously (only works if module is already loaded)\n // This is a fallback for cases where EFTimegroup hasn't called registerIsTimegroupCalculatingDuration\n // In practice, EFTimegroup will call registerIsTimegroupCalculatingDuration when it loads\n let fallbackFn: (timegroup: EFTimegroup | undefined) => boolean = () => false;\n try {\n // Access the function via a global or try to get it from the module cache\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const efTimegroupModule = (globalThis as any).__EFTimegroupModule;\n if (efTimegroupModule?.isTimegroupCalculatingDuration) {\n fallbackFn = efTimegroupModule.isTimegroupCalculatingDuration;\n }\n } catch {\n // Use default fallback\n }\n isTimegroupCalculatingDurationFn = fallbackFn;\n return fallbackFn;\n};\n\nexport const timegroupContext = createContext<EFTimegroup>(\n Symbol(\"timeGroupContext\"),\n);\n\n// ============================================================================\n// Core Concept 1: Temporal Role\n// ============================================================================\n// A temporal element is either a root (controls its own playback) or a child\n// (delegates playback to its root timegroup). This is the fundamental invariant.\n// ============================================================================\n\ntype TemporalRole = \"root\" | \"child\";\n\nfunction determineTemporalRole(\n parentTimegroup: EFTimegroup | undefined,\n): TemporalRole {\n return parentTimegroup === undefined ? \"root\" : \"child\";\n}\n\n// ============================================================================\n// Core Concept 2: Duration Source\n// ============================================================================\n// Duration comes from one of three sources: intrinsic (media-based),\n// explicit (attribute), or inherited (from parent). This determines the base\n// duration before any modifications.\n// ============================================================================\n\ntype DurationSource = \"intrinsic\" | \"explicit\" | \"inherited\";\n\ninterface DurationSourceResult {\n source: DurationSource;\n baseDurationMs: number;\n}\n\nfunction determineDurationSource(\n intrinsicDurationMs: number | undefined,\n explicitDurationMs: number | undefined,\n parentDurationMs: number | undefined,\n): DurationSourceResult {\n if (intrinsicDurationMs !== undefined) {\n return { source: \"intrinsic\", baseDurationMs: intrinsicDurationMs };\n }\n if (explicitDurationMs !== undefined) {\n return { source: \"explicit\", baseDurationMs: explicitDurationMs };\n }\n if (parentDurationMs !== undefined) {\n return { source: \"inherited\", baseDurationMs: parentDurationMs };\n }\n return { source: \"inherited\", baseDurationMs: 0 };\n}\n\n// ============================================================================\n// Core Concept 3: Duration Modification Strategy\n// ============================================================================\n// Duration can be modified by trimming (removing from edges) or source\n// manipulation (selecting a portion of the source). These are mutually\n// exclusive strategies.\n// ============================================================================\n\ntype DurationModificationStrategy = \"none\" | \"trimming\" | \"source-manipulation\";\n\ninterface DurationModificationState {\n strategy: DurationModificationStrategy;\n trimStartMs: number | undefined;\n trimEndMs: number | undefined;\n sourceInMs: number | undefined;\n sourceOutMs: number | undefined;\n}\n\nfunction determineDurationModificationStrategy(\n trimStartMs: number | undefined,\n trimEndMs: number | undefined,\n sourceInMs: number | undefined,\n sourceOutMs: number | undefined,\n): DurationModificationState {\n if (trimStartMs !== undefined || trimEndMs !== undefined) {\n return {\n strategy: \"trimming\",\n trimStartMs,\n trimEndMs,\n sourceInMs: undefined,\n sourceOutMs: undefined,\n };\n }\n if (sourceInMs !== undefined || sourceOutMs !== undefined) {\n return {\n strategy: \"source-manipulation\",\n trimStartMs: undefined,\n trimEndMs: undefined,\n sourceInMs,\n sourceOutMs,\n };\n }\n return {\n strategy: \"none\",\n trimStartMs: undefined,\n trimEndMs: undefined,\n sourceInMs: undefined,\n sourceOutMs: undefined,\n };\n}\n\nfunction evaluateModifiedDuration(\n baseDurationMs: number,\n modification: DurationModificationState,\n): number {\n if (baseDurationMs === 0) {\n return 0;\n }\n\n switch (modification.strategy) {\n case \"trimming\": {\n const trimmedDurationMs =\n baseDurationMs -\n (modification.trimStartMs ?? 0) -\n (modification.trimEndMs ?? 0);\n return Math.max(0, trimmedDurationMs);\n }\n case \"source-manipulation\": {\n const sourceInMs = modification.sourceInMs ?? 0;\n const sourceOutMs = modification.sourceOutMs ?? baseDurationMs;\n if (sourceInMs >= sourceOutMs) {\n return 0;\n }\n return sourceOutMs - sourceInMs;\n }\n case \"none\":\n return baseDurationMs;\n }\n}\n\n// ============================================================================\n// Core Concept 4: Start Time Calculation Strategy\n// ============================================================================\n// Start time is calculated differently based on parent timegroup mode:\n// - Sequence mode: based on previous sibling\n// - Other modes: based on parent start + offset\n// ============================================================================\n\ntype StartTimeStrategy = \"sequence\" | \"offset\";\n\nfunction determineStartTimeStrategy(\n parentTimegroup: EFTimegroup | undefined,\n): StartTimeStrategy {\n if (!parentTimegroup) {\n return \"offset\";\n }\n return parentTimegroup.mode === \"sequence\" ? \"sequence\" : \"offset\";\n}\n\nfunction evaluateStartTimeForSequence(\n _element: TemporalMixinInterface & HTMLElement,\n parentTimegroup: EFTimegroup,\n siblingTemporals: TemporalMixinInterface[],\n ownIndex: number,\n): number {\n if (ownIndex === 0) {\n return parentTimegroup.startTimeMs;\n }\n const previous = siblingTemporals[ownIndex - 1];\n if (!previous) {\n throw new Error(\"Previous temporal element not found\");\n }\n return previous.startTimeMs + previous.durationMs - parentTimegroup.overlapMs;\n}\n\nfunction evaluateStartTimeForOffset(\n parentTimegroup: EFTimegroup,\n offsetMs: number,\n): number {\n return parentTimegroup.startTimeMs + offsetMs;\n}\n\nfunction evaluateStartTime(\n element: TemporalMixinInterface & HTMLElement,\n parentTimegroup: EFTimegroup | undefined,\n offsetMs: number,\n getSiblingTemporals: (parent: EFTimegroup) => TemporalMixinInterface[],\n): number {\n if (!parentTimegroup) {\n return 0;\n }\n\n const strategy = determineStartTimeStrategy(parentTimegroup);\n switch (strategy) {\n case \"sequence\": {\n const siblingTemporals = getSiblingTemporals(parentTimegroup);\n const ownIndex = siblingTemporals.indexOf(element);\n if (ownIndex === -1) {\n return 0;\n }\n return evaluateStartTimeForSequence(\n element,\n parentTimegroup,\n siblingTemporals,\n ownIndex,\n );\n }\n case \"offset\":\n return evaluateStartTimeForOffset(parentTimegroup, offsetMs);\n }\n}\n\n// ============================================================================\n// Core Concept 5: Current Time Source\n// ============================================================================\n// Current time comes from one of three sources: playback controller (root\n// elements), root timegroup (child elements), or local storage (fallback).\n// ============================================================================\n\ntype CurrentTimeSource = \"playback-controller\" | \"root-timegroup\" | \"local\";\n\ninterface CurrentTimeSourceResult {\n source: CurrentTimeSource;\n timeMs: number;\n}\n\nfunction determineCurrentTimeSource(\n playbackController: PlaybackController | undefined,\n rootTimegroup: EFTimegroup | undefined,\n isRootTimegroup: boolean,\n localTimeMs: number,\n startTimeMs: number,\n durationMs: number,\n): CurrentTimeSourceResult {\n if (playbackController) {\n const timeMs = Math.min(\n Math.max(0, playbackController.currentTimeMs),\n durationMs,\n );\n return { source: \"playback-controller\", timeMs };\n }\n\n if (rootTimegroup && !isRootTimegroup) {\n const timeMs = Math.min(\n Math.max(0, rootTimegroup.currentTimeMs - startTimeMs),\n durationMs,\n );\n return { source: \"root-timegroup\", timeMs };\n }\n\n const timeMs = Math.min(Math.max(0, localTimeMs), durationMs);\n return { source: \"local\", timeMs };\n}\n\nexport declare class TemporalMixinInterface {\n playbackController?: PlaybackController;\n playing: boolean;\n loop: boolean;\n play(): void;\n pause(): void;\n\n get hasOwnDuration(): boolean;\n /**\n * Whether the element has a duration set as an attribute.\n */\n get hasExplicitDuration(): boolean;\n\n get sourceStartMs(): number;\n\n /**\n * Used to trim the start of the media.\n *\n * This can be set in either seconds or milliseconds.\n *\n * For example, `trimstart=\"10s\"` is equivalent to `trimstart=\"10000ms\"`.\n *\n * @domAttribute \"trimstart\"\n */\n get trimStartMs(): number | undefined;\n\n /**\n * Used to trim the end of the media.\n *\n * This can be set in either seconds or milliseconds.\n *\n * For example, `trimend=\"10s\"` is equivalent to `trimend=\"10000ms\"`.\n *\n * @domAttribute \"trimend\"\n */\n get trimEndMs(): number;\n\n set trimStartMs(value: number | undefined);\n set trimEndMs(value: number | undefined);\n set trimstart(value: string | undefined);\n set trimend(value: string | undefined);\n\n /**\n * The source in time of the element.\n *\n * This is an amount of time to trim off the beginning of the media.\n *\n * This can be set in either seconds or milliseconds.\n *\n * For example, `sourcein=\"10s\"` is equivalent to `sourcein=\"10000ms\"`.\n *\n * If the sourcein time is greater than the duration of the media, the media\n * will not be played.\n *\n * If the media is 20 seconds long, and the `sourcein` value is set to `10s`, the\n * media will play for 10 seconds, starting at the 10 second mark.\n *\n * Can be used in conjunction with `sourceout` to create a trimmed media.\n *\n * @domAttribute \"sourcein\"\n */\n get sourceInMs(): number | undefined;\n\n /**\n * The source out time of the element.\n *\n * This is the point in time in the media that will be treated as the end of\n * the media.\n *\n * This can be set in either seconds or milliseconds.\n *\n * For example, `sourceout=\"10s\"` is equivalent to `sourceout=\"10000ms\"`.\n *\n * If the sourceout time is greater than the duration of the media, the media\n * will play until the end of the media.\n *\n * If the media is 20 seconds long, and the `sourceout` value is set to `10s`,\n * the media will play for 10 seconds, starting at zero seconds and ending at\n * the 10 second mark.\n *\n * Can be used in conjunction with `sourcein` to create a trimmed media.\n *\n * @domAttribute \"sourceout\"\n */\n get sourceOutMs(): number | undefined;\n\n set sourceInMs(value: number | undefined);\n set sourceOutMs(value: number | undefined);\n set sourcein(value: string | undefined);\n set sourceout(value: string | undefined);\n\n /**\n * @domAttribute \"duration\"\n */\n get durationMs(): number;\n\n get explicitDurationMs(): number | undefined;\n\n get intrinsicDurationMs(): number | undefined;\n\n /**\n * The start time of the element within its root timegroup in milliseconds.\n *\n * This is an absolute time according to the highest scoped timegroup the media element is contained within.\n *\n * The calculated value will depend on the mode of the timegroup and the offset of the media element.\n *\n * If the parent time group is in `sequence` mode, the start time will be the\n * start time of the previous sibling element plus the previous sibling's duration\n * minus the overlap of the previous sibling and the current sibling.\n *\n * If the parent time group is in `contain` or `fixed` mode, the start time will be\n * the start time of the parent time group plus the offset of the media element.\n */\n get startTimeMs(): number;\n /**\n * The end time of the element within its root timegroup in milliseconds.\n *\n * This is an absolute time according to the highest scoped timegroup the media\n * element is contained within. Computed by adding the media's duration to its\n * start time.\n *\n * If the media element has been trimmed, its end time will be calculated according it\n * its trimmed duration, not its original duration.\n */\n get endTimeMs(): number;\n /**\n * The start time of the element within its parent timegroup in milliseconds.\n *\n * This is a relative time according to the closest timegroup the media element\n * is contained within. Unless the media element has been given any kind of specific offset\n * it is common for this time to be zero.\n */\n get startTimeWithinParentMs(): number;\n\n /**\n * The current time of the element in milliseconds.\n *\n * This is a relative time according to the closest timegroup the media element\n * is contained within.\n *\n * This is suitable for determining the percentage of the media that has been\n * played.\n */\n get ownCurrentTimeMs(): number;\n\n /**\n * Element's current time for progress calculation.\n * For timegroups: their timeline currentTimeMs\n * For other temporal elements: their ownCurrentTimeMs\n */\n get currentTimeMs(): number;\n set currentTimeMs(value: number);\n /**\n * The current time of the element in milliseconds, adjusted for trimming.\n *\n * This is suitable for mapping to internal media time codes for audio/video\n * elements.\n *\n * For example, if the media has a `sourcein` value of 10s, when `ownCurrentTimeMs` is 0s,\n * `currentSourceTimeMs` will be 10s.\n *\n * sourcein=10s sourceout=10s\n * / / /\n * |--------|=================|---------|\n * ^\n * |_\n * currentSourceTimeMs === 10s\n * |_\n * ownCurrentTimeMs === 0s\n */\n get currentSourceTimeMs(): number;\n\n set duration(value: string);\n get duration(): string;\n\n /**\n * The offset of the element within its parent timegroup in milliseconds.\n *\n * This can be set in either seconds or milliseconds.\n *\n * For example, `offset=\"10s\"` is equivalent to `offset=\"10000ms\"`.\n *\n * This can be used to create a negative or positive offset for the start time of the media.\n *\n * This will change the start time of the media relative to it's otherwise normal start time.\n *\n * The duration of the element, or it's parent, or the start and end time of it's temporal siblings will not\n * be affected by this offset.\n *\n * @domAttribute \"offset\"\n */\n set offset(value: string);\n get offset(): string;\n\n /**\n * A convenience property for getting the nearest containing timegroup of the media element.\n */\n parentTimegroup?: EFTimegroup;\n\n /**\n * A convenience property for getting the root timegroup of the media element.\n */\n rootTimegroup?: EFTimegroup;\n\n frameTask: Task<readonly unknown[], unknown>;\n\n didBecomeRoot(): void;\n didBecomeChild(): void;\n\n updateComplete: Promise<boolean>;\n}\n\nexport const isEFTemporal = (obj: any): obj is TemporalMixinInterface =>\n obj[EF_TEMPORAL];\n\nconst EF_TEMPORAL = Symbol(\"EF_TEMPORAL\");\n\nexport const deepGetTemporalElements = (\n element: Element,\n temporals: Array<TemporalMixinInterface & HTMLElement> = [],\n) => {\n for (const child of element.children) {\n if (isEFTemporal(child)) {\n temporals.push(child as TemporalMixinInterface & HTMLElement);\n }\n deepGetTemporalElements(child, temporals);\n }\n return temporals;\n};\n\nexport const deepGetElementsWithFrameTasks = (\n element: Element,\n elements: Array<TemporalMixinInterface & HTMLElement> = [],\n) => {\n for (const child of element.children) {\n if (\"frameTask\" in child && child.frameTask instanceof Task) {\n elements.push(child as TemporalMixinInterface & HTMLElement);\n }\n deepGetElementsWithFrameTasks(child, elements);\n }\n return elements;\n};\n\nlet temporalCache: Map<Element, TemporalMixinInterface[]>;\nlet temporalCacheResetScheduled = false;\nexport const resetTemporalCache = () => {\n temporalCache = new Map();\n if (\n typeof requestAnimationFrame !== \"undefined\" &&\n !temporalCacheResetScheduled\n ) {\n temporalCacheResetScheduled = true;\n requestAnimationFrame(() => {\n temporalCacheResetScheduled = false;\n resetTemporalCache();\n });\n }\n};\nresetTemporalCache();\n\nexport const shallowGetTemporalElements = (\n element: Element,\n temporals: TemporalMixinInterface[] = [],\n) => {\n const cachedResult = temporalCache.get(element);\n if (cachedResult) {\n return cachedResult;\n }\n for (const child of element.children) {\n if (isEFTemporal(child)) {\n temporals.push(child);\n } else {\n shallowGetTemporalElements(child, temporals);\n }\n }\n temporalCache.set(element, temporals);\n return temporals;\n};\n\nexport class OwnCurrentTimeController implements ReactiveController {\n #lastKnownTimeMs: number | undefined = undefined;\n \n constructor(\n private host: EFTimegroup,\n private temporal: TemporalMixinInterface & LitElement,\n ) {\n host.addController(this);\n }\n\n hostUpdated() {\n // CRITICAL FIX: Only trigger child updates when root's currentTimeMs actually changes.\n // Previously, this fired on EVERY root update, causing 40+ child updates per root update.\n // With nested timegroups, this created cascading updates that locked up the main thread.\n const currentTimeMs = this.host.currentTimeMs;\n if (this.#lastKnownTimeMs === currentTimeMs) {\n return; // Time hasn't changed, no need to update children\n }\n this.#lastKnownTimeMs = currentTimeMs;\n \n // Defer update using setTimeout(0) to avoid Lit warning about scheduling updates after update completed.\n // This batches updates and ensures we're completely outside any Lit update cycle.\n // Using setTimeout instead of Promise.resolve() because microtasks run before Lit's\n // change detection completes.\n setTimeout(() => {\n this.temporal.requestUpdate(\"ownCurrentTimeMs\");\n }, 0);\n }\n\n remove() {\n this.host.removeController(this);\n }\n}\n\ntype Constructor<T = {}> = new (...args: any[]) => T;\n\nlet startTimeMsCache = new WeakMap<Element, number>();\nlet startTimeMsCacheResetScheduled = false;\nconst resetStartTimeMsCache = () => {\n startTimeMsCache = new WeakMap();\n if (\n typeof requestAnimationFrame !== \"undefined\" &&\n !startTimeMsCacheResetScheduled\n ) {\n startTimeMsCacheResetScheduled = true;\n requestAnimationFrame(() => {\n startTimeMsCacheResetScheduled = false;\n resetStartTimeMsCache();\n });\n }\n};\nresetStartTimeMsCache();\n\nexport const flushStartTimeMsCache = () => {\n startTimeMsCache = new WeakMap();\n};\n\nexport const EFTemporal = <T extends Constructor<LitElement>>(\n superClass: T,\n) => {\n class TemporalMixinClass extends superClass {\n #ownCurrentTimeController?: OwnCurrentTimeController;\n\n #parentTimegroup?: EFTimegroup;\n #rootTimegroupLocked = false; // When true, rootTimegroup won't be auto-recalculated\n \n @consume({ context: timegroupContext, subscribe: true })\n set parentTimegroup(value: EFTimegroup | undefined) {\n const oldParent = this.#parentTimegroup;\n const oldRole = determineTemporalRole(oldParent);\n const newRole = determineTemporalRole(value);\n\n this.#parentTimegroup = value;\n\n this.#ownCurrentTimeController?.remove();\n // Only auto-calculate rootTimegroup if it hasn't been locked\n // (locked means it was manually set, e.g., for render clones)\n if (!this.#rootTimegroupLocked) {\n this.rootTimegroup = this.getRootTimegroup();\n }\n if (this.rootTimegroup) {\n this.#ownCurrentTimeController = new OwnCurrentTimeController(\n this.rootTimegroup,\n this as InstanceType<Constructor<TemporalMixinInterface> & T>,\n );\n }\n\n // Only trigger callbacks if role actually changed\n if (oldRole !== newRole) {\n if (newRole === \"root\") {\n this.didBecomeRoot();\n } else {\n this.didBecomeChild();\n }\n }\n }\n \n /**\n * Lock the rootTimegroup to prevent auto-recalculation.\n * Used for render clones where the root must be fixed.\n * @internal\n */\n lockRootTimegroup() {\n this.#rootTimegroupLocked = true;\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.#ownCurrentTimeController?.remove();\n\n if (this.playbackController) {\n this.playbackController.remove();\n this.playbackController = undefined;\n }\n\n // Clean up tracked animations to prevent memory leaks\n // Use dynamic import to avoid circular dependency with updateAnimations\n import(\"./updateAnimations.js\").then(({ cleanupTrackedAnimations }) => {\n cleanupTrackedAnimations(this);\n });\n }\n\n connectedCallback() {\n super.connectedCallback();\n this.#ownCurrentTimeController?.remove();\n\n // Root detection: Check DOM structure to determine if this is truly a root.\n // \n // We can't rely on Lit Context (parentTimegroup) because context propagates\n // asynchronously during update cycles. Children may complete their first update\n // before ancestors have provided context, causing them to incorrectly think\n // they're roots.\n //\n // Instead, we check if there's an ancestor ef-timegroup in the DOM. This is\n // reliable because DOM structure is established synchronously at connection time.\n // \n // If there's NO ancestor timegroup, this is a true root → create PlaybackController.\n // If there IS an ancestor, wait for context to propagate (handled by parentTimegroup setter).\n // Note: closest() includes self, so we check from parentElement to find true ancestors.\n const hasAncestorTimegroup = this.parentElement?.closest('ef-timegroup') != null;\n \n if (!hasAncestorTimegroup && !this.playbackController) {\n // True root: no ancestor timegroup in DOM\n // Defer slightly to allow element to fully initialize\n this.updateComplete.then(() => {\n if (!this.isConnected) return;\n if (!this.playbackController) {\n this.didBecomeRoot();\n }\n });\n }\n // For elements WITH ancestors, the parentTimegroup setter will be called\n // when Lit Context propagates, and if the role changes, didBecomeRoot/didBecomeChild\n // will be called appropriately.\n }\n\n get parentTimegroup() {\n return this.#parentTimegroup;\n }\n\n playbackController?: PlaybackController;\n\n get playing(): boolean {\n if (!this.playbackController) {\n return false;\n }\n return this.playbackController.playing;\n }\n\n set playing(value: boolean) {\n if (!this.playbackController) {\n console.warn(\"Cannot set playing on non-root temporal element\", this);\n return;\n }\n this.playbackController.setPlaying(value);\n }\n\n play(): void {\n if (!this.playbackController) {\n console.warn(\"play() called on non-root temporal element\", this);\n return;\n }\n this.playbackController.play();\n }\n\n pause(): void {\n if (!this.playbackController) {\n console.warn(\"pause() called on non-root temporal element\", this);\n return;\n }\n this.playbackController.pause();\n }\n\n @property({ type: Boolean, reflect: true, attribute: \"loop\" })\n get loop(): boolean {\n return this.playbackController?.loop ?? this.#loop;\n }\n\n set loop(value: boolean) {\n const oldValue = this.#loop;\n this.#loop = value;\n if (this.playbackController) {\n this.playbackController.setLoop(value);\n }\n this.requestUpdate(\"loop\", oldValue);\n }\n\n @property({\n type: String,\n attribute: \"offset\",\n converter: durationConverter,\n })\n private _offsetMs = 0;\n\n @property({\n type: Number,\n attribute: \"duration\",\n converter: durationConverter,\n })\n private _durationMs?: number;\n\n set duration(value: string | undefined) {\n if (value !== undefined) {\n this.setAttribute(\"duration\", value);\n } else {\n this.removeAttribute(\"duration\");\n }\n }\n\n @property({\n type: Number,\n attribute: \"trimstart\",\n converter: durationConverter,\n })\n private _trimStartMs: number | undefined = undefined;\n\n get trimStartMs() {\n if (this._trimStartMs === undefined) {\n return undefined;\n }\n return Math.min(\n Math.max(this._trimStartMs, 0),\n this.intrinsicDurationMs ?? 0,\n );\n }\n\n set trimStartMs(value: number | undefined) {\n this._trimStartMs = value;\n }\n\n @property({\n type: Number,\n attribute: \"trimend\",\n converter: durationConverter,\n })\n private _trimEndMs: number | undefined = undefined;\n\n get trimEndMs() {\n if (this._trimEndMs === undefined) {\n return undefined;\n }\n return Math.min(this._trimEndMs, this.intrinsicDurationMs ?? 0);\n }\n\n set trimEndMs(value: number | undefined) {\n this._trimEndMs = value;\n }\n\n @property({\n type: Number,\n attribute: \"sourcein\",\n converter: durationConverter,\n })\n private _sourceInMs: number | undefined = undefined;\n\n get sourceInMs() {\n if (this._sourceInMs === undefined) {\n return undefined;\n }\n return Math.max(this._sourceInMs, 0);\n }\n\n set sourceInMs(value: number | undefined) {\n this._sourceInMs = value;\n }\n\n @property({\n type: Number,\n attribute: \"sourceout\",\n converter: durationConverter,\n })\n private _sourceOutMs: number | undefined = undefined;\n\n get sourceOutMs() {\n if (this._sourceOutMs === undefined) {\n return undefined;\n }\n if (\n this.intrinsicDurationMs &&\n this._sourceOutMs > this.intrinsicDurationMs\n ) {\n return this.intrinsicDurationMs;\n }\n return Math.max(this._sourceOutMs, 0);\n }\n\n set sourceOutMs(value: number | undefined) {\n this._sourceOutMs = value;\n }\n\n @property({\n type: Number,\n attribute: \"startoffset\",\n converter: durationConverter,\n })\n private _startOffsetMs = 0;\n public get startOffsetMs(): number {\n return this._startOffsetMs;\n }\n\n @state()\n rootTimegroup?: EFTimegroup = this.getRootTimegroup();\n\n private getRootTimegroup(): EFTimegroup | undefined {\n let parent =\n this.tagName === \"EF-TIMEGROUP\" ? this : this.parentTimegroup;\n while (parent?.parentTimegroup) {\n parent = parent.parentTimegroup;\n }\n return parent as EFTimegroup | undefined;\n }\n\n get hasExplicitDuration() {\n return this._durationMs !== undefined;\n }\n\n get explicitDurationMs() {\n if (this.hasExplicitDuration) {\n return this._durationMs;\n }\n return undefined;\n }\n\n get hasOwnDuration() {\n return this.intrinsicDurationMs !== undefined || this.hasExplicitDuration;\n }\n\n get intrinsicDurationMs() {\n return undefined;\n }\n\n get durationMs() {\n // Prevent infinite loops: don't call parent.durationMs if parent is currently calculating\n // Lazy import to break circular dependency: EFTemporal -> EFTimegroup -> EFMedia -> EFTemporal\n const isTimegroupCalculatingDuration =\n getIsTimegroupCalculatingDuration();\n const parentDurationMs = isTimegroupCalculatingDuration(\n this.parentTimegroup,\n )\n ? undefined\n : this.parentTimegroup?.durationMs;\n const durationSource = determineDurationSource(\n this.intrinsicDurationMs,\n this._durationMs,\n parentDurationMs,\n );\n\n const modification = determineDurationModificationStrategy(\n this.trimStartMs,\n this.trimEndMs,\n this.sourceInMs,\n this.sourceOutMs,\n );\n\n return evaluateModifiedDuration(\n durationSource.baseDurationMs,\n modification,\n );\n }\n\n get sourceStartMs() {\n return this.trimStartMs ?? this.sourceInMs ?? 0;\n }\n\n #offsetMs() {\n return this._offsetMs || 0;\n }\n\n #parentTemporal() {\n let parent = this.parentElement;\n while (parent && !isEFTemporal(parent)) {\n parent = parent.parentElement;\n }\n return parent;\n }\n\n /**\n * The start time of the element within its parent timegroup.\n */\n get startTimeWithinParentMs() {\n const parent = this.#parentTemporal();\n if (!parent) {\n return 0;\n }\n return this.startTimeMs - parent.startTimeMs;\n }\n\n #loop = false;\n\n get startTimeMs(): number {\n const cachedStartTime = startTimeMsCache.get(this);\n if (cachedStartTime !== undefined) {\n return cachedStartTime;\n }\n\n const startTime = evaluateStartTime(\n this as InstanceType<Constructor<TemporalMixinInterface> & T>,\n this.parentTimegroup,\n this.#offsetMs(),\n (parent) => shallowGetTemporalElements(parent),\n );\n\n startTimeMsCache.set(this, startTime);\n return startTime;\n }\n\n get endTimeMs(): number {\n return this.startTimeMs + this.durationMs;\n }\n\n #currentTimeMs = 0;\n\n /**\n * The current time of the element within itself.\n * Compare with `currentTimeMs` to see the current time with respect to the root timegroup\n */\n get ownCurrentTimeMs(): number {\n const timeSource = determineCurrentTimeSource(\n this.playbackController,\n this.rootTimegroup,\n this.rootTimegroup === (this as any as EFTimegroup),\n this.#currentTimeMs,\n this.startTimeMs,\n this.durationMs,\n );\n return timeSource.timeMs;\n }\n\n /**\n * Element's current time for progress calculation.\n * Non-timegroup temporal elements use their local time (ownCurrentTimeMs)\n */\n get currentTimeMs() {\n return this.ownCurrentTimeMs;\n }\n\n set currentTimeMs(value: number) {\n const role = determineTemporalRole(this.parentTimegroup);\n\n // Apply current time based on role\n switch (role) {\n case \"root\":\n if (this.playbackController) {\n this.playbackController.currentTime = value / 1000;\n } else {\n this.#currentTimeMs = value;\n this.requestUpdate(\"currentTimeMs\");\n }\n break;\n case \"child\":\n if (\n this.rootTimegroup &&\n this.rootTimegroup !== (this as any as EFTimegroup)\n ) {\n this.rootTimegroup.currentTimeMs = value;\n } else {\n this.#currentTimeMs = value;\n this.requestUpdate(\"currentTimeMs\");\n }\n break;\n }\n }\n\n /**\n * Used to calculate the internal currentTimeMs of the element. This is useful\n * for mapping to internal media time codes for audio/video elements.\n */\n get currentSourceTimeMs() {\n const leadingTrimMs = this.sourceInMs || this.trimStartMs || 0;\n return this.ownCurrentTimeMs + leadingTrimMs;\n }\n\n frameTask = new Task(this, {\n autoRun: EF_INTERACTIVE,\n args: () => [this.ownCurrentTimeMs] as const,\n onError: (error) => {\n // CRITICAL: Attach .catch() handler to prevent unhandled rejection\n this.frameTask.taskComplete.catch(() => {});\n \n // Don't log AbortErrors - these are expected when element is disconnected\n const isAbortError = \n error instanceof DOMException && error.name === \"AbortError\" ||\n error instanceof Error && (\n error.name === \"AbortError\" ||\n error.message?.includes(\"signal is aborted\") ||\n error.message?.includes(\"The user aborted a request\")\n );\n \n if (isAbortError) {\n return;\n }\n console.error(\"EFTemporal frameTask error\", error);\n },\n task: async ([], { signal }) => {\n let fullyUpdated = await this.updateComplete;\n signal?.throwIfAborted();\n let loopCount = 0;\n const MAX_LOOP_ITERATIONS = 100;\n while (!fullyUpdated) {\n loopCount++;\n if (loopCount > MAX_LOOP_ITERATIONS) {\n console.error(`[EFTemporal] frameTask while loop exceeded ${MAX_LOOP_ITERATIONS} iterations, breaking. Element:`, this.tagName, this.id || 'unnamed');\n break; // Break out to prevent infinite loop\n }\n fullyUpdated = await this.updateComplete;\n signal?.throwIfAborted();\n }\n },\n });\n\n didBecomeRoot() {\n if (!this.playbackController) {\n this.playbackController = new PlaybackController(this as any);\n if (this.#loop) {\n this.playbackController.setLoop(this.#loop);\n }\n }\n }\n\n didBecomeChild() {\n if (this.playbackController) {\n this.playbackController.remove();\n this.playbackController = undefined;\n }\n }\n }\n\n Object.defineProperty(TemporalMixinClass.prototype, EF_TEMPORAL, {\n value: true,\n });\n\n return TemporalMixinClass as unknown as Constructor<TemporalMixinInterface> &\n T;\n};\n"],"mappings":"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"}
@@ -1,14 +1,14 @@
1
1
  import { TemporalMixinInterface } from "./EFTemporal.js";
2
2
  import { EFTextSegment } from "./EFTextSegment.js";
3
- import * as lit9 from "lit";
3
+ import * as lit8 from "lit";
4
4
  import { LitElement, PropertyValueMap } from "lit";
5
- import * as lit_html9 from "lit-html";
5
+ import * as lit_html8 from "lit-html";
6
6
 
7
7
  //#region src/elements/EFText.d.ts
8
8
  type SplitMode = "line" | "word" | "char";
9
9
  declare const EFText_base: (new (...args: any[]) => TemporalMixinInterface) & typeof LitElement;
10
10
  declare class EFText extends EFText_base {
11
- static styles: lit9.CSSResult[];
11
+ static styles: lit8.CSSResult[];
12
12
  split: SplitMode;
13
13
  private validateSplit;
14
14
  staggerMs?: number;
@@ -19,7 +19,7 @@ declare class EFText extends EFText_base {
19
19
  private _textContent;
20
20
  private _templateElement;
21
21
  private _segmentsReadyResolvers;
22
- render(): lit_html9.TemplateResult<1>;
22
+ render(): lit_html8.TemplateResult<1>;
23
23
  set textContent(value: string | null);
24
24
  get textContent(): string;
25
25
  /**
@@ -39,6 +39,7 @@ declare class EFText extends EFText_base {
39
39
  private setupMutationObserver;
40
40
  private getTextContent;
41
41
  private splitText;
42
+ private detectWordBoundaries;
42
43
  private splitTextIntoSegments;
43
44
  get intrinsicDurationMs(): number | undefined;
44
45
  }