@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
@@ -1,4 +1,4 @@
1
- import { deepGetTemporalElements } from "./EFTemporal.js";
1
+ import { deepGetTemporalElements, isEFTemporal } from "./EFTemporal.js";
2
2
 
3
3
  //#region src/elements/updateAnimations.ts
4
4
  const ANIMATION_PRECISION_OFFSET = .1;
@@ -8,144 +8,527 @@ const DURATION_PROPERTY = "--ef-duration";
8
8
  const TRANSITION_DURATION_PROPERTY = "--ef-transition-duration";
9
9
  const TRANSITION_OUT_START_PROPERTY = "--ef-transition-out-start";
10
10
  /**
11
- * Evaluates what the element's state should be based on the timeline
11
+ * Tracks animations per element to prevent them from being lost when they complete.
12
+ * Once an animation reaches 100% completion, it's removed from getAnimations(),
13
+ * but we keep a reference to it so we can continue controlling it.
14
+ */
15
+ const animationTracker = /* @__PURE__ */ new WeakMap();
16
+ /**
17
+ * Tracks whether DOM structure has changed for an element, requiring animation rediscovery.
18
+ * For render clones (static DOM), this stays false after initial discovery.
19
+ * For prime timeline (interactive), this is set to true when mutations occur.
20
+ */
21
+ const domStructureChanged = /* @__PURE__ */ new WeakMap();
22
+ /**
23
+ * Tracks the last known animation count for an element to detect new animations.
24
+ * Used as a lightweight check before calling expensive getAnimations().
25
+ */
26
+ const lastAnimationCount = /* @__PURE__ */ new WeakMap();
27
+ /**
28
+ * Checks if an element is in a render clone (static DOM context).
29
+ * Render clones are in containers with class "ef-render-clone-container".
30
+ */
31
+ const isRenderClone = (element) => {
32
+ return element.closest(".ef-render-clone-container") !== null;
33
+ };
34
+ /**
35
+ * Validates that an animation is still valid and controllable.
36
+ * Animations become invalid when:
37
+ * - They've been cancelled (idle state and not in getAnimations())
38
+ * - Their effect is null (animation was removed)
39
+ * - Their target is no longer in the DOM
40
+ */
41
+ const isAnimationValid = (animation, currentAnimations) => {
42
+ if (animation.playState === "idle" && !currentAnimations.includes(animation)) return false;
43
+ const effect = animation.effect;
44
+ if (!effect) return false;
45
+ if (effect instanceof KeyframeEffect) {
46
+ const target = effect.target;
47
+ if (target && target instanceof Element) {
48
+ if (!target.isConnected) return false;
49
+ }
50
+ }
51
+ return true;
52
+ };
53
+ /**
54
+ * Discovers and tracks animations on an element and its subtree.
55
+ * This ensures we have references to animations even after they complete.
56
+ *
57
+ * Tracks animations per element where they exist, not just on the root element.
58
+ * This allows us to find animations on any element in the subtree.
59
+ *
60
+ * OPTIMIZATION: For render clones (static DOM), discovery happens once at creation.
61
+ * For prime timeline (interactive), discovery is responsive to DOM changes.
62
+ *
63
+ * Also cleans up invalid animations (cancelled, removed from DOM, etc.)
64
+ */
65
+ const discoverAndTrackAnimations = (element) => {
66
+ const isClone = isRenderClone(element);
67
+ const hasTrackedAnimations = animationTracker.has(element);
68
+ const structureChanged = domStructureChanged.get(element) ?? true;
69
+ if (isClone && hasTrackedAnimations && !structureChanged) {
70
+ const rootTracked$1 = animationTracker.get(element);
71
+ const currentAnimations$1 = [];
72
+ const rootDirectAnimations = element.getAnimations();
73
+ for (const animation of rootTracked$1) if (isAnimationValid(animation, rootDirectAnimations)) currentAnimations$1.push(animation);
74
+ return {
75
+ tracked: rootTracked$1,
76
+ current: currentAnimations$1
77
+ };
78
+ }
79
+ const currentAnimations = element.getAnimations({ subtree: true });
80
+ if (isClone) domStructureChanged.set(element, false);
81
+ lastAnimationCount.set(element, currentAnimations.length);
82
+ for (const animation of currentAnimations) {
83
+ const effect = animation.effect;
84
+ const target = effect && effect instanceof KeyframeEffect ? effect.target : null;
85
+ if (target && target instanceof Element) {
86
+ let tracked = animationTracker.get(target);
87
+ if (!tracked) {
88
+ tracked = /* @__PURE__ */ new Set();
89
+ animationTracker.set(target, tracked);
90
+ }
91
+ tracked.add(animation);
92
+ }
93
+ }
94
+ let rootTracked = animationTracker.get(element);
95
+ if (!rootTracked) {
96
+ rootTracked = /* @__PURE__ */ new Set();
97
+ animationTracker.set(element, rootTracked);
98
+ }
99
+ for (const animation of currentAnimations) rootTracked.add(animation);
100
+ for (const animation of rootTracked) if (!isAnimationValid(animation, currentAnimations)) rootTracked.delete(animation);
101
+ const allTargets = /* @__PURE__ */ new Set();
102
+ for (const animation of currentAnimations) {
103
+ const effect = animation.effect;
104
+ const target = effect && effect instanceof KeyframeEffect ? effect.target : null;
105
+ if (target && target instanceof Element) allTargets.add(target);
106
+ }
107
+ const subtreeElements = element.querySelectorAll("*");
108
+ for (const el of subtreeElements) {
109
+ const tracked = animationTracker.get(el);
110
+ if (tracked) {
111
+ for (const animation of tracked) if (!isAnimationValid(animation, Array.from(el.getAnimations()))) tracked.delete(animation);
112
+ if (tracked.size === 0) animationTracker.delete(el);
113
+ }
114
+ }
115
+ return {
116
+ tracked: rootTracked,
117
+ current: currentAnimations
118
+ };
119
+ };
120
+ /**
121
+ * Cleans up tracked animations when an element is disconnected.
122
+ * This prevents memory leaks.
123
+ */
124
+ const cleanupTrackedAnimations = (element) => {
125
+ animationTracker.delete(element);
126
+ domStructureChanged.delete(element);
127
+ lastAnimationCount.delete(element);
128
+ };
129
+ /**
130
+ * Determines what phase an element is in relative to the timeline.
131
+ *
132
+ * WHY: Phase is the primary concept that drives all decisions. By explicitly
133
+ * enumerating phases, we make the code's logic clear: phase determines visibility,
134
+ * animation coordination, and visual state.
135
+ *
136
+ * Phases:
137
+ * - before-start: Timeline is before element's start time
138
+ * - active: Timeline is within element's active range (start to end, exclusive of end)
139
+ * - at-end-boundary: Timeline is exactly at element's end time
140
+ * - after-end: Timeline is after element's end time
141
+ *
142
+ * Note: We detect "at-end-boundary" by checking if timeline equals end time.
143
+ * The boundary policy will then determine if this should be treated as visible/active
144
+ * or not based on element characteristics.
145
+ */
146
+ const determineElementPhase = (element, timelineTimeMs) => {
147
+ const endTimeMs = element.endTimeMs;
148
+ const startTimeMs = element.startTimeMs;
149
+ if (endTimeMs <= startTimeMs) return "active";
150
+ if (timelineTimeMs < startTimeMs) return "before-start";
151
+ const epsilon = .001;
152
+ const diff = timelineTimeMs - endTimeMs;
153
+ if (diff > epsilon) return "after-end";
154
+ if (Math.abs(diff) <= epsilon) return "at-end-boundary";
155
+ return "active";
156
+ };
157
+ /**
158
+ * Visibility policy: determines when elements should be visible for display purposes.
159
+ *
160
+ * WHY: Root elements, elements aligned with composition end, and text segments
161
+ * should remain visible at exact end time to prevent flicker and show final frames.
162
+ * Other elements use exclusive end for clean transitions between elements.
163
+ */
164
+ var VisibilityPolicy = class {
165
+ shouldIncludeEndBoundary(element) {
166
+ if (!element.parentTimegroup) return true;
167
+ if (element.endTimeMs === element.rootTimegroup?.endTimeMs) return true;
168
+ if (this.isTextSegment(element)) return true;
169
+ return false;
170
+ }
171
+ /**
172
+ * Checks if element is a text segment.
173
+ * Encapsulates the tag name check to hide implementation detail.
174
+ */
175
+ isTextSegment(element) {
176
+ return element.tagName === "EF-TEXT-SEGMENT";
177
+ }
178
+ };
179
+ /**
180
+ * Animation policy: determines when animations should be coordinated.
181
+ *
182
+ * WHY: When an animation reaches exactly the end time of an element, using exclusive
183
+ * end would make the element invisible, causing the animation to be removed from the
184
+ * DOM and creating a visual jump. By using inclusive end, we ensure animations remain
185
+ * coordinated even at exact boundary times, providing smooth visual transitions.
186
+ */
187
+ var AnimationPolicy = class {
188
+ shouldIncludeEndBoundary(_element) {
189
+ return true;
190
+ }
191
+ };
192
+ const visibilityPolicy = new VisibilityPolicy();
193
+ const animationPolicy = new AnimationPolicy();
194
+ /**
195
+ * Determines if an element should be visible based on its phase and visibility policy.
196
+ */
197
+ const shouldBeVisible = (phase, element) => {
198
+ if (phase === "before-start" || phase === "after-end") return false;
199
+ if (phase === "active") return true;
200
+ return visibilityPolicy.shouldIncludeEndBoundary(element);
201
+ };
202
+ /**
203
+ * Determines if animations should be coordinated based on element phase and animation policy.
204
+ */
205
+ const shouldCoordinateAnimations = (phase, element) => {
206
+ if (phase === "before-start" || phase === "after-end") return false;
207
+ if (phase === "active") return true;
208
+ return animationPolicy.shouldIncludeEndBoundary(element);
209
+ };
210
+ /**
211
+ * Evaluates what the element's state should be based on the timeline.
212
+ *
213
+ * WHY: This function determines the complete temporal state including phase,
214
+ * which becomes the primary driver for all subsequent decisions.
12
215
  */
