@editframe/elements 0.24.1-beta.0 → 0.25.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 (335) hide show
  1. package/dist/DelayedLoadingState.js +31 -0
  2. package/dist/DelayedLoadingState.js.map +1 -0
  3. package/dist/EF_FRAMEGEN.d.ts +50 -46
  4. package/dist/EF_FRAMEGEN.js +5 -1
  5. package/dist/EF_FRAMEGEN.js.map +1 -0
  6. package/dist/EF_INTERACTIVE.js +4 -0
  7. package/dist/EF_INTERACTIVE.js.map +1 -0
  8. package/dist/EF_RENDERING.js +4 -0
  9. package/dist/EF_RENDERING.js.map +1 -0
  10. package/dist/_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js +4 -1
  11. package/dist/attachContextRoot.js +6 -1
  12. package/dist/attachContextRoot.js.map +1 -0
  13. package/dist/elements/CrossUpdateController.js +4 -0
  14. package/dist/elements/CrossUpdateController.js.map +1 -0
  15. package/dist/elements/EFAudio.d.ts +24 -16
  16. package/dist/elements/EFAudio.js +10 -1
  17. package/dist/elements/EFAudio.js.map +1 -0
  18. package/dist/elements/EFCaptions.d.ts +118 -109
  19. package/dist/elements/EFCaptions.js +11 -6
  20. package/dist/elements/EFCaptions.js.map +1 -0
  21. package/dist/elements/EFImage.d.ts +31 -20
  22. package/dist/elements/EFImage.js +6 -1
  23. package/dist/elements/EFImage.js.map +1 -0
  24. package/dist/elements/EFMedia/AssetIdMediaEngine.js +5 -0
  25. package/dist/elements/EFMedia/AssetIdMediaEngine.js.map +1 -0
  26. package/dist/elements/EFMedia/AssetMediaEngine.js +12 -0
  27. package/dist/elements/EFMedia/AssetMediaEngine.js.map +1 -0
  28. package/dist/elements/EFMedia/BaseMediaEngine.js +53 -0
  29. package/dist/elements/EFMedia/BaseMediaEngine.js.map +1 -0
  30. package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +47 -46
  31. package/dist/elements/EFMedia/BufferedSeekingInput.js +6 -1
  32. package/dist/elements/EFMedia/BufferedSeekingInput.js.map +1 -0
  33. package/dist/elements/EFMedia/JitMediaEngine.js +12 -0
  34. package/dist/elements/EFMedia/JitMediaEngine.js.map +1 -0
  35. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.d.ts +9 -13
  36. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +5 -0
  37. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js.map +1 -0
  38. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +6 -1
  39. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js.map +1 -0
  40. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js +5 -0
  41. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js.map +1 -0
  42. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +5 -0
  43. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js.map +1 -0
  44. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +5 -0
  45. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js.map +1 -0
  46. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +5 -0
  47. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js.map +1 -0
  48. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +5 -0
  49. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js.map +1 -0
  50. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +6 -1
  51. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js.map +1 -0
  52. package/dist/elements/EFMedia/shared/AudioSpanUtils.js +18 -2
  53. package/dist/elements/EFMedia/shared/AudioSpanUtils.js.map +1 -0
  54. package/dist/elements/EFMedia/shared/BufferUtils.d.ts +9 -67
  55. package/dist/elements/EFMedia/shared/BufferUtils.js +15 -0
  56. package/dist/elements/EFMedia/shared/BufferUtils.js.map +1 -0
  57. package/dist/elements/EFMedia/shared/GlobalInputCache.js +29 -0
  58. package/dist/elements/EFMedia/shared/GlobalInputCache.js.map +1 -0
  59. package/dist/elements/EFMedia/shared/MediaTaskUtils.d.ts +11 -17
  60. package/dist/elements/EFMedia/shared/PrecisionUtils.js +25 -0
  61. package/dist/elements/EFMedia/shared/PrecisionUtils.js.map +1 -0
  62. package/dist/elements/EFMedia/shared/ThumbnailExtractor.js +22 -0
  63. package/dist/elements/EFMedia/shared/ThumbnailExtractor.js.map +1 -0
  64. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js +13 -0
  65. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js.map +1 -0
  66. package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js +21 -0
  67. package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js.map +1 -0
  68. package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js +18 -0
  69. package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js.map +1 -0
  70. package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js +10 -0
  71. package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js.map +1 -0
  72. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.js +5 -0
  73. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.js.map +1 -0
  74. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js +5 -0
  75. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js.map +1 -0
  76. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js +6 -1
  77. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js.map +1 -0
  78. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.js +5 -0
  79. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.js.map +1 -0
  80. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js +5 -0
  81. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js.map +1 -0
  82. package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js +16 -2
  83. package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js.map +1 -0
  84. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.d.ts +9 -13
  85. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +5 -0
  86. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js.map +1 -0
  87. package/dist/elements/EFMedia.d.ts +115 -104
  88. package/dist/elements/EFMedia.js +25 -1
  89. package/dist/elements/EFMedia.js.map +1 -0
  90. package/dist/elements/EFSourceMixin.d.ts +10 -11
  91. package/dist/elements/EFSourceMixin.js +5 -0
  92. package/dist/elements/EFSourceMixin.js.map +1 -0
  93. package/dist/elements/EFSurface.d.ts +35 -27
  94. package/dist/elements/EFSurface.js +6 -1
  95. package/dist/elements/EFSurface.js.map +1 -0
  96. package/dist/elements/EFTemporal.d.ts +200 -213
  97. package/dist/elements/EFTemporal.js +24 -4
  98. package/dist/elements/EFTemporal.js.map +1 -0
  99. package/dist/elements/EFThumbnailStrip.d.ts +91 -83
  100. package/dist/elements/EFThumbnailStrip.js +49 -4
  101. package/dist/elements/EFThumbnailStrip.js.map +1 -0
  102. package/dist/elements/EFTimegroup.d.ts +107 -101
  103. package/dist/elements/EFTimegroup.js +58 -3
  104. package/dist/elements/EFTimegroup.js.map +1 -0
  105. package/dist/elements/EFVideo.d.ts +120 -108
  106. package/dist/elements/EFVideo.js +46 -2
  107. package/dist/elements/EFVideo.js.map +1 -0
  108. package/dist/elements/EFWaveform.d.ts +48 -41
  109. package/dist/elements/EFWaveform.js +6 -1
  110. package/dist/elements/EFWaveform.js.map +1 -0
  111. package/dist/elements/FetchMixin.d.ts +8 -6
  112. package/dist/elements/FetchMixin.js +4 -0
  113. package/dist/elements/FetchMixin.js.map +1 -0
  114. package/dist/elements/SampleBuffer.d.ts +18 -13
  115. package/dist/elements/SampleBuffer.js +5 -0
  116. package/dist/elements/SampleBuffer.js.map +1 -0
  117. package/dist/elements/TargetController.d.ts +23 -24
  118. package/dist/elements/TargetController.js +8 -3
  119. package/dist/elements/TargetController.js.map +1 -0
  120. package/dist/elements/TimegroupController.d.ts +17 -12
  121. package/dist/elements/TimegroupController.js +4 -0
  122. package/dist/elements/TimegroupController.js.map +1 -0
  123. package/dist/elements/durationConverter.js +9 -4
  124. package/dist/elements/durationConverter.js.map +1 -0
  125. package/dist/elements/parseTimeToMs.js +4 -0
  126. package/dist/elements/parseTimeToMs.js.map +1 -0
  127. package/dist/elements/renderTemporalAudio.js +4 -0
  128. package/dist/elements/renderTemporalAudio.js.map +1 -0
  129. package/dist/elements/updateAnimations.js +29 -8
  130. package/dist/elements/updateAnimations.js.map +1 -0
  131. package/dist/elements-ZhsB7B5N.css +9 -0
  132. package/dist/elements-ZhsB7B5N.css.map +1 -0
  133. package/dist/getRenderInfo.d.ts +53 -47
  134. package/dist/getRenderInfo.js +5 -0
  135. package/dist/getRenderInfo.js.map +1 -0
  136. package/dist/gui/ContextMixin.d.ts +19 -20
  137. package/dist/gui/ContextMixin.js +32 -1
  138. package/dist/gui/ContextMixin.js.map +1 -0
  139. package/dist/gui/Controllable.d.ts +13 -14
  140. package/dist/gui/Controllable.js +5 -0
  141. package/dist/gui/Controllable.js.map +1 -0
  142. package/dist/gui/EFConfiguration.d.ts +18 -14
  143. package/dist/gui/EFConfiguration.js +6 -1
  144. package/dist/gui/EFConfiguration.js.map +1 -0
  145. package/dist/gui/EFControls.d.ts +35 -31
  146. package/dist/gui/EFControls.js +8 -3
  147. package/dist/gui/EFControls.js.map +1 -0
  148. package/dist/gui/EFDial.d.ts +23 -16
  149. package/dist/gui/EFDial.js +6 -1
  150. package/dist/gui/EFDial.js.map +1 -0
  151. package/dist/gui/EFFilmstrip.d.ts +183 -177
  152. package/dist/gui/EFFilmstrip.js +30 -25
  153. package/dist/gui/EFFilmstrip.js.map +1 -0
  154. package/dist/gui/EFFitScale.d.ts +30 -24
  155. package/dist/gui/EFFitScale.js +6 -1
  156. package/dist/gui/EFFitScale.js.map +1 -0
  157. package/dist/gui/EFFocusOverlay.d.ts +22 -14
  158. package/dist/gui/EFFocusOverlay.js +6 -1
  159. package/dist/gui/EFFocusOverlay.js.map +1 -0
  160. package/dist/gui/EFPause.d.ts +24 -18
  161. package/dist/gui/EFPause.js +6 -1
  162. package/dist/gui/EFPause.js.map +1 -0
  163. package/dist/gui/EFPlay.d.ts +24 -18
  164. package/dist/gui/EFPlay.js +6 -1
  165. package/dist/gui/EFPlay.js.map +1 -0
  166. package/dist/gui/EFPreview.d.ts +22 -15
  167. package/dist/gui/EFPreview.js +9 -1
  168. package/dist/gui/EFPreview.js.map +1 -0
  169. package/dist/gui/EFResizableBox.d.ts +39 -32
  170. package/dist/gui/EFResizableBox.js +8 -3
  171. package/dist/gui/EFResizableBox.js.map +1 -0
  172. package/dist/gui/EFScrubber.d.ts +31 -25
  173. package/dist/gui/EFScrubber.js +6 -1
  174. package/dist/gui/EFScrubber.js.map +1 -0
  175. package/dist/gui/EFTimeDisplay.d.ts +21 -14
  176. package/dist/gui/EFTimeDisplay.js +6 -1
  177. package/dist/gui/EFTimeDisplay.js.map +1 -0
  178. package/dist/gui/EFToggleLoop.d.ts +19 -13
  179. package/dist/gui/EFToggleLoop.js +6 -1
  180. package/dist/gui/EFToggleLoop.js.map +1 -0
  181. package/dist/gui/EFTogglePlay.d.ts +23 -17
  182. package/dist/gui/EFTogglePlay.js +6 -1
  183. package/dist/gui/EFTogglePlay.js.map +1 -0
  184. package/dist/gui/EFWorkbench.d.ts +24 -16
  185. package/dist/gui/EFWorkbench.js +6 -1
  186. package/dist/gui/EFWorkbench.js.map +1 -0
  187. package/dist/gui/PlaybackController.d.ts +54 -50
  188. package/dist/gui/PlaybackController.js +18 -0
  189. package/dist/gui/PlaybackController.js.map +1 -0
  190. package/dist/gui/TWMixin.js +5 -1
  191. package/dist/gui/TWMixin.js.map +1 -0
  192. package/dist/gui/TWMixin2.js +6 -1
  193. package/dist/gui/TWMixin2.js.map +1 -0
  194. package/dist/gui/TargetOrContextMixin.js +5 -0
  195. package/dist/gui/TargetOrContextMixin.js.map +1 -0
  196. package/dist/gui/currentTimeContext.js +5 -0
  197. package/dist/gui/currentTimeContext.js.map +1 -0
  198. package/dist/gui/durationContext.js +5 -0
  199. package/dist/gui/durationContext.js.map +1 -0
  200. package/dist/gui/efContext.js +5 -0
  201. package/dist/gui/efContext.js.map +1 -0
  202. package/dist/gui/fetchContext.js +5 -0
  203. package/dist/gui/fetchContext.js.map +1 -0
  204. package/dist/gui/focusContext.d.ts +6 -5
  205. package/dist/gui/focusContext.js +5 -0
  206. package/dist/gui/focusContext.js.map +1 -0
  207. package/dist/gui/focusedElementContext.js +5 -0
  208. package/dist/gui/focusedElementContext.js.map +1 -0
  209. package/dist/gui/playingContext.js +5 -0
  210. package/dist/gui/playingContext.js.map +1 -0
  211. package/dist/index.d.ts +27 -26
  212. package/dist/index.js +6 -1
  213. package/dist/index.js.map +1 -0
  214. package/dist/msToTimeCode.js +4 -0
  215. package/dist/msToTimeCode.js.map +1 -0
  216. package/dist/otel/BridgeSpanExporter.js +5 -0
  217. package/dist/otel/BridgeSpanExporter.js.map +1 -0
  218. package/dist/otel/setupBrowserTracing.js +7 -2
  219. package/dist/otel/setupBrowserTracing.js.map +1 -0
  220. package/dist/otel/tracingHelpers.d.ts +7 -34
  221. package/dist/otel/tracingHelpers.js +34 -2
  222. package/dist/otel/tracingHelpers.js.map +1 -0
  223. package/dist/transcoding/cache/RequestDeduplicator.js +25 -0
  224. package/dist/transcoding/cache/RequestDeduplicator.js.map +1 -0
  225. package/dist/transcoding/cache/URLTokenDeduplicator.js +23 -0
  226. package/dist/transcoding/cache/URLTokenDeduplicator.js.map +1 -0
  227. package/dist/transcoding/types/index.d.ts +96 -270
  228. package/dist/transcoding/utils/UrlGenerator.d.ts +30 -25
  229. package/dist/transcoding/utils/UrlGenerator.js +19 -0
  230. package/dist/transcoding/utils/UrlGenerator.js.map +1 -0
  231. package/dist/utils/LRUCache.js +44 -0
  232. package/dist/utils/LRUCache.js.map +1 -0
  233. package/package.json +11 -24
  234. package/tsdown.config.ts +36 -0
  235. package/dist/DelayedLoadingState.d.ts +0 -48
  236. package/dist/DelayedLoadingState.integration.test.d.ts +0 -1
  237. package/dist/DelayedLoadingState.test.d.ts +0 -1
  238. package/dist/EF_INTERACTIVE.d.ts +0 -1
  239. package/dist/EF_RENDERING.d.ts +0 -1
  240. package/dist/LoadingDebounce.test.d.ts +0 -1
  241. package/dist/ManualScrubTest.test.d.ts +0 -1
  242. package/dist/ScrubResolvedFlashing.test.d.ts +0 -1
  243. package/dist/ScrubTrackManager.test.d.ts +0 -1
  244. package/dist/VideoSeekFlashing.browsertest.d.ts +0 -0
  245. package/dist/VideoStuckDiagnostic.test.d.ts +0 -1
  246. package/dist/attachContextRoot.d.ts +0 -1
  247. package/dist/elements/ContextProxiesController.d.ts +0 -39
  248. package/dist/elements/CrossUpdateController.d.ts +0 -8
  249. package/dist/elements/EFAudio.browsertest.d.ts +0 -0
  250. package/dist/elements/EFCaptions.browsertest.d.ts +0 -0
  251. package/dist/elements/EFImage.browsertest.d.ts +0 -0
  252. package/dist/elements/EFMedia/AssetIdMediaEngine.d.ts +0 -19
  253. package/dist/elements/EFMedia/AssetIdMediaEngine.test.d.ts +0 -1
  254. package/dist/elements/EFMedia/AssetMediaEngine.browsertest.d.ts +0 -0
  255. package/dist/elements/EFMedia/AssetMediaEngine.d.ts +0 -56
  256. package/dist/elements/EFMedia/BaseMediaEngine.browsertest.d.ts +0 -1
  257. package/dist/elements/EFMedia/BaseMediaEngine.d.ts +0 -103
  258. package/dist/elements/EFMedia/BufferedSeekingInput.browsertest.d.ts +0 -1
  259. package/dist/elements/EFMedia/JitMediaEngine.browsertest.d.ts +0 -0
  260. package/dist/elements/EFMedia/JitMediaEngine.d.ts +0 -46
  261. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.d.ts +0 -9
  262. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.d.ts +0 -3
  263. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.browsertest.d.ts +0 -9
  264. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.d.ts +0 -4
  265. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.browsertest.d.ts +0 -9
  266. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.d.ts +0 -3
  267. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.d.ts +0 -0
  268. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.d.ts +0 -7
  269. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.d.ts +0 -4
  270. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.d.ts +0 -4
  271. package/dist/elements/EFMedia/audioTasks/makeAudioTasksVideoOnly.browsertest.d.ts +0 -1
  272. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.d.ts +0 -3
  273. package/dist/elements/EFMedia/shared/AudioSpanUtils.d.ts +0 -7
  274. package/dist/elements/EFMedia/shared/GlobalInputCache.d.ts +0 -39
  275. package/dist/elements/EFMedia/shared/PrecisionUtils.d.ts +0 -28
  276. package/dist/elements/EFMedia/shared/RenditionHelpers.browsertest.d.ts +0 -1
  277. package/dist/elements/EFMedia/shared/RenditionHelpers.d.ts +0 -11
  278. package/dist/elements/EFMedia/shared/ThumbnailExtractor.d.ts +0 -27
  279. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.browsertest.d.ts +0 -9
  280. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.d.ts +0 -17
  281. package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.d.ts +0 -29
  282. package/dist/elements/EFMedia/videoTasks/ScrubInputCache.d.ts +0 -25
  283. package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.d.ts +0 -8
  284. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.d.ts +0 -4
  285. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.d.ts +0 -3
  286. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.d.ts +0 -6
  287. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.d.ts +0 -4
  288. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.d.ts +0 -4
  289. package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.d.ts +0 -6
  290. package/dist/elements/EFMedia.browsertest.d.ts +0 -10
  291. package/dist/elements/EFSurface.browsertest.d.ts +0 -0
  292. package/dist/elements/EFTemporal.browsertest.d.ts +0 -22
  293. package/dist/elements/EFThumbnailStrip.browsertest.d.ts +0 -0
  294. package/dist/elements/EFThumbnailStrip.media-engine.browsertest.d.ts +0 -0
  295. package/dist/elements/EFTimegroup.browsertest.d.ts +0 -41
  296. package/dist/elements/EFVideo.browsertest.d.ts +0 -0
  297. package/dist/elements/FetchContext.browsertest.d.ts +0 -0
  298. package/dist/elements/TargetController.browsertest.d.ts +0 -19
  299. package/dist/elements/durationConverter.d.ts +0 -16
  300. package/dist/elements/parseTimeToMs.d.ts +0 -1
  301. package/dist/elements/printTaskStatus.d.ts +0 -2
  302. package/dist/elements/renderTemporalAudio.d.ts +0 -10
  303. package/dist/elements/updateAnimations.browsertest.d.ts +0 -13
  304. package/dist/elements/updateAnimations.d.ts +0 -24
  305. package/dist/elements/util.d.ts +0 -3
  306. package/dist/gui/ContextMixin.browsertest.d.ts +0 -15
  307. package/dist/gui/Controllable.browsertest.d.ts +0 -0
  308. package/dist/gui/EFControls.browsertest.d.ts +0 -11
  309. package/dist/gui/EFDial.browsertest.d.ts +0 -0
  310. package/dist/gui/EFFilmstrip.browsertest.d.ts +0 -11
  311. package/dist/gui/EFPause.browsertest.d.ts +0 -0
  312. package/dist/gui/EFPlay.browsertest.d.ts +0 -0
  313. package/dist/gui/EFResizableBox.browsertest.d.ts +0 -0
  314. package/dist/gui/EFTimeDisplay.browsertest.d.ts +0 -0
  315. package/dist/gui/TWMixin.d.ts +0 -2
  316. package/dist/gui/TargetOrContextMixin.d.ts +0 -10
  317. package/dist/gui/currentTimeContext.d.ts +0 -3
  318. package/dist/gui/durationContext.d.ts +0 -3
  319. package/dist/gui/efContext.d.ts +0 -4
  320. package/dist/gui/fetchContext.d.ts +0 -3
  321. package/dist/gui/focusedElementContext.d.ts +0 -3
  322. package/dist/gui/playingContext.d.ts +0 -6
  323. package/dist/msToTimeCode.d.ts +0 -1
  324. package/dist/otel/BridgeSpanExporter.d.ts +0 -13
  325. package/dist/otel/setupBrowserTracing.d.ts +0 -12
  326. package/dist/style.css +0 -2
  327. package/dist/transcoding/cache/RequestDeduplicator.d.ts +0 -29
  328. package/dist/transcoding/cache/RequestDeduplicator.test.d.ts +0 -1
  329. package/dist/transcoding/cache/URLTokenDeduplicator.d.ts +0 -38
  330. package/dist/transcoding/cache/URLTokenDeduplicator.test.d.ts +0 -1
  331. package/dist/transcoding/utils/MediaUtils.d.ts +0 -9
  332. package/dist/transcoding/utils/constants.d.ts +0 -27
  333. package/dist/utils/LRUCache.d.ts +0 -80
  334. package/dist/utils/LRUCache.test.d.ts +0 -1
  335. /package/dist/{LoadingIndicator.browsertest.d.ts → elements.js} +0 -0