13
216
  const evaluateTemporalState = (element) => {
14
217
  const timelineTimeMs = (element.rootTimegroup ?? element).currentTimeMs;
15
218
  const progress = element.durationMs <= 0 ? 1 : Math.max(0, Math.min(1, element.currentTimeMs / element.durationMs));
16
- const isRootElement = !element.parentTimegroup;
17
- const isLastElementInComposition = element.endTimeMs === element.rootTimegroup?.endTimeMs;
18
- const isTextSegment = element.tagName === "EF-TEXT-SEGMENT";
19
- const useInclusiveEnd = isRootElement || isLastElementInComposition || isTextSegment;
219
+ const phase = determineElementPhase(element, timelineTimeMs);
20
220
  return {
21
221
  progress,
22
- isVisible: element.startTimeMs <= timelineTimeMs && (useInclusiveEnd ? element.endTimeMs >= timelineTimeMs : element.endTimeMs > timelineTimeMs),
23
- timelineTimeMs
222
+ isVisible: shouldBeVisible(phase, element),
223
+ timelineTimeMs,
224
+ phase
24
225
  };
25
226
  };
26
227
  /**
27
- * Evaluates element visibility specifically for animation coordination
28
- * Uses inclusive end boundaries to prevent animation jumps at exact boundaries
228
+ * Evaluates element visibility state specifically for animation coordination.
229
+ * Uses inclusive end boundaries to prevent animation jumps at exact boundaries.
230
+ *
231
+ * This is exported for external use cases that need animation-specific visibility
232
+ * evaluation without the full ElementUpdateContext.
29
233
  */