@@ -5,9 +5,11 @@ import { __decorate } from "../_virtual/_@oxc-project_runtime@0.94.0/helpers/dec
5
5
  import { consume, createContext } from "@lit/context";
6
6
  import { Task } from "@lit/task";
7
7
  import { property, state } from "lit/decorators.js";
8
+
9
+ //#region src/elements/EFTemporal.ts
8
10
  const timegroupContext = createContext(Symbol("timeGroupContext"));
9
11
  const isEFTemporal = (obj) => obj[EF_TEMPORAL];
10
- var EF_TEMPORAL = Symbol("EF_TEMPORAL");
12
+ const EF_TEMPORAL = Symbol("EF_TEMPORAL");
11
13
  const deepGetTemporalElements = (element, temporals = []) => {
12
14
  for (const child of element.children) {
13
15
  if (isEFTemporal(child)) temporals.push(child);
@@ -22,7 +24,7 @@ const deepGetElementsWithFrameTasks = (element, elements = []) => {
22
24
  }
23
25
  return elements;
24
26
  };
25
- var temporalCache;
27
+ let temporalCache;
26
28
  const resetTemporalCache = () => {
27
29
  temporalCache = /* @__PURE__ */ new Map();
28
30
  if (typeof requestAnimationFrame !== "undefined") requestAnimationFrame(resetTemporalCache);
@@ -49,8 +51,8 @@ var OwnCurrentTimeController = class {
49
51
  this.host.removeController(this);
50
52
  }
51
53
  };
52
- var startTimeMsCache = /* @__PURE__ */ new WeakMap();
53
- var resetStartTimeMsCache = () => {
54
+ let startTimeMsCache = /* @__PURE__ */ new WeakMap();
55
+ const resetStartTimeMsCache = () => {
54
56
  startTimeMsCache = /* @__PURE__ */ new WeakMap();
55
57
  if (typeof requestAnimationFrame !== "undefined") requestAnimationFrame(resetStartTimeMsCache);
56
58
  };
@@ -215,6 +217,9 @@ const EFTemporal = (superClass) => {
215
217
  while (parent && !isEFTemporal(parent)) parent = parent.parentElement;
216
218
  return parent;
217
219
  }
220
+ /**
221
+ * The start time of the element within its parent timegroup.
222
+ */
218
223
  get startTimeWithinParentMs() {
219
224
  if (!this.parentTemporal) return 0;
220
225
  return this.startTimeMs - this.parentTemporal.startTimeMs;
@@ -260,11 +265,19 @@ const EFTemporal = (superClass) => {
260
265
  return this.startTimeMs + this.durationMs;
261
266
  }
262
267
  #currentTimeMs = 0;
268
+ /**
269
+ * The current time of the element within itself.
270
+ * Compare with `currentTimeMs` to see the current time with respect to the root timegroup
271
+ */
263
272
  get ownCurrentTimeMs() {
264
273
  if (this.playbackController) return Math.min(Math.max(0, this.playbackController.currentTimeMs), this.durationMs);
265
274
  if (this.rootTimegroup && this.rootTimegroup !== this) return Math.min(Math.max(0, this.rootTimegroup.currentTimeMs - this.startTimeMs), this.durationMs);
266
275
  return Math.min(Math.max(0, this.#currentTimeMs), this.durationMs);
267
276
  }
277
+ /**
278
+ * Element's current time for progress calculation.
279
+ * Non-timegroup temporal elements use their local time (ownCurrentTimeMs)
280
+ */
268
281
  get currentTimeMs() {
269
282
  return this.ownCurrentTimeMs;
270
283
  }
@@ -279,6 +292,10 @@ const EFTemporal = (superClass) => {
279
292
  this.requestUpdate("currentTimeMs");
280
293
  }
281
294
  }
295
+ /**
296
+ * Used to calculate the internal currentTimeMs of the element. This is useful
297
+ * for mapping to internal media time codes for audio/video elements.
298
+ */
282
299
  get currentSourceTimeMs() {
283
300
  const leadingTrimMs = this.sourceInMs || this.trimStartMs || 0;
284
301
  return this.ownCurrentTimeMs + leadingTrimMs;
@@ -344,4 +361,7 @@ const EFTemporal = (superClass) => {
344
361
  Object.defineProperty(TemporalMixinClass.prototype, EF_TEMPORAL, { value: true });
345
362
  return TemporalMixinClass;
346
363
  };
364
+
365
+ //#endregion
347
366
  export { EFTemporal, deepGetElementsWithFrameTasks, deepGetTemporalElements, flushStartTimeMsCache, isEFTemporal, resetTemporalCache, shallowGetTemporalElements, timegroupContext };
367
+ //# sourceMappingURL=EFTemporal.js.map
@@ -0,0 +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[]>;\nexport const resetTemporalCache = () => {\n temporalCache = new Map();\n if (typeof requestAnimationFrame !== \"undefined\") {\n requestAnimationFrame(resetTemporalCache);\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>();\nconst resetStartTimeMsCache = () => {\n startTimeMsCache = new WeakMap();\n if (typeof requestAnimationFrame !== \"undefined\") {\n requestAnimationFrame(resetStartTimeMsCache);\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,86 +1,94 @@
1
- import { LitElement } from 'lit';
2
- import { EFVideo } from './EFVideo.js';
3
- export declare class EFThumbnailStrip extends LitElement {
4
- static styles: import('lit').CSSResult[];
5
- canvasRef: import('lit-html/directives/ref').Ref<HTMLCanvasElement>;
6
- private _targetController;
7
- private _targetElement;
8
- get targetElement(): EFVideo | null;
9
- set targetElement(value: EFVideo | null);
10
- target: string;
11
- /**
12
- * Desired thumbnail width in pixels (height is determined by aspect ratio)
13
- * Number of thumbnails is derived from this and available strip width
14
- */
15
- thumbnailWidth: number;
16
- /**
17
- * Custom start time in milliseconds relative to trimmed timeline (0 = start of trimmed portion)
18
- * In trimmed mode: 0ms = sourceStartMs, 1000ms = sourceStartMs + 1000ms
19
- * In intrinsic mode: 0ms = 0ms in source media
20
- */
21
- startTimeMs?: number;
22
- /**
23
- * Custom end time in milliseconds relative to trimmed timeline
24
- * In trimmed mode: relative to sourceStartMs
25
- * In intrinsic mode: relative to source media start (0ms)
26
- */
27
- endTimeMs?: number;
28
- /**
29
- * Use intrinsic duration instead of trimmed duration
30
- * Accepts "true"/"false" string values or boolean
31
- */
32
- useIntrinsicDuration: boolean;
33
- private _stripWidth;
34
- private _stripHeight;
35
- private _pendingStripWidth;
36
- private _thumbnailLayoutTask;
37
- private set stripWidth(value);
38
- private get stripWidth();
39
- /**
40
- * Run thumbnail render task directly with provided layout (bypasses task args dependency)
41
- */
42
- private runThumbnailRenderTask;
43
- private resizeObserver?;
44
- private _thumbnailUpdateInProgress;
45
- private _pendingThumbnailUpdate;
46
- private _videoPropertyObserver?;
47
- updated(changedProperties: Map<string | number | symbol, unknown>): void;
48
- /**
49
- * Run thumbnail update with responsive debouncing (based on EFTimegroup currentTime pattern)
50
- */
51
- private runThumbnailUpdate;
52
- private thumbnailLayoutTask;
53
- /**
54
- * Calculate layout with a ready media engine
55
- */
56
- private calculateLayoutWithMediaEngine;
57
- /**
58
- * Generate layout from calculated time range
59
- */
60
- private generateLayoutFromTimeRange;
61
- private thumbnailRenderTask;
62
- /**
63
- * Render thumbnails with provided layout (main rendering logic)
64
- */
65
- private renderThumbnails;
66
- connectedCallback(): void;
67
- disconnectedCallback(): void;
68
- /**
69
- * Draw thumbnails to the canvas with cache hits and placeholders
70
- */
71
- private drawThumbnails;
72
- /**
73
- * Load missing thumbnails using MediaEngine batch extraction
74
- */
75
- private loadMissingThumbnails;
76
- /**
77
- * Convert Canvas to ImageData for caching
78
- */
79
- private canvasToImageData;
80
- render(): import('lit-html').TemplateResult<1>;
1
+ import { EFVideo } from "./EFVideo.js";
2
+ import * as lit25 from "lit";
3
+ import { LitElement } from "lit";
4
+ import * as lit_html22 from "lit-html";
5
+ import * as lit_html_directives_ref6 from "lit-html/directives/ref";
6
+
7
+ //#region src/elements/EFThumbnailStrip.d.ts
8
+ declare class EFThumbnailStrip extends LitElement {
9
+ static styles: lit25.CSSResult[];
10
+ canvasRef: lit_html_directives_ref6.Ref<HTMLCanvasElement>;
11
+ private _targetController;
12
+ private _targetElement;
13
+ get targetElement(): EFVideo | null;
14
+ set targetElement(value: EFVideo | null);
15
+ target: string;
16
+ /**
17
+ * Desired thumbnail width in pixels (height is determined by aspect ratio)
18
+ * Number of thumbnails is derived from this and available strip width
19
+ */
20
+ thumbnailWidth: number;
21
+ /**
22
+ * Custom start time in milliseconds relative to trimmed timeline (0 = start of trimmed portion)
23
+ * In trimmed mode: 0ms = sourceStartMs, 1000ms = sourceStartMs + 1000ms
24
+ * In intrinsic mode: 0ms = 0ms in source media
25
+ */
26
+ startTimeMs?: number;
27
+ /**
28
+ * Custom end time in milliseconds relative to trimmed timeline
29
+ * In trimmed mode: relative to sourceStartMs
30
+ * In intrinsic mode: relative to source media start (0ms)
31
+ */
32
+ endTimeMs?: number;
33
+ /**
34
+ * Use intrinsic duration instead of trimmed duration
35
+ * Accepts "true"/"false" string values or boolean
36
+ */
37
+ useIntrinsicDuration: boolean;
38
+ private _stripWidth;
39
+ private _stripHeight;
40
+ private _pendingStripWidth;
41
+ private _thumbnailLayoutTask;
42
+ private set stripWidth(value);
43
+ private get stripWidth();
44
+ /**
45
+ * Run thumbnail render task directly with provided layout (bypasses task args dependency)
46
+ */
47
+ private runThumbnailRenderTask;
48
+ private resizeObserver?;
49
+ private _thumbnailUpdateInProgress;
50
+ private _pendingThumbnailUpdate;
51
+ private _videoPropertyObserver?;
52
+ updated(changedProperties: Map<string | number | symbol, unknown>): void;
53
+ /**
54
+ * Run thumbnail update with responsive debouncing (based on EFTimegroup currentTime pattern)
55
+ */
56
+ private runThumbnailUpdate;
57
+ private thumbnailLayoutTask;
58
+ /**
59
+ * Calculate layout with a ready media engine
60
+ */
61
+ private calculateLayoutWithMediaEngine;
62
+ /**
63
+ * Generate layout from calculated time range
64
+ */
65
+ private generateLayoutFromTimeRange;
66
+ private thumbnailRenderTask;
67
+ /**
68
+ * Render thumbnails with provided layout (main rendering logic)
69
+ */
70
+ private renderThumbnails;
71
+ connectedCallback(): void;
72
+ disconnectedCallback(): void;
73
+ /**
74
+ * Draw thumbnails to the canvas with cache hits and placeholders
75
+ */
76
+ private drawThumbnails;
77
+ /**
78
+ * Load missing thumbnails using MediaEngine batch extraction
79
+ */
80
+ private loadMissingThumbnails;
81
+ /**
82
+ * Convert Canvas to ImageData for caching
83
+ */
84
+ private canvasToImageData;
85
+ render(): lit_html22.TemplateResult<1>;
81
86
  }
82
87
  declare global {
83
- interface HTMLElementTagNameMap {
84
- "ef-thumbnail-strip": EFThumbnailStrip;
85
- }
88
+ interface HTMLElementTagNameMap {
89
+ "ef-thumbnail-strip": EFThumbnailStrip;
90
+ }
86
91
  }
92
+ //#endregion
93
+ export { EFThumbnailStrip };
94
+ //# sourceMappingURL=EFThumbnailStrip.d.ts.map
@@ -5,21 +5,39 @@ import { Task } from "@lit/task";
5
5
  import { LitElement, css, html } from "lit";
6
6
  import { customElement, property, state } from "lit/decorators.js";
7
7
  import { createRef, ref } from "lit/directives/ref.js";
8
- var thumbnailImageCache = new OrderedLRUCache(200, (a, b) => {
8
+
9
+ //#region src/elements/EFThumbnailStrip.ts
10
+ /**
11
+ * Global thumbnail image cache for smooth resize performance
12
+ * Shared across all thumbnail strip instances
13
+ * Uses OrderedLRUCache for efficient timestamp-based searching
14
+ */
15
+ const thumbnailImageCache = new OrderedLRUCache(200, (a, b) => {
9
16
  const partsA = a.split(":");
10
17
  const partsB = b.split(":");
11
18
  return Number.parseFloat(partsA[partsA.length - 1] || "0") - Number.parseFloat(partsB[partsB.length - 1] || "0");
12
19
  });
13
20
  globalThis.debugThumbnailCache = thumbnailImageCache;
21
+ /**
22
+ * Quantize timestamp to 30fps frame boundaries for consistent caching
23
+ * This eliminates cache misses from floating point precision differences
24
+ */
14
25
  function quantizeTimestamp(timeMs) {
15
26
  const frameIntervalMs = 1e3 / 30;
16
27
  return Math.round(timeMs / frameIntervalMs) * frameIntervalMs;
17
28
  }
29
+ /**
30
+ * Generate cache key for thumbnail image data (dimension-independent, quantized)
31
+ */
18
32
  function getThumbnailCacheKey(videoSrc, timeMs) {
19
33
  return `${videoSrc}:${quantizeTimestamp(timeMs)}`;
20
34
  }
21
- var THUMBNAIL_GAP = 1;
22
- var STRIP_BORDER_PADDING = 4;
35
+ const THUMBNAIL_GAP = 1;
36
+ const STRIP_BORDER_PADDING = 4;
37
+ /**
38
+ * Calculate optimal thumbnail count and timestamps for the strip
39
+ * Groups thumbnails by scrub segment ID for efficient caching
40
+ */
23
41
  function calculateThumbnailLayout(stripWidth, thumbnailWidth, startTimeMs, endTimeMs, scrubSegmentDurationMs) {
24
42
  if (stripWidth <= 0 || thumbnailWidth <= 0 || endTimeMs <= startTimeMs) return {
25
43
  count: 0,
@@ -48,7 +66,7 @@ function calculateThumbnailLayout(stripWidth, thumbnailWidth, startTimeMs, endTi
48
66
  }))
49
67
  };
50
68
  }
51
- var EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
69
+ let EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
52
70
  constructor(..._args) {
53
71
  super(..._args);
54
72
  this.canvasRef = createRef();
@@ -201,6 +219,9 @@ var EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
201
219
  get stripWidth() {
202
220
  return this._stripWidth;
203
221
  }
222
+ /**
223
+ * Run thumbnail render task directly with provided layout (bypasses task args dependency)
224
+ */
204
225
  async runThumbnailRenderTask(layout) {
205
226
  if (!layout || !this.targetElement || layout.count === 0) return [];
206
227
  return this.renderThumbnails(layout, this.targetElement, this.thumbnailWidth);
@@ -213,6 +234,9 @@ var EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
213
234
  }
214
235
  if (changedProperties.has("thumbnailWidth") || changedProperties.has("startTimeMs") || changedProperties.has("endTimeMs") || changedProperties.has("useIntrinsicDuration")) this.runThumbnailUpdate();
215
236
  }
237
+ /**
238
+ * Run thumbnail update with responsive debouncing (based on EFTimegroup currentTime pattern)
239
+ */
216
240
  runThumbnailUpdate() {
217
241
  if (this._thumbnailUpdateInProgress) {
218
242
  this._pendingThumbnailUpdate = true;
@@ -231,6 +255,9 @@ var EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
231
255
  }
232
256
  });
233
257
  }
258
+ /**
259
+ * Calculate layout with a ready media engine
260
+ */
234
261
  calculateLayoutWithMediaEngine(stripWidth, thumbnailWidth, targetElement, startTimeMs, endTimeMs, useIntrinsicDuration, mediaEngine) {
235
262
  if (useIntrinsicDuration) {
236
263
  const effectiveStartMs$1 = startTimeMs ?? 0;
@@ -243,9 +270,15 @@ var EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
243
270
  const effectiveEndMs = endTimeMs !== void 0 ? sourceStart + endTimeMs : sourceStart + trimmedDuration;
244
271
  return this.generateLayoutFromTimeRange(stripWidth, thumbnailWidth, effectiveStartMs, effectiveEndMs, mediaEngine);
245
272
  }
273
+ /**
274
+ * Generate layout from calculated time range
275
+ */
246
276
  generateLayoutFromTimeRange(stripWidth, thumbnailWidth, effectiveStartMs, effectiveEndMs, mediaEngine) {
247
277
  return calculateThumbnailLayout(stripWidth, thumbnailWidth, effectiveStartMs, effectiveEndMs, mediaEngine && typeof mediaEngine.getScrubVideoRendition === "function" ? mediaEngine.getScrubVideoRendition()?.segmentDurationMs : void 0);
248
278
  }
279
+ /**
280
+ * Render thumbnails with provided layout (main rendering logic)
281
+ */
249
282
  async renderThumbnails(layout, targetElement, thumbnailWidth) {
250
283
  if (!layout || !targetElement || layout.count === 0) return [];
251
284
  const videoSrc = targetElement.src;
@@ -317,6 +350,9 @@ var EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
317
350
  this._videoPropertyObserver?.disconnect();
318
351
  this._videoPropertyObserver = void 0;
319
352
  }
353
+ /**
354
+ * Draw thumbnails to the canvas with cache hits and placeholders
355
+ */
320
356
  async drawThumbnails(thumbnails) {
321
357
  const canvas = this.canvasRef.value;
322
358
  if (!canvas) return;
@@ -370,6 +406,9 @@ var EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
370
406
  ctx.setLineDash([]);
371
407
  }
372
408
  }
409
+ /**
410
+ * Load missing thumbnails using MediaEngine batch extraction
411
+ */
373
412
  async loadMissingThumbnails(thumbnails, targetElement) {
374
413
  const mediaEngine = targetElement.mediaEngineTask?.value;
375
414
  if (!mediaEngine) return;
@@ -393,6 +432,9 @@ var EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
393
432
  }
394
433
  await this.drawThumbnails(thumbnails);
395
434
  }
435
+ /**
436
+ * Convert Canvas to ImageData for caching
437
+ */
396
438
  canvasToImageData(canvas) {
397
439
  const ctx = canvas.getContext("2d");
398
440
  if (!ctx) return null;
@@ -437,4 +479,7 @@ __decorate([property({
437
479
  })], EFThumbnailStrip.prototype, "useIntrinsicDuration", void 0);
438
480
  __decorate([state()], EFThumbnailStrip.prototype, "stripWidth", null);
439
481
  EFThumbnailStrip = __decorate([customElement("ef-thumbnail-strip")], EFThumbnailStrip);
482
+
483
+ //#endregion
440
484
  export { EFThumbnailStrip };
485
+ //# sourceMappingURL=EFThumbnailStrip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EFThumbnailStrip.js","names":["timestamps: number[]","EFThumbnailStrip","effectiveStartMs","effectiveEndMs","allThumbnails: ThumbnailRenderInfo[]","status: ThumbnailRenderInfo[\"status\"]","nearHitKey: string | undefined","drawWidth: number","drawHeight: number","drawX: number","drawY: number"],"sources":["../../src/elements/EFThumbnailStrip.ts"],"sourcesContent":["import { Task } from \"@lit/task\";\nimport { css, html, LitElement } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { createRef, ref } from \"lit/directives/ref.js\";\nimport type { MediaEngine as ImportedMediaEngine } from \"../transcoding/types/index.js\";\nimport { OrderedLRUCache } from \"../utils/LRUCache.js\";\nimport type { EFVideo } from \"./EFVideo.js\";\nimport { TargetController } from \"./TargetController.ts\";\n\n/**\n * Global thumbnail image cache for smooth resize performance\n * Shared across all thumbnail strip instances\n * Uses OrderedLRUCache for efficient timestamp-based searching\n */\nconst thumbnailImageCache = new OrderedLRUCache<string, ImageData>(\n 200,\n (a, b) => {\n // Extract timestamp from cache key for ordered searching (take last part after splitting on ':')\n const partsA = a.split(\":\");\n const partsB = b.split(\":\");\n const timeA = Number.parseFloat(partsA[partsA.length - 1] || \"0\");\n const timeB = Number.parseFloat(partsB[partsB.length - 1] || \"0\");\n return timeA - timeB;\n },\n);\n\n// Export for debugging (works in both browser and server)\n(\n globalThis as typeof globalThis & {\n debugThumbnailCache: typeof thumbnailImageCache;\n }\n).debugThumbnailCache = thumbnailImageCache;\n\n/**\n * Quantize timestamp to 30fps frame boundaries for consistent caching\n * This eliminates cache misses from floating point precision differences\n */\nfunction quantizeTimestamp(timeMs: number): number {\n const frameIntervalMs = 1000 / 30; // 33.33ms at 30fps\n return Math.round(timeMs / frameIntervalMs) * frameIntervalMs;\n}\n\n/**\n * Generate cache key for thumbnail image data (dimension-independent, quantized)\n */\nfunction getThumbnailCacheKey(videoSrc: string, timeMs: number): string {\n const quantizedTimeMs = quantizeTimestamp(timeMs);\n return `${videoSrc}:${quantizedTimeMs}`;\n}\n\n// Constants for consistent thumbnail layout\nconst THUMBNAIL_GAP = 1; // 1px gap between thumbnails\nconst STRIP_BORDER_PADDING = 4; // Account for border/padding in available height\n\ninterface ThumbnailSegment {\n segmentId: number;\n thumbnails: Array<{\n timeMs: number;\n }>;\n}\n\ninterface ThumbnailLayout {\n count: number;\n segments: readonly ThumbnailSegment[];\n}\n\n// Use the imported MediaEngine type and mediabunny types\n\ninterface ThumbnailRenderInfo {\n timeMs: number;\n segmentId: number;\n x: number;\n width: number;\n height: number;\n status: \"exact-hit\" | \"near-hit\" | \"missing\" | \"loading\";\n imageData?: ImageData;\n nearHitKey?: string;\n}\n\n/**\n * Calculate optimal thumbnail count and timestamps for the strip\n * Groups thumbnails by scrub segment ID for efficient caching\n */\nfunction calculateThumbnailLayout(\n stripWidth: number,\n thumbnailWidth: number,\n startTimeMs: number,\n endTimeMs: number,\n scrubSegmentDurationMs?: number,\n): ThumbnailLayout {\n // Must have positive width and valid time range\n if (stripWidth <= 0 || thumbnailWidth <= 0 || endTimeMs <= startTimeMs) {\n return { count: 0, segments: [] };\n }\n\n // Simple calculation: how many full thumbnails fit, plus one more to fill the width\n const thumbnailPitch = thumbnailWidth + THUMBNAIL_GAP;\n const baseFitCount = Math.floor(stripWidth / thumbnailPitch);\n const count = Math.max(1, baseFitCount + 1); // Always one extra to fill width\n\n // Generate timestamps evenly distributed across time range\n const timestamps: number[] = [];\n const timeRange = endTimeMs - startTimeMs;\n\n for (let i = 0; i < count; i++) {\n const timeMs =\n count === 1\n ? (startTimeMs + endTimeMs) / 2\n : startTimeMs + (i * timeRange) / (count - 1);\n timestamps.push(timeMs);\n }\n\n // Group by segment ID\n const segmentMap = new Map<number, Array<{ timeMs: number }>>();\n for (const timeMs of timestamps) {\n const segmentId = scrubSegmentDurationMs\n ? Math.floor(timeMs / scrubSegmentDurationMs)\n : 0;\n if (!segmentMap.has(segmentId)) {\n segmentMap.set(segmentId, []);\n }\n // biome-ignore lint/style/noNonNullAssertion: Set in line above\n segmentMap.get(segmentId)!.push({ timeMs });\n }\n\n const segments = Array.from(segmentMap.entries())\n .sort(([a], [b]) => a - b)\n .map(([segmentId, thumbnails]) => ({ segmentId, thumbnails }));\n\n return { count, segments };\n}\n\n@customElement(\"ef-thumbnail-strip\")\nexport class EFThumbnailStrip extends LitElement {\n static styles = [\n css`\n :host {\n display: block;\n position: relative;\n width: 100%;\n height: 48px; /* Default filmstrip height */\n background: #2a2a2a;\n border: 2px solid #333;\n border-radius: 6px;\n overflow: hidden;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);\n }\n canvas {\n display: block;\n position: absolute;\n top: 0;\n left: 0;\n image-rendering: pixelated; /* Keep thumbnails crisp */\n /* Width and height set programmatically to prevent CSS scaling */\n }\n .loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(42, 42, 42, 0.9);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n color: #ccc;\n font-weight: 500;\n }\n `,\n ];\n\n canvasRef = createRef<HTMLCanvasElement>();\n\n // Target video element using the same pattern as EFSurface\n // @ts-expect-error controller is intentionally not referenced directly to prevent GC\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: Used for side effects\n private _targetController: TargetController = new TargetController(\n this as any,\n );\n\n private _targetElement: EFVideo | null = null;\n\n @state()\n get targetElement(): EFVideo | null {\n return this._targetElement;\n }\n\n set targetElement(value: EFVideo | null) {\n const oldValue = this._targetElement;\n this._targetElement = value;\n\n // Clean up previous video property observer\n this._videoPropertyObserver?.disconnect();\n\n // When target element changes, set up property watching and media engine listener\n if (value && value !== oldValue) {\n // Watch for video property changes that affect thumbnails\n this._videoPropertyObserver = new MutationObserver((mutations) => {\n let shouldUpdate = false;\n for (const mutation of mutations) {\n if (mutation.type === \"attributes\" && mutation.attributeName) {\n const attr = mutation.attributeName;\n if (\n attr === \"trimstart\" ||\n attr === \"trimend\" ||\n attr === \"sourcein\" ||\n attr === \"sourceout\" ||\n attr === \"src\"\n ) {\n shouldUpdate = true;\n break;\n }\n }\n }\n if (shouldUpdate) {\n this.runThumbnailUpdate();\n }\n });\n\n this._videoPropertyObserver.observe(value, {\n attributes: true,\n attributeFilter: [\n \"trimstart\",\n \"trimend\",\n \"sourcein\",\n \"sourceout\",\n \"src\",\n ],\n });\n\n // Listen for media engine ready\n if (value.mediaEngineTask) {\n value.mediaEngineTask.taskComplete\n .then(() => {\n // When media engine is ready, retrigger thumbnails if we have width\n if (this._stripWidth > 0) {\n this.thumbnailLayoutTask.run();\n }\n })\n .catch(() => {\n // Ignore media engine errors\n });\n }\n }\n\n this.requestUpdate(\"targetElement\", oldValue);\n }\n\n @property({ type: String })\n target = \"\";\n\n /**\n * Desired thumbnail width in pixels (height is determined by aspect ratio)\n * Number of thumbnails is derived from this and available strip width\n */\n @property({ type: Number, attribute: \"thumbnail-width\" })\n thumbnailWidth = 80;\n\n /**\n * Custom start time in milliseconds relative to trimmed timeline (0 = start of trimmed portion)\n * In trimmed mode: 0ms = sourceStartMs, 1000ms = sourceStartMs + 1000ms\n * In intrinsic mode: 0ms = 0ms in source media\n */\n @property({ type: Number, attribute: \"start-time-ms\" })\n startTimeMs?: number;\n\n /**\n * Custom end time in milliseconds relative to trimmed timeline\n * In trimmed mode: relative to sourceStartMs\n * In intrinsic mode: relative to source media start (0ms)\n */\n @property({ type: Number, attribute: \"end-time-ms\" })\n endTimeMs?: number;\n\n /**\n * Use intrinsic duration instead of trimmed duration\n * Accepts \"true\"/\"false\" string values or boolean\n */\n @property({\n type: Boolean,\n attribute: \"use-intrinsic-duration\",\n reflect: true,\n converter: {\n fromAttribute: (value: string | null) => {\n if (value === null) return false;\n return value === \"true\";\n },\n toAttribute: (value: boolean) => (value ? \"true\" : null),\n },\n })\n useIntrinsicDuration = false;\n\n private _stripWidth = 0;\n private _stripHeight = 48; // Default height, updated by ResizeObserver\n private _pendingStripWidth: number | undefined;\n private _thumbnailLayoutTask: Promise<ThumbnailRenderInfo[]> | undefined;\n @state()\n private set stripWidth(value: number) {\n if (this._thumbnailLayoutTask) {\n this._pendingStripWidth = value;\n return;\n }\n this._stripWidth = value;\n\n if (value > 0) {\n this._thumbnailLayoutTask = this.thumbnailLayoutTask\n .run()\n .then(async () => {\n // Use taskComplete and .value instead of promise return value\n await this.thumbnailLayoutTask.taskComplete;\n const layout = this.thumbnailLayoutTask.value;\n return layout ? this.runThumbnailRenderTask(layout) : [];\n })\n .finally(() => {\n this._thumbnailLayoutTask = undefined;\n if (this._pendingStripWidth) {\n this.stripWidth = this._pendingStripWidth;\n this._pendingStripWidth = undefined;\n }\n });\n }\n }\n private get stripWidth() {\n return this._stripWidth;\n }\n\n /**\n * Run thumbnail render task directly with provided layout (bypasses task args dependency)\n */\n private async runThumbnailRenderTask(\n layout: ThumbnailLayout,\n ): Promise<ThumbnailRenderInfo[]> {\n if (!layout || !this.targetElement || layout.count === 0) {\n return [];\n }\n\n // Run the thumbnail render task logic directly\n return this.renderThumbnails(\n layout,\n this.targetElement,\n this.thumbnailWidth,\n );\n }\n\n private resizeObserver?: ResizeObserver;\n private _thumbnailUpdateInProgress = false;\n private _pendingThumbnailUpdate = false;\n private _videoPropertyObserver?: MutationObserver;\n\n updated(changedProperties: Map<string | number | symbol, unknown>) {\n super.updated(changedProperties);\n\n // IMPLEMENTATION GUIDELINES: Fix for initial loading bug - ensure width is detected\n if (this._stripWidth === 0) {\n const width = this.clientWidth;\n if (width > 0) {\n this.stripWidth = width;\n }\n }\n\n // IMPLEMENTATION GUIDELINES: Responsive debouncing for thumbnail property changes using EFTimegroup pattern\n if (\n changedProperties.has(\"thumbnailWidth\") ||\n changedProperties.has(\"startTimeMs\") ||\n changedProperties.has(\"endTimeMs\") ||\n changedProperties.has(\"useIntrinsicDuration\")\n ) {\n this.runThumbnailUpdate();\n }\n }\n\n /**\n * Run thumbnail update with responsive debouncing (based on EFTimegroup currentTime pattern)\n */\n private runThumbnailUpdate() {\n // If update already in progress, just flag that another update is needed\n if (this._thumbnailUpdateInProgress) {\n this._pendingThumbnailUpdate = true;\n return;\n }\n\n this._thumbnailUpdateInProgress = true;\n\n // Trigger full layout→render pipeline immediately for responsiveness\n this.thumbnailLayoutTask\n .run()\n .then(async () => {\n await this.thumbnailLayoutTask.taskComplete;\n const layout = this.thumbnailLayoutTask.value;\n if (layout) {\n await this.runThumbnailRenderTask(layout);\n }\n })\n .catch(() => {\n // Ignore errors - thumbnails will show as placeholders\n })\n .finally(() => {\n this._thumbnailUpdateInProgress = false;\n\n // If more property changes came in while we were processing, run another update\n if (this._pendingThumbnailUpdate) {\n this._pendingThumbnailUpdate = false;\n this.runThumbnailUpdate();\n }\n });\n }\n\n private thumbnailLayoutTask = new Task(this, {\n autoRun: false,\n task: async ([\n stripWidth,\n thumbnailWidth,\n targetElement,\n startTimeMs,\n endTimeMs,\n useIntrinsicDuration,\n mediaEngine,\n ]: readonly [\n number,\n number,\n EFVideo | null,\n number | undefined,\n number | undefined,\n boolean,\n ImportedMediaEngine | null | undefined,\n ]) => {\n // Need valid dimensions and target element\n if (stripWidth <= 0 || !targetElement) {\n return { count: 0, segments: [] };\n }\n\n // IMPLEMENTATION GUIDELINES: Wait for media engine to be ready before generating thumbnails\n if (!mediaEngine) {\n // If no media engine yet, wait for it to be ready\n if (targetElement.mediaEngineTask) {\n await targetElement.mediaEngineTask.taskComplete;\n // Get the media engine after it's ready\n const readyMediaEngine = targetElement.mediaEngineTask.value;\n if (!readyMediaEngine) {\n return { count: 0, segments: [] };\n }\n // Continue with the ready media engine\n return this.calculateLayoutWithMediaEngine(\n stripWidth,\n thumbnailWidth,\n targetElement,\n startTimeMs,\n endTimeMs,\n useIntrinsicDuration,\n readyMediaEngine,\n );\n }\n return { count: 0, segments: [] };\n }\n\n // Media engine is ready, proceed with layout calculation\n return this.calculateLayoutWithMediaEngine(\n stripWidth,\n thumbnailWidth,\n targetElement,\n startTimeMs,\n endTimeMs,\n useIntrinsicDuration,\n mediaEngine,\n );\n },\n args: () =>\n [\n this.stripWidth,\n this.thumbnailWidth,\n this.targetElement,\n this.startTimeMs,\n this.endTimeMs,\n this.useIntrinsicDuration,\n this.targetElement?.mediaEngineTask?.value,\n ] as const,\n });\n\n /**\n * Calculate layout with a ready media engine\n */\n private calculateLayoutWithMediaEngine(\n stripWidth: number,\n thumbnailWidth: number,\n targetElement: EFVideo,\n startTimeMs: number | undefined,\n endTimeMs: number | undefined,\n useIntrinsicDuration: boolean,\n mediaEngine: ImportedMediaEngine,\n ) {\n // Determine time range for thumbnails with correct timeline coordinate handling\n if (useIntrinsicDuration) {\n // INTRINSIC MODE: start-time-ms/end-time-ms are relative to source timeline (0 = source start)\n const effectiveStartMs = startTimeMs ?? 0;\n const effectiveEndMs =\n endTimeMs ?? targetElement.intrinsicDurationMs ?? 0;\n\n return this.generateLayoutFromTimeRange(\n stripWidth,\n thumbnailWidth,\n effectiveStartMs,\n effectiveEndMs,\n mediaEngine,\n );\n }\n // TRIMMED MODE: start-time-ms/end-time-ms are relative to trimmed timeline (0 = trim start)\n const sourceStart = targetElement.sourceStartMs ?? 0;\n const trimmedDuration = targetElement.durationMs ?? 0;\n\n // Convert trimmed timeline coordinates to source timeline coordinates\n const effectiveStartMs =\n startTimeMs !== undefined\n ? sourceStart + startTimeMs // Convert from trimmed timeline to source timeline\n : sourceStart; // Default: start of trimmed portion\n\n const effectiveEndMs =\n endTimeMs !== undefined\n ? sourceStart + endTimeMs // Convert from trimmed timeline to source timeline\n : sourceStart + trimmedDuration; // Default: end of trimmed portion\n\n return this.generateLayoutFromTimeRange(\n stripWidth,\n thumbnailWidth,\n effectiveStartMs,\n effectiveEndMs,\n mediaEngine,\n );\n }\n\n /**\n * Generate layout from calculated time range\n */\n private generateLayoutFromTimeRange(\n stripWidth: number,\n thumbnailWidth: number,\n effectiveStartMs: number,\n effectiveEndMs: number,\n mediaEngine: ImportedMediaEngine,\n ) {\n // Get scrub segment duration from media engine if available\n const scrubSegmentDurationMs =\n mediaEngine && typeof mediaEngine.getScrubVideoRendition === \"function\"\n ? mediaEngine.getScrubVideoRendition()?.segmentDurationMs\n : undefined;\n\n // Generate layout using our algorithm with segment alignment\n const layout = calculateThumbnailLayout(\n stripWidth,\n thumbnailWidth,\n effectiveStartMs,\n effectiveEndMs,\n scrubSegmentDurationMs,\n );\n\n return layout;\n }\n\n private thumbnailRenderTask = new Task(this, {\n autoRun: false,\n task: async ([layout, targetElement, thumbnailWidth]: readonly [\n ThumbnailLayout | null,\n EFVideo | null,\n number,\n ]) => {\n // Simplified task that delegates to renderThumbnails method\n if (!layout || !targetElement) {\n return [];\n }\n return this.renderThumbnails(layout, targetElement, thumbnailWidth);\n },\n args: () =>\n [\n this.thumbnailLayoutTask.value || null,\n this.targetElement,\n this.thumbnailWidth,\n ] as const,\n });\n\n /**\n * Render thumbnails with provided layout (main rendering logic)\n */\n private async renderThumbnails(\n layout: ThumbnailLayout,\n targetElement: EFVideo,\n thumbnailWidth: number,\n ): Promise<ThumbnailRenderInfo[]> {\n if (!layout || !targetElement || layout.count === 0) {\n return [];\n }\n\n const videoSrc = targetElement.src;\n const availableHeight = this._stripHeight - STRIP_BORDER_PADDING; // Account for border/padding\n\n const allThumbnails: ThumbnailRenderInfo[] = [];\n let thumbnailIndex = 0; // Track ordinal position\n\n // Process each segment\n for (const segment of layout.segments) {\n for (const thumbnail of segment.thumbnails) {\n const cacheKey = getThumbnailCacheKey(videoSrc, thumbnail.timeMs);\n\n // Try exact cache hit first\n let imageData = thumbnailImageCache.get(cacheKey);\n let status: ThumbnailRenderInfo[\"status\"] = \"exact-hit\";\n let nearHitKey: string | undefined;\n\n if (!imageData) {\n // Try near cache hit within 5 seconds using proper range search\n const timeMinus = Math.max(0, thumbnail.timeMs - 5000);\n const timePlus = thumbnail.timeMs + 5000;\n\n // For range bounds, use raw timestamps (don't quantize the search range)\n const rangeStartKey = `${videoSrc}:${timeMinus}`;\n const rangeEndKey = `${videoSrc}:${timePlus}`;\n\n // Use findRange to find any cached items in this time window\n const nearHits = thumbnailImageCache.findRange(\n rangeStartKey,\n rangeEndKey,\n );\n\n // Filter to only include the same video source\n const sameVideoHits = nearHits.filter((hit) =>\n hit.key.startsWith(`${videoSrc}:`),\n );\n\n if (sameVideoHits.length > 0) {\n // Get the closest match by time from same video\n const nearestHit = sameVideoHits.reduce((closest, current) => {\n const currentParts = current.key.split(\":\");\n const closestParts = closest.key.split(\":\");\n const currentTime = Number.parseFloat(\n currentParts[currentParts.length - 1] || \"0\",\n );\n const closestTime = Number.parseFloat(\n closestParts[closestParts.length - 1] || \"0\",\n );\n const currentDiff = Math.abs(currentTime - thumbnail.timeMs);\n const closestDiff = Math.abs(closestTime - thumbnail.timeMs);\n return currentDiff < closestDiff ? current : closest;\n });\n\n imageData = nearestHit.value;\n status = \"near-hit\";\n nearHitKey = nearestHit.key;\n } else {\n status = \"missing\";\n }\n }\n\n // Fixed integer positioning - no floating point\n const x = thumbnailIndex * (thumbnailWidth + THUMBNAIL_GAP);\n\n allThumbnails.push({\n timeMs: thumbnail.timeMs,\n segmentId: segment.segmentId,\n x,\n width: thumbnailWidth, // Always exactly 80px\n height: availableHeight, // Always exactly 44px\n status,\n imageData,\n nearHitKey,\n });\n\n thumbnailIndex++; // Increment ordinal position\n }\n }\n\n // Draw current state (cache hits and placeholders)\n await this.drawThumbnails(allThumbnails);\n\n // Load missing thumbnails from scrub tracks\n await this.loadMissingThumbnails(allThumbnails, targetElement);\n\n return allThumbnails;\n }\n\n connectedCallback() {\n super.connectedCallback();\n\n // Set up ResizeObserver to track element dimensions\n this.resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n // Use borderBoxSize for accurate dimensions including borders/padding\n const width =\n entry.borderBoxSize && entry.borderBoxSize.length > 0\n ? entry.borderBoxSize[0]?.inlineSize\n : entry.contentRect.width;\n\n const height =\n entry.borderBoxSize && entry.borderBoxSize.length > 0\n ? entry.borderBoxSize[0]?.blockSize\n : entry.contentRect.height;\n\n this._stripHeight = height ?? 0;\n this.stripWidth = width ?? 0; // This triggers thumbnail layout update\n }\n });\n\n this.resizeObserver.observe(this);\n\n // Force initial width calculation after element is fully connected\n this.updateComplete.then(() => {\n if (this._stripWidth === 0) {\n const width = this.clientWidth;\n if (width > 0) {\n this.stripWidth = width ?? 0;\n }\n }\n });\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.resizeObserver?.disconnect();\n this.resizeObserver = undefined;\n\n // Clean up video property observer\n this._videoPropertyObserver?.disconnect();\n this._videoPropertyObserver = undefined;\n }\n\n /**\n * Draw thumbnails to the canvas with cache hits and placeholders\n */\n private async drawThumbnails(\n thumbnails: ThumbnailRenderInfo[],\n ): Promise<void> {\n const canvas = this.canvasRef.value;\n if (!canvas) {\n return;\n }\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n return;\n }\n\n // Set canvas to exact size we're drawing - prevents CSS scaling\n const dpr = window.devicePixelRatio || 1;\n\n // Set canvas buffer size for high DPI rendering\n canvas.width = this._stripWidth * dpr;\n canvas.height = this._stripHeight * dpr;\n\n // Set canvas DOM size to exactly what we're drawing - no CSS scaling\n canvas.style.width = `${this._stripWidth}px`;\n canvas.style.height = `${this._stripHeight}px`;\n\n // Scale the drawing context to match device pixel ratio\n ctx.scale(dpr, dpr);\n\n // Clear canvas (use logical pixel dimensions since context is scaled)\n ctx.fillStyle = \"#2a2a2a\";\n ctx.fillRect(0, 0, this._stripWidth, this._stripHeight);\n\n // Draw each thumbnail with proper aspect ratio and centering\n for (const thumb of thumbnails) {\n if (thumb.imageData) {\n // Draw cached thumbnail with aspect ratio preservation\n const tempCanvas = document.createElement(\"canvas\");\n tempCanvas.width = thumb.imageData.width;\n tempCanvas.height = thumb.imageData.height;\n const tempCtx = tempCanvas.getContext(\"2d\");\n if (!tempCtx) {\n continue;\n }\n tempCtx.putImageData(thumb.imageData, 0, 0);\n\n // Preserve aspect ratio within fixed container bounds\n const sourceAspect = thumb.imageData.width / thumb.imageData.height;\n const containerAspect = thumb.width / thumb.height;\n\n // Calculate aspect-ratio-preserving dimensions with integer coordinates\n let drawWidth: number;\n let drawHeight: number;\n let drawX: number;\n let drawY: number;\n\n if (sourceAspect > containerAspect) {\n // Source is wider - fit to container width, letterbox top/bottom\n drawWidth = thumb.width;\n drawHeight = Math.round(thumb.width / sourceAspect);\n drawX = thumb.x;\n drawY = Math.round((this._stripHeight - drawHeight) / 2);\n } else {\n // Source is taller - fit to container height, pillarbox left/right\n drawWidth = Math.round(thumb.height * sourceAspect);\n drawHeight = thumb.height;\n drawX = thumb.x + Math.round((thumb.width - drawWidth) / 2);\n drawY = Math.round((this._stripHeight - drawHeight) / 2);\n }\n\n // Draw with proper aspect ratio preservation\n ctx.drawImage(tempCanvas, drawX, drawY, drawWidth, drawHeight);\n\n // Add subtle indicator for near hits\n if (thumb.status === \"near-hit\") {\n ctx.fillStyle = \"rgba(255, 165, 0, 0.3)\";\n ctx.fillRect(thumb.x, 0, thumb.width, 2);\n }\n } else {\n // Draw placeholder - center vertically in strip with integer positioning\n const placeholderY = Math.round((this._stripHeight - thumb.height) / 2);\n ctx.fillStyle = \"#404040\";\n ctx.fillRect(thumb.x, placeholderY, thumb.width, thumb.height);\n\n // Add subtle loading indicator with integer positioning\n ctx.strokeStyle = \"#666\";\n ctx.lineWidth = 1;\n ctx.setLineDash([2, 2]);\n ctx.strokeRect(thumb.x, placeholderY, thumb.width, thumb.height);\n ctx.setLineDash([]);\n }\n }\n }\n\n /**\n * Load missing thumbnails using MediaEngine batch extraction\n */\n private async loadMissingThumbnails(\n thumbnails: ThumbnailRenderInfo[],\n targetElement: EFVideo,\n ): Promise<void> {\n const mediaEngine = targetElement.mediaEngineTask?.value;\n if (!mediaEngine) {\n return;\n }\n\n // Get all missing thumbnails\n const missingThumbnails = thumbnails.filter(\n (t) => t.status === \"missing\" || t.status === \"near-hit\",\n );\n\n if (missingThumbnails.length === 0) {\n return;\n }\n\n // Update status to loading\n for (const thumb of missingThumbnails) {\n thumb.status = \"loading\";\n }\n\n // Batch extract all missing thumbnails using MediaEngine\n const timestamps = missingThumbnails.map((t) => t.timeMs);\n\n const thumbnailResults = await mediaEngine.extractThumbnails(timestamps);\n\n // Convert canvases to ImageData and update thumbnails\n for (let i = 0; i < missingThumbnails.length; i++) {\n const thumb = missingThumbnails[i];\n const thumbnailResult = thumbnailResults[i];\n\n if (thumb && thumbnailResult) {\n // Convert canvas to ImageData\n const imageData = this.canvasToImageData(thumbnailResult.thumbnail);\n\n if (imageData) {\n const cacheKey = getThumbnailCacheKey(\n targetElement.src,\n thumb.timeMs,\n );\n thumbnailImageCache.set(cacheKey, imageData);\n thumb.imageData = imageData;\n thumb.status = \"exact-hit\";\n }\n }\n }\n\n // Redraw with newly loaded thumbnails\n await this.drawThumbnails(thumbnails);\n }\n\n /**\n * Convert Canvas to ImageData for caching\n */\n private canvasToImageData(\n canvas: HTMLCanvasElement | OffscreenCanvas,\n ): ImageData | null {\n // Extract ImageData from canvas\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n return null;\n }\n\n return ctx.getImageData(0, 0, canvas.width, canvas.height);\n }\n\n render() {\n return html`\n <canvas ${ref(this.canvasRef)}></canvas>\n ${this.thumbnailRenderTask.render({\n pending: () => html``,\n complete: () => html``,\n error: (e) =>\n html`<div class=\"error\">Error loading thumbnails: ${e}</div>`,\n })}\n `;\n }\n}\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-thumbnail-strip\": EFThumbnailStrip;\n }\n}\n"],"mappings":"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"}