30
- const evaluateTemporalStateForAnimation = (element) => {
31
- const timelineTimeMs = (element.rootTimegroup ?? element).currentTimeMs;
234
+ const evaluateAnimationVisibilityState = (element) => {
235
+ const state = evaluateTemporalState(element);
236
+ const shouldCoordinate = shouldCoordinateAnimations(state.phase, element);
32
237
  return {
33
- progress: element.durationMs <= 0 ? 1 : Math.max(0, Math.min(1, element.currentTimeMs / element.durationMs)),
34
- isVisible: element.startTimeMs <= timelineTimeMs && element.endTimeMs >= timelineTimeMs,
35
- timelineTimeMs
238
+ ...state,
239
+ isVisible: shouldCoordinate
36
240
  };
37
241
  };
38
242
  /**
39
- * Updates the visual state (CSS + display) to match temporal state
243
+ * Capability check: determines if an element supports stagger offset.
244
+ * Encapsulates the knowledge of which element types support this feature.
40
245
  */
41
- const updateVisualState = (element, state) => {
42
- element.style.setProperty(PROGRESS_PROPERTY, `${state.progress * 100}%`);
246
+ const supportsStaggerOffset = (element) => {
247
+ return element.tagName === "EF-TEXT-SEGMENT";
248
+ };
249
+ /**
250
+ * Calculates effective delay including stagger offset if applicable.
251
+ *
252
+ * Stagger offset allows elements (like text segments) to have their animations
253
+ * start at different times while keeping their visibility timing unchanged.
254
+ * This enables staggered animation effects within a single timegroup.
255
+ */
256
+ const calculateEffectiveDelay = (delay, element) => {
257
+ if (supportsStaggerOffset(element)) {
258
+ const segment = element;
259
+ if (segment.staggerOffsetMs !== void 0 && segment.staggerOffsetMs !== null) return delay + segment.staggerOffsetMs;
260
+ let cssValue = element.style.getPropertyValue("--ef-stagger-offset").trim();
261
+ if (!cssValue) cssValue = window.getComputedStyle(element).getPropertyValue("--ef-stagger-offset").trim();
262
+ if (cssValue) {
263
+ const match = cssValue.match(/(\d+(?:\.\d+)?)\s*ms?/);
264
+ if (match) {
265
+ const staggerOffset = parseFloat(match[1]);
266
+ if (!isNaN(staggerOffset)) return delay + staggerOffset;
267
+ } else {
268
+ const numValue = parseFloat(cssValue);
269
+ if (!isNaN(numValue)) return delay + numValue;
270
+ }
271
+ }
272
+ }
273
+ return delay;
274
+ };
275
+ /**
276
+ * Calculates maximum safe animation time to prevent completion.
277
+ *
278
+ * WHY: Once an animation reaches "finished" state, it can no longer be manually controlled
279
+ * via currentTime. By clamping to just before completion (using ANIMATION_PRECISION_OFFSET),
280
+ * we ensure the animation remains in a controllable state, allowing us to synchronize it
281
+ * with the timeline even when it would naturally be complete.
282
+ */
283
+ const calculateMaxSafeAnimationTime = (duration, iterations) => {
284
+ return duration * iterations - ANIMATION_PRECISION_OFFSET;
285
+ };
286
+ /**
287
+ * Determines if the current iteration should be reversed based on direction
288
+ */
289
+ const shouldReverseIteration = (direction, currentIteration) => {
290
+ return direction === "reverse" || direction === "alternate" && currentIteration % 2 === 1 || direction === "alternate-reverse" && currentIteration % 2 === 0;
291
+ };
292
+ /**
293
+ * Applies direction to iteration time (reverses if needed)
294
+ */
295
+ const applyDirectionToIterationTime = (currentIterationTime, duration, direction, currentIteration) => {
296
+ if (shouldReverseIteration(direction, currentIteration)) return duration - currentIterationTime;
297
+ return currentIterationTime;
298
+ };
299
+ /**
300
+ * Maps element time to animation time for normal direction.
301
+ * Uses cumulative time throughout the animation.
302
+ * Note: elementTime should already be adjusted (elementTime - effectiveDelay).
303
+ */
304
+ const mapNormalDirectionTime = (elementTime, duration, maxSafeTime) => {
305
+ const currentIteration = Math.floor(elementTime / duration);
306
+ const iterationTime = elementTime % duration;
307
+ const cumulativeTime = currentIteration * duration + iterationTime;
308
+ return Math.min(cumulativeTime, maxSafeTime);
309
+ };
310
+ /**
311
+ * Maps element time to animation time for reverse direction.
312
+ * Uses cumulative time with reversed iterations.
313
+ * Note: elementTime should already be adjusted (elementTime - effectiveDelay).
314
+ */
315
+ const mapReverseDirectionTime = (elementTime, duration, maxSafeTime) => {
316
+ const currentIteration = Math.floor(elementTime / duration);
317
+ const reversedIterationTime = duration - elementTime % duration;
318
+ const cumulativeTime = currentIteration * duration + reversedIterationTime;
319
+ return Math.min(cumulativeTime, maxSafeTime);
320
+ };
321
+ /**
322
+ * Maps element time to animation time for alternate/alternate-reverse directions.
323
+ *
324
+ * WHY SPECIAL HANDLING: Alternate directions oscillate between forward and reverse iterations.
325
+ * Without delay, we use iteration time (0 to duration) because the animation naturally
326
+ * resets each iteration. However, with delay, iteration 0 needs to account for the delay
327
+ * offset (using ownCurrentTimeMs), and later iterations need cumulative time to properly
328
+ * track progress across multiple iterations. This complexity requires a dedicated mapper
329
+ * rather than trying to handle it in the general case.
330
+ */
331
+ const mapAlternateDirectionTime = (elementTime, effectiveDelay, duration, direction, maxSafeTime) => {
332
+ const adjustedTime = elementTime - effectiveDelay;
333
+ if (effectiveDelay > 0) {
334
+ if (Math.floor(adjustedTime / duration) === 0) return Math.min(elementTime, maxSafeTime);
335
+ return Math.min(adjustedTime, maxSafeTime);
336
+ }
337
+ const currentIteration = Math.floor(elementTime / duration);
338
+ const iterationTime = applyDirectionToIterationTime(elementTime % duration, duration, direction, currentIteration);
339
+ return Math.min(iterationTime, maxSafeTime);
340
+ };
341
+ /**
342
+ * Maps element time to animation time based on direction.
343
+ *
344
+ * WHY: This function explicitly transforms element time to animation time, making
345
+ * the time mapping concept clear. Different directions require different transformations
346
+ * to achieve the desired visual effect.
347
+ */
348
+ const mapElementTimeToAnimationTime = (elementTime, timing, effectiveDelay) => {
349
+ const { duration, iterations, direction } = timing;
350
+ const maxSafeTime = calculateMaxSafeAnimationTime(duration, iterations);
351
+ const adjustedTime = elementTime - effectiveDelay;
352
+ if (direction === "reverse") return mapReverseDirectionTime(adjustedTime, duration, maxSafeTime);
353
+ if (direction === "alternate" || direction === "alternate-reverse") return mapAlternateDirectionTime(elementTime, effectiveDelay, duration, direction, maxSafeTime);
354
+ return mapNormalDirectionTime(adjustedTime, duration, maxSafeTime);
355
+ };
356
+ /**
357
+ * Determines the animation time for a completed animation based on direction.
358
+ */
359
+ const getCompletedAnimationTime = (timing, maxSafeTime) => {
360
+ const { direction, iterations, duration } = timing;
361
+ if (direction === "alternate" || direction === "alternate-reverse") {
362
+ const finalIteration = iterations - 1;
363
+ if (direction === "alternate" && finalIteration % 2 === 1 || direction === "alternate-reverse" && finalIteration % 2 === 0) return Math.min(duration - ANIMATION_PRECISION_OFFSET, maxSafeTime);
364
+ }
365
+ return maxSafeTime;
366
+ };
367
+ /**
368
+ * Validates that animation effect is a KeyframeEffect with a target
369
+ */
370
+ const validateAnimationEffect = (effect) => {
371
+ return effect !== null && effect instanceof KeyframeEffect && effect.target !== null;
372
+ };
373
+ /**
374
+ * Extracts timing information from an animation effect.
375
+ * Duration and delay from getTiming() are already in milliseconds.
376
+ * We use getTiming().delay directly from the animation object.
377
+ */
378
+ const extractAnimationTiming = (effect) => {
379
+ const timing = effect.getTiming();
380
+ return {
381
+ duration: Number(timing.duration) || 0,
382
+ delay: Number(timing.delay) || 0,
383
+ iterations: Number(timing.iterations) || DEFAULT_ANIMATION_ITERATIONS,
384
+ direction: timing.direction || "normal"
385
+ };
386
+ };
387
+ /**
388
+ * Prepares animation for manual control by ensuring it's paused
389
+ */
390
+ const prepareAnimation = (animation) => {
391
+ if (animation.playState === "finished") animation.cancel();
392
+ else if (animation.playState === "running") animation.pause();
393
+ };
394
+ /**
395
+ * Maps element time to animation currentTime and sets it on the animation.
396
+ *
397
+ * WHY: This function explicitly performs the time mapping transformation,
398
+ * making it clear that we're transforming element time to animation time.
399
+ */
400
+ const mapAndSetAnimationTime = (animation, element, timing, effectiveDelay) => {
401
+ const elementTime = element.ownCurrentTimeMs ?? 0;
402
+ if (animation.playState === "running") animation.pause();
403
+ const adjustedTime = elementTime - effectiveDelay;
404
+ if (adjustedTime < 0) {
405
+ if (timing.delay > 0) animation.currentTime = elementTime;
406
+ else animation.currentTime = 0;
407
+ return;
408
+ }
409
+ const { duration, iterations } = timing;
410
+ const currentIteration = Math.floor(adjustedTime / duration);
411
+ if (currentIteration >= iterations) {
412
+ const completedAnimationTime = getCompletedAnimationTime(timing, calculateMaxSafeAnimationTime(duration, iterations));
413
+ if (timing.delay > 0) animation.currentTime = effectiveDelay + completedAnimationTime;
414
+ else animation.currentTime = completedAnimationTime;
415
+ } else {
416
+ const animationTime = mapElementTimeToAnimationTime(elementTime, timing, effectiveDelay);
417
+ const { direction, delay } = timing;
418
+ if (delay > 0) if ((direction === "alternate" || direction === "alternate-reverse") && effectiveDelay > 0 && currentIteration === 0) animation.currentTime = elementTime;
419
+ else animation.currentTime = effectiveDelay + animationTime;
420
+ else animation.currentTime = animationTime;
421
+ }
422
+ };
423
+ /**
424
+ * Synchronizes a single animation with the timeline using the element as the time source.
425
+ *
426
+ * For animations in this element's subtree, always use this element as the time source.
427
+ * This handles both animations directly on the temporal element and on its non-temporal children.
428
+ */
429
+ const synchronizeAnimation = (animation, element) => {
430
+ const effect = animation.effect;
431
+ if (!validateAnimationEffect(effect)) return;
432
+ const timing = extractAnimationTiming(effect);
433
+ if (timing.duration <= 0) {
434
+ animation.currentTime = 0;
435
+ return;
436
+ }
437
+ const target = effect.target;
438
+ let timeSource = element;
439
+ if (target && target instanceof HTMLElement) {
440
+ const nearestTimegroup = target.closest("ef-timegroup");
441
+ if (nearestTimegroup && isEFTemporal(nearestTimegroup)) timeSource = nearestTimegroup;
442
+ }
443
+ let staggerElement = timeSource;
444
+ if (target && target instanceof HTMLElement) {
445
+ const targetAsAnimatable = target;
446
+ if (supportsStaggerOffset(targetAsAnimatable)) staggerElement = targetAsAnimatable;
447
+ else {
448
+ const parentSegment = target.closest("ef-text-segment");
449
+ if (parentSegment && supportsStaggerOffset(parentSegment)) staggerElement = parentSegment;
450
+ }
451
+ }
452
+ const effectiveDelay = calculateEffectiveDelay(timing.delay, staggerElement);
453
+ mapAndSetAnimationTime(animation, timeSource, timing, effectiveDelay);
454
+ };
455
+ /**
456
+ * Coordinates animations for a single element and its subtree, using the element as the time source.
457
+ *
458
+ * Uses tracked animations to ensure we can control animations even after they complete.
459
+ * Both CSS animations (created via the 'animation' property) and WAAPI animations are included.
460
+ *
461
+ * CRITICAL: CSS animations are created asynchronously when classes are added. This function
462
+ * discovers new animations on each call and tracks them in memory. Once animations complete,
463
+ * they're removed from getAnimations(), but we keep references to them so we can continue
464
+ * controlling them.
465
+ */
466
+ const coordinateElementAnimations = (element) => {
467
+ const { tracked: trackedAnimations, current: currentAnimations } = discoverAndTrackAnimations(element);
468
+ for (const animation of trackedAnimations) {
469
+ if (!isAnimationValid(animation, currentAnimations)) continue;
470
+ prepareAnimation(animation);
471
+ synchronizeAnimation(animation, element);
472
+ }
473
+ };
474
+ /**
475
+ * Applies visual state (CSS + display) to match temporal state.
476
+ *
477
+ * WHY: This function applies visual state based on the element's phase and state.
478
+ * Phase determines what should be visible, and this function applies that decision.
479
+ */
480
+ const applyVisualState = (element, state) => {
481
+ element.style.setProperty(PROGRESS_PROPERTY, `${state.progress}`);
43
482
  if (!state.isVisible) {
44
- if (element.style.display !== "none") element.style.display = "none";
483
+ element.style.setProperty("display", "none");
45
484
  return;
46
485
  }
47
- if (element.style.display === "none") element.style.display = "";
486
+ element.style.removeProperty("display");
48
487
  element.style.setProperty(DURATION_PROPERTY, `${element.durationMs}ms`);
49
488
  element.style.setProperty(TRANSITION_DURATION_PROPERTY, `${element.parentTimegroup?.overlapMs ?? 0}ms`);
50
489
  element.style.setProperty(TRANSITION_OUT_START_PROPERTY, `${element.durationMs - (element.parentTimegroup?.overlapMs ?? 0)}ms`);
51
490
  };
52
491
  /**
53
- * Coordinates animations for a single element and its subtree, using the element as the time source
492
+ * Applies animation coordination if the element phase requires it.
493
+ *
494
+ * WHY: Animation coordination is driven by phase. If the element is in a phase
495
+ * where animations should be coordinated, we coordinate them.
54
496
  */
55
- const coordinateAnimationsForSingleElement = (element) => {
56
- const animations = element.getAnimations({ subtree: true });
57
- for (const animation of animations) {
58
- if (animation.playState === "finished") {
59
- animation.cancel();
60
- animation.play();
61
- animation.pause();
62
- } else if (animation.playState === "running") animation.pause();
63
- const effect = animation.effect;
64
- if (!(effect && effect instanceof KeyframeEffect)) continue;
65
- const target = effect.target;
66
- if (!target) continue;
67
- const timing = effect.getTiming();
68
- const duration = Number(timing.duration) || 0;
69
- let delay = Number(timing.delay) || 0;
70
- if (target instanceof HTMLElement) {
71
- const animationDelays = window.getComputedStyle(target).animationDelay.split(", ").map((s) => s.trim());
72
- const parseDelay = (delayStr) => {
73
- if (delayStr === "0s" || delayStr === "0ms") return 0;
74
- const delayMatch = delayStr.match(/^([\d.]+)(s|ms)$/);
75
- if (delayMatch?.[1] && delayMatch[2]) {
76
- const value = Number.parseFloat(delayMatch[1]);
77
- return delayMatch[2] === "s" ? value * 1e3 : value;
78
- }
79
- return 0;
80
- };
81
- if (animationDelays.length === 1 && animationDelays[0]) {
82
- const parsedDelay = parseDelay(animationDelays[0]);
83
- if (parsedDelay > 0) delay = parsedDelay;
84
- else if ((animationDelays[0] === "0s" || animationDelays[0] === "0ms") && delay === 0) delay = 0;
85
- } else if (animationDelays.length > 1) {
86
- const animationIndex = Array.from(target.getAnimations()).indexOf(animation);
87
- if (animationIndex >= 0 && animationIndex < animationDelays.length && animationDelays[animationIndex]) {
88
- const parsedDelay = parseDelay(animationDelays[animationIndex]);
89
- if (parsedDelay > 0) delay = parsedDelay;
90
- }
91
- }
92
- }
93
- const iterations = Number(timing.iterations) || DEFAULT_ANIMATION_ITERATIONS;
94
- if (duration <= 0) {
95
- animation.currentTime = 0;
96
- continue;
97
- }
98
- const currentTime = element.ownCurrentTimeMs ?? 0;
99
- let effectiveDelay = delay;
100
- if (element.tagName === "EF-TEXT-SEGMENT" && element.staggerOffsetMs !== void 0) {
101
- const staggerOffsetMs = element.staggerOffsetMs;
102
- effectiveDelay = delay + staggerOffsetMs;
103
- }
104
- if (currentTime < effectiveDelay) {
105
- animation.currentTime = 0;
106
- continue;
107
- }
108
- const adjustedTime = currentTime - effectiveDelay;
109
- const currentIteration = Math.floor(adjustedTime / duration);
110
- let currentIterationTime = adjustedTime % duration;
111
- const direction = timing.direction || "normal";
112
- const isAlternate = direction === "alternate" || direction === "alternate-reverse";
113
- if (direction === "reverse" || direction === "alternate" && currentIteration % 2 === 1 || direction === "alternate-reverse" && currentIteration % 2 === 0) currentIterationTime = duration - currentIterationTime;
114
- if (currentIteration >= iterations) {
115
- const maxSafeAnimationTime = duration * iterations - ANIMATION_PRECISION_OFFSET;
116
- if (isAlternate) {
117
- const finalIteration = iterations - 1;
118
- if (direction === "alternate" && finalIteration % 2 === 1 || direction === "alternate-reverse" && finalIteration % 2 === 0) animation.currentTime = Math.min(duration - ANIMATION_PRECISION_OFFSET, maxSafeAnimationTime);
119
- else animation.currentTime = maxSafeAnimationTime;
120
- } else animation.currentTime = maxSafeAnimationTime;
121
- } else if (isAlternate) if (effectiveDelay > 0) if (currentIteration === 0) animation.currentTime = currentTime;
122
- else {
123
- const maxSafeAnimationTime = duration * iterations - ANIMATION_PRECISION_OFFSET;
124
- animation.currentTime = Math.min(adjustedTime, maxSafeAnimationTime);
125
- }
126
- else animation.currentTime = currentIterationTime;
127
- else {
128
- const timeWithinAnimation = currentIteration * duration + currentIterationTime;
129
- const maxSafeAnimationTime = duration * iterations - ANIMATION_PRECISION_OFFSET;
130
- animation.currentTime = Math.min(timeWithinAnimation, maxSafeAnimationTime);
131
- }
132
- }
497
+ const applyAnimationCoordination = (element, phase) => {
498
+ if (shouldCoordinateAnimations(phase, element)) coordinateElementAnimations(element);
499
+ };
500
+ /**
501
+ * Evaluates the complete state for an element update.
502
+ * This separates evaluation (what should the state be?) from application (apply that state).
503
+ */
504
+ const evaluateElementState = (element) => {
505
+ return {
506
+ element,
507
+ state: evaluateTemporalState(element)
508
+ };
133
509
  };
134
510
  /**
135
- * Main function: synchronizes DOM element with timeline
511
+ * Main function: synchronizes DOM element with timeline.
512
+ *
513
+ * Orchestrates clear flow: Phase → Policy → Time Mapping → State Application
514
+ *
515
+ * WHY: This function makes the conceptual flow explicit:
516
+ * 1. Determine phase (what phase is the element in?)
517
+ * 2. Apply policies (should it be visible/coordinated based on phase?)
518
+ * 3. Map time for animations (transform element time to animation time)
519
+ * 4. Apply visual state (update CSS and display based on phase and policies)
136
520
  */
137
521
  const updateAnimations = (element) => {
138
- const temporalState = evaluateTemporalState(element);
139
- deepGetTemporalElements(element).forEach((temporalElement) => {
140
- updateVisualState(temporalElement, evaluateTemporalState(temporalElement));
141
- });
142
- updateVisualState(element, temporalState);
143
- if (evaluateTemporalStateForAnimation(element).isVisible) coordinateAnimationsForSingleElement(element);
144
- deepGetTemporalElements(element).forEach((temporalElement) => {
145
- if (evaluateTemporalStateForAnimation(temporalElement).isVisible) coordinateAnimationsForSingleElement(temporalElement);
522
+ const rootContext = evaluateElementState(element);
523
+ const childContexts = deepGetTemporalElements(element).map((temporalElement) => evaluateElementState(temporalElement));
524
+ applyVisualState(rootContext.element, rootContext.state);
525
+ applyAnimationCoordination(rootContext.element, rootContext.state.phase);
526
+ childContexts.forEach((context) => {
527
+ applyVisualState(context.element, context.state);
528
+ applyAnimationCoordination(context.element, context.state.phase);
146
529
  });
147
530
  };
148
531
 
149
532
  //#endregion
150
- export { evaluateTemporalStateForAnimation, updateAnimations };
533
+ export { cleanupTrackedAnimations, evaluateAnimationVisibilityState, updateAnimations };
151
534
  //# sourceMappingURL=updateAnimations.js.map