@editframe/elements 0.37.3-beta → 0.38.1

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 (327) hide show
  1. package/dist/EF_FRAMEGEN.js +17 -14
  2. package/dist/EF_FRAMEGEN.js.map +1 -1
  3. package/dist/EF_RENDERING.js.map +1 -1
  4. package/dist/canvas/EFCanvas.d.ts +9 -2
  5. package/dist/canvas/EFCanvas.js +14 -4
  6. package/dist/canvas/EFCanvas.js.map +1 -1
  7. package/dist/canvas/EFCanvasItem.d.ts +2 -2
  8. package/dist/canvas/overlays/SelectionOverlay.d.ts +10 -2
  9. package/dist/canvas/overlays/SelectionOverlay.js +5 -12
  10. package/dist/canvas/overlays/SelectionOverlay.js.map +1 -1
  11. package/dist/canvas/overlays/overlayState.js.map +1 -1
  12. package/dist/canvas/selection/SelectionController.js.map +1 -1
  13. package/dist/elements/EFAudio.d.ts +1 -11
  14. package/dist/elements/EFAudio.js +2 -10
  15. package/dist/elements/EFAudio.js.map +1 -1
  16. package/dist/elements/EFCaptions.d.ts +5 -9
  17. package/dist/elements/EFCaptions.js +34 -11
  18. package/dist/elements/EFCaptions.js.map +1 -1
  19. package/dist/elements/EFImage.d.ts +10 -8
  20. package/dist/elements/EFImage.js +117 -32
  21. package/dist/elements/EFImage.js.map +1 -1
  22. package/dist/elements/EFMedia/AssetMediaEngine.js +2 -2
  23. package/dist/elements/EFMedia/AssetMediaEngine.js.map +1 -1
  24. package/dist/elements/EFMedia/BaseMediaEngine.js +15 -92
  25. package/dist/elements/EFMedia/BaseMediaEngine.js.map +1 -1
  26. package/dist/elements/EFMedia/BufferedSeekingInput.js +10 -11
  27. package/dist/elements/EFMedia/BufferedSeekingInput.js.map +1 -1
  28. package/dist/elements/EFMedia/{AssetIdMediaEngine.js → FileMediaEngine.js} +44 -24
  29. package/dist/elements/EFMedia/FileMediaEngine.js.map +1 -0
  30. package/dist/elements/EFMedia/JitMediaEngine.js +14 -13
  31. package/dist/elements/EFMedia/JitMediaEngine.js.map +1 -1
  32. package/dist/elements/EFMedia/shared/AudioSpanUtils.js +3 -3
  33. package/dist/elements/EFMedia/shared/AudioSpanUtils.js.map +1 -1
  34. package/dist/elements/EFMedia/shared/ThumbnailExtractor.js +12 -7
  35. package/dist/elements/EFMedia/shared/ThumbnailExtractor.js.map +1 -1
  36. package/dist/elements/EFMedia/shared/timeoutUtils.js +44 -0
  37. package/dist/elements/EFMedia/shared/timeoutUtils.js.map +1 -0
  38. package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js +1 -1
  39. package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js.map +1 -1
  40. package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js +4 -4
  41. package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js.map +1 -1
  42. package/dist/elements/EFMedia.d.ts +14 -8
  43. package/dist/elements/EFMedia.js +52 -19
  44. package/dist/elements/EFMedia.js.map +1 -1
  45. package/dist/elements/EFPanZoom.d.ts +2 -2
  46. package/dist/elements/EFPanZoom.js +1 -1
  47. package/dist/elements/EFPanZoom.js.map +1 -1
  48. package/dist/elements/EFSourceMixin.js +16 -8
  49. package/dist/elements/EFSourceMixin.js.map +1 -1
  50. package/dist/elements/EFSurface.d.ts +5 -8
  51. package/dist/elements/EFSurface.js +4 -43
  52. package/dist/elements/EFSurface.js.map +1 -1
  53. package/dist/elements/EFTemporal.d.ts +33 -8
  54. package/dist/elements/EFTemporal.js +92 -40
  55. package/dist/elements/EFTemporal.js.map +1 -1
  56. package/dist/elements/EFText.d.ts +3 -0
  57. package/dist/elements/EFText.js +54 -21
  58. package/dist/elements/EFText.js.map +1 -1
  59. package/dist/elements/EFTextSegment.js +8 -4
  60. package/dist/elements/EFTextSegment.js.map +1 -1
  61. package/dist/elements/EFTimegroup.d.ts +26 -43
  62. package/dist/elements/EFTimegroup.js +295 -314
  63. package/dist/elements/EFTimegroup.js.map +1 -1
  64. package/dist/elements/EFVideo.d.ts +44 -42
  65. package/dist/elements/EFVideo.js +259 -172
  66. package/dist/elements/EFVideo.js.map +1 -1
  67. package/dist/elements/EFWaveform.d.ts +3 -8
  68. package/dist/elements/EFWaveform.js +18 -13
  69. package/dist/elements/EFWaveform.js.map +1 -1
  70. package/dist/elements/ElementPositionInfo.js.map +1 -1
  71. package/dist/elements/FetchMixin.js.map +1 -1
  72. package/dist/elements/TargetController.d.ts +0 -3
  73. package/dist/elements/TargetController.js +12 -35
  74. package/dist/elements/TargetController.js.map +1 -1
  75. package/dist/elements/TimegroupController.js.map +1 -1
  76. package/dist/elements/cloneFactoryRegistry.d.ts +14 -0
  77. package/dist/elements/cloneFactoryRegistry.js +15 -0
  78. package/dist/elements/cloneFactoryRegistry.js.map +1 -0
  79. package/dist/elements/renderTemporalAudio.js +8 -6
  80. package/dist/elements/renderTemporalAudio.js.map +1 -1
  81. package/dist/elements/setupTemporalHierarchy.js +62 -0
  82. package/dist/elements/setupTemporalHierarchy.js.map +1 -0
  83. package/dist/elements/updateAnimations.js +62 -87
  84. package/dist/elements/updateAnimations.js.map +1 -1
  85. package/dist/getRenderInfo.d.ts +3 -2
  86. package/dist/getRenderInfo.js +20 -4
  87. package/dist/getRenderInfo.js.map +1 -1
  88. package/dist/gui/ContextMixin.js +68 -12
  89. package/dist/gui/ContextMixin.js.map +1 -1
  90. package/dist/gui/Controllable.js +1 -1
  91. package/dist/gui/Controllable.js.map +1 -1
  92. package/dist/gui/EFActiveRootTemporal.d.ts +2 -2
  93. package/dist/gui/EFActiveRootTemporal.js.map +1 -1
  94. package/dist/gui/EFControls.d.ts +2 -2
  95. package/dist/gui/EFControls.js +2 -2
  96. package/dist/gui/EFControls.js.map +1 -1
  97. package/dist/gui/EFDial.d.ts +2 -2
  98. package/dist/gui/EFDial.js +12 -9
  99. package/dist/gui/EFDial.js.map +1 -1
  100. package/dist/gui/EFFilmstrip.d.ts +2 -0
  101. package/dist/gui/EFFilmstrip.js +18 -10
  102. package/dist/gui/EFFilmstrip.js.map +1 -1
  103. package/dist/gui/EFFitScale.d.ts +28 -4
  104. package/dist/gui/EFFitScale.js +88 -26
  105. package/dist/gui/EFFitScale.js.map +1 -1
  106. package/dist/gui/EFFocusOverlay.d.ts +2 -2
  107. package/dist/gui/EFFocusOverlay.js +3 -3
  108. package/dist/gui/EFFocusOverlay.js.map +1 -1
  109. package/dist/gui/EFOverlayItem.d.ts +2 -2
  110. package/dist/gui/EFOverlayLayer.d.ts +2 -2
  111. package/dist/gui/EFPause.d.ts +2 -2
  112. package/dist/gui/EFPause.js +1 -1
  113. package/dist/gui/EFPlay.d.ts +2 -2
  114. package/dist/gui/EFPlay.js +1 -1
  115. package/dist/gui/EFPreview.js +1 -1
  116. package/dist/gui/EFResizableBox.d.ts +2 -2
  117. package/dist/gui/EFResizableBox.js +5 -5
  118. package/dist/gui/EFResizableBox.js.map +1 -1
  119. package/dist/gui/EFScrubber.d.ts +2 -2
  120. package/dist/gui/EFScrubber.js +8 -13
  121. package/dist/gui/EFScrubber.js.map +1 -1
  122. package/dist/gui/EFTimeDisplay.d.ts +6 -2
  123. package/dist/gui/EFTimeDisplay.js +25 -7
  124. package/dist/gui/EFTimeDisplay.js.map +1 -1
  125. package/dist/gui/EFTimelineRuler.d.ts +2 -2
  126. package/dist/gui/EFTimelineRuler.js +3 -3
  127. package/dist/gui/EFTimelineRuler.js.map +1 -1
  128. package/dist/gui/EFToggleLoop.d.ts +2 -2
  129. package/dist/gui/EFToggleLoop.js +1 -1
  130. package/dist/gui/EFTogglePlay.d.ts +2 -2
  131. package/dist/gui/EFTogglePlay.js +1 -1
  132. package/dist/gui/EFTransformHandles.d.ts +2 -2
  133. package/dist/gui/EFTransformHandles.js +6 -6
  134. package/dist/gui/EFTransformHandles.js.map +1 -1
  135. package/dist/gui/EFWorkbench.d.ts +40 -36
  136. package/dist/gui/EFWorkbench.js +436 -822
  137. package/dist/gui/EFWorkbench.js.map +1 -1
  138. package/dist/gui/FitScaleHelpers.js.map +1 -1
  139. package/dist/gui/PlaybackController.d.ts +3 -8
  140. package/dist/gui/PlaybackController.js +59 -56
  141. package/dist/gui/PlaybackController.js.map +1 -1
  142. package/dist/gui/TWMixin.js +1 -1
  143. package/dist/gui/TWMixin.js.map +1 -1
  144. package/dist/gui/TargetOrContextMixin.js +43 -6
  145. package/dist/gui/TargetOrContextMixin.js.map +1 -1
  146. package/dist/gui/ef-theme.css +136 -0
  147. package/dist/gui/hierarchy/EFHierarchy.d.ts +2 -2
  148. package/dist/gui/hierarchy/EFHierarchy.js +14 -24
  149. package/dist/gui/hierarchy/EFHierarchy.js.map +1 -1
  150. package/dist/gui/hierarchy/EFHierarchyItem.d.ts +3 -3
  151. package/dist/gui/hierarchy/EFHierarchyItem.js +22 -10
  152. package/dist/gui/hierarchy/EFHierarchyItem.js.map +1 -1
  153. package/dist/gui/icons.js.map +1 -1
  154. package/dist/gui/previewSettingsContext.d.ts +18 -0
  155. package/dist/gui/previewSettingsContext.js.map +1 -1
  156. package/dist/gui/theme.js +34 -0
  157. package/dist/gui/theme.js.map +1 -0
  158. package/dist/gui/timeline/EFTimeline.d.ts +2 -2
  159. package/dist/gui/timeline/EFTimeline.js +70 -52
  160. package/dist/gui/timeline/EFTimeline.js.map +1 -1
  161. package/dist/gui/timeline/EFTimelineRow.d.ts +5 -3
  162. package/dist/gui/timeline/EFTimelineRow.js +55 -32
  163. package/dist/gui/timeline/EFTimelineRow.js.map +1 -1
  164. package/dist/gui/timeline/TrimHandles.d.ts +23 -9
  165. package/dist/gui/timeline/TrimHandles.js +224 -51
  166. package/dist/gui/timeline/TrimHandles.js.map +1 -1
  167. package/dist/gui/timeline/flattenHierarchy.js.map +1 -1
  168. package/dist/gui/timeline/timelineEditingContext.d.ts +34 -0
  169. package/dist/gui/timeline/timelineEditingContext.js +24 -0
  170. package/dist/gui/timeline/timelineEditingContext.js.map +1 -0
  171. package/dist/gui/timeline/timelineStateContext.js.map +1 -1
  172. package/dist/gui/timeline/tracks/AudioTrack.js +1 -1
  173. package/dist/gui/timeline/tracks/AudioTrack.js.map +1 -1
  174. package/dist/gui/timeline/tracks/CaptionsTrack.d.ts +2 -3
  175. package/dist/gui/timeline/tracks/CaptionsTrack.js +17 -75
  176. package/dist/gui/timeline/tracks/CaptionsTrack.js.map +1 -1
  177. package/dist/gui/timeline/tracks/EFThumbnailStrip.d.ts +52 -0
  178. package/dist/gui/timeline/tracks/EFThumbnailStrip.js +596 -0
  179. package/dist/gui/timeline/tracks/EFThumbnailStrip.js.map +1 -0
  180. package/dist/gui/timeline/tracks/HTMLTrack.js.map +1 -1
  181. package/dist/gui/timeline/tracks/ImageTrack.js.map +1 -1
  182. package/dist/gui/timeline/tracks/TextTrack.d.ts +3 -2
  183. package/dist/gui/timeline/tracks/TextTrack.js +17 -43
  184. package/dist/gui/timeline/tracks/TextTrack.js.map +1 -1
  185. package/dist/gui/timeline/tracks/TimegroupTrack.d.ts +3 -4
  186. package/dist/gui/timeline/tracks/TimegroupTrack.js +33 -23
  187. package/dist/gui/timeline/tracks/TimegroupTrack.js.map +1 -1
  188. package/dist/gui/timeline/tracks/TrackItem.d.ts +7 -9
  189. package/dist/gui/timeline/tracks/TrackItem.js +18 -17
  190. package/dist/gui/timeline/tracks/TrackItem.js.map +1 -1
  191. package/dist/gui/timeline/tracks/VideoTrack.d.ts +3 -3
  192. package/dist/gui/timeline/tracks/VideoTrack.js +11 -14
  193. package/dist/gui/timeline/tracks/VideoTrack.js.map +1 -1
  194. package/dist/gui/timeline/tracks/WaveformTrack.js.map +1 -1
  195. package/dist/gui/timeline/tracks/renderTrackChildren.js.map +1 -1
  196. package/dist/gui/timeline/tracks/waveformUtils.js +1 -1
  197. package/dist/gui/timeline/tracks/waveformUtils.js.map +1 -1
  198. package/dist/gui/tree/EFTree.d.ts +2 -2
  199. package/dist/gui/tree/EFTree.js +8 -14
  200. package/dist/gui/tree/EFTree.js.map +1 -1
  201. package/dist/gui/tree/EFTreeItem.d.ts +2 -2
  202. package/dist/gui/tree/EFTreeItem.js +3 -3
  203. package/dist/gui/tree/EFTreeItem.js.map +1 -1
  204. package/dist/gui/tree/treeContext.js.map +1 -1
  205. package/dist/index.d.ts +10 -8
  206. package/dist/index.js +6 -5
  207. package/dist/index.js.map +1 -1
  208. package/dist/node.d.ts +2 -2
  209. package/dist/node.js +2 -2
  210. package/dist/preview/AdaptiveResolutionTracker.js +3 -3
  211. package/dist/preview/AdaptiveResolutionTracker.js.map +1 -1
  212. package/dist/preview/FrameController.d.ts +2 -17
  213. package/dist/preview/FrameController.js +40 -63
  214. package/dist/preview/FrameController.js.map +1 -1
  215. package/dist/preview/QualityUpgradeScheduler.d.ts +76 -0
  216. package/dist/preview/QualityUpgradeScheduler.js +158 -0
  217. package/dist/preview/QualityUpgradeScheduler.js.map +1 -0
  218. package/dist/preview/RenderContext.d.ts +119 -1
  219. package/dist/preview/RenderContext.js +21 -3
  220. package/dist/preview/RenderContext.js.map +1 -1
  221. package/dist/preview/RenderProfiler.js.map +1 -1
  222. package/dist/preview/RenderStats.js +85 -0
  223. package/dist/preview/RenderStats.js.map +1 -0
  224. package/dist/preview/encoding/canvasEncoder.js +2 -52
  225. package/dist/preview/encoding/canvasEncoder.js.map +1 -1
  226. package/dist/preview/encoding/mainThreadEncoder.js.map +1 -1
  227. package/dist/preview/encoding/workerEncoder.js.map +1 -1
  228. package/dist/preview/logger.js.map +1 -1
  229. package/dist/preview/previewSettings.d.ts +34 -0
  230. package/dist/preview/previewSettings.js +29 -17
  231. package/dist/preview/previewSettings.js.map +1 -1
  232. package/dist/preview/previewTypes.js +4 -4
  233. package/dist/preview/previewTypes.js.map +1 -1
  234. package/dist/preview/renderElementToCanvas.d.ts +44 -0
  235. package/dist/preview/renderElementToCanvas.js +72 -0
  236. package/dist/preview/renderElementToCanvas.js.map +1 -0
  237. package/dist/preview/renderTimegroupToCanvas.d.ts +134 -32
  238. package/dist/preview/renderTimegroupToCanvas.js +321 -146
  239. package/dist/preview/renderTimegroupToCanvas.js.map +1 -1
  240. package/dist/preview/renderTimegroupToCanvas.types.d.ts +51 -0
  241. package/dist/preview/renderTimegroupToVideo.d.ts +20 -35
  242. package/dist/preview/renderTimegroupToVideo.js +94 -106
  243. package/dist/preview/renderTimegroupToVideo.js.map +1 -1
  244. package/dist/preview/renderTimegroupToVideo.types.d.ts +42 -0
  245. package/dist/preview/renderVideoToVideo.js +286 -0
  246. package/dist/preview/renderVideoToVideo.js.map +1 -0
  247. package/dist/preview/renderers.d.ts +56 -0
  248. package/dist/preview/renderers.js +13 -1
  249. package/dist/preview/renderers.js.map +1 -1
  250. package/dist/preview/rendering/ScaleConfig.js +74 -0
  251. package/dist/preview/rendering/ScaleConfig.js.map +1 -0
  252. package/dist/preview/rendering/inlineImages.d.ts +13 -0
  253. package/dist/preview/rendering/inlineImages.js +7 -44
  254. package/dist/preview/rendering/inlineImages.js.map +1 -1
  255. package/dist/preview/rendering/loadImage.d.ts +8 -0
  256. package/dist/preview/rendering/loadImage.js +22 -0
  257. package/dist/preview/rendering/loadImage.js.map +1 -0
  258. package/dist/preview/rendering/renderToImageNative.js +3 -3
  259. package/dist/preview/rendering/renderToImageNative.js.map +1 -1
  260. package/dist/preview/rendering/serializeTimelineDirect.js +224 -68
  261. package/dist/preview/rendering/serializeTimelineDirect.js.map +1 -1
  262. package/dist/preview/statsTrackingStrategy.js +1 -101
  263. package/dist/preview/statsTrackingStrategy.js.map +1 -1
  264. package/dist/preview/workers/WorkerPool.js +0 -1
  265. package/dist/preview/workers/WorkerPool.js.map +1 -1
  266. package/dist/preview/workers/encoderWorkerInline.js +21 -54
  267. package/dist/preview/workers/encoderWorkerInline.js.map +1 -1
  268. package/dist/render/EFRenderAPI.d.ts +2 -1
  269. package/dist/render/EFRenderAPI.js +12 -36
  270. package/dist/render/EFRenderAPI.js.map +1 -1
  271. package/dist/render/getRenderData.js +4 -4
  272. package/dist/render/getRenderData.js.map +1 -1
  273. package/dist/style.css +114 -163
  274. package/dist/transcoding/cache/RequestDeduplicator.js +1 -0
  275. package/dist/transcoding/cache/RequestDeduplicator.js.map +1 -1
  276. package/dist/transcoding/types/index.d.ts +1 -1
  277. package/dist/transcoding/utils/UrlGenerator.js +10 -3
  278. package/dist/transcoding/utils/UrlGenerator.js.map +1 -1
  279. package/dist/utils/LRUCache.js +1 -0
  280. package/dist/utils/LRUCache.js.map +1 -1
  281. package/dist/utils/frameTime.js +23 -1
  282. package/dist/utils/frameTime.js.map +1 -1
  283. package/package.json +45 -8
  284. package/scripts/build-css.js +8 -1
  285. package/test/setup.ts +0 -1
  286. package/test/useAssetMSW.ts +50 -0
  287. package/test/visualRegressionUtils.ts +23 -9
  288. package/tsdown.config.ts +6 -1
  289. package/dist/_virtual/rolldown_runtime.js +0 -27
  290. package/dist/elements/EFMedia/AssetIdMediaEngine.js.map +0 -1
  291. package/dist/elements/EFThumbnailStrip.d.ts +0 -167
  292. package/dist/elements/EFThumbnailStrip.js +0 -731
  293. package/dist/elements/EFThumbnailStrip.js.map +0 -1
  294. package/dist/elements/SessionThumbnailCache.js +0 -154
  295. package/dist/elements/SessionThumbnailCache.js.map +0 -1
  296. package/dist/node_modules/react/cjs/react-jsx-runtime.development.js +0 -688
  297. package/dist/node_modules/react/cjs/react-jsx-runtime.development.js.map +0 -1
  298. package/dist/node_modules/react/cjs/react.development.js +0 -1521
  299. package/dist/node_modules/react/cjs/react.development.js.map +0 -1
  300. package/dist/node_modules/react/index.js +0 -13
  301. package/dist/node_modules/react/index.js.map +0 -1
  302. package/dist/node_modules/react/jsx-runtime.js +0 -13
  303. package/dist/node_modules/react/jsx-runtime.js.map +0 -1
  304. package/dist/preview/encoding/types.d.ts +0 -1
  305. package/dist/preview/renderTimegroupPreview.js +0 -686
  306. package/dist/preview/renderTimegroupPreview.js.map +0 -1
  307. package/dist/preview/rendering/renderToImage.d.ts +0 -2
  308. package/dist/preview/rendering/renderToImage.js +0 -95
  309. package/dist/preview/rendering/renderToImage.js.map +0 -1
  310. package/dist/preview/rendering/renderToImageForeignObject.js +0 -163
  311. package/dist/preview/rendering/renderToImageForeignObject.js.map +0 -1
  312. package/dist/preview/rendering/renderToImageNative.d.ts +0 -1
  313. package/dist/preview/rendering/svgSerializer.js +0 -43
  314. package/dist/preview/rendering/svgSerializer.js.map +0 -1
  315. package/dist/preview/rendering/types.d.ts +0 -2
  316. package/dist/preview/thumbnailCacheSettings.js +0 -52
  317. package/dist/preview/thumbnailCacheSettings.js.map +0 -1
  318. package/dist/sandbox/PlaybackControls.d.ts +0 -1
  319. package/dist/sandbox/PlaybackControls.js +0 -10
  320. package/dist/sandbox/PlaybackControls.js.map +0 -1
  321. package/dist/sandbox/ScenarioRunner.d.ts +0 -1
  322. package/dist/sandbox/ScenarioRunner.js +0 -1
  323. package/dist/sandbox/defineSandbox.d.ts +0 -1
  324. package/dist/sandbox/index.d.ts +0 -3
  325. package/dist/sandbox/index.js +0 -2
  326. package/test/EFVideo.framegen.browsertest.ts +0 -80
  327. package/test/thumbnail-performance-test.html +0 -116
@@ -2,13 +2,36 @@ import { LitElement } from "lit";
2
2
  import * as lit_html_directives_ref1 from "lit-html/directives/ref";
3
3
 
4
4
  //#region src/gui/EFFitScale.d.ts
5
+ interface ScaleInput {
6
+ containerWidth: number;
7
+ containerHeight: number;
8
+ contentWidth: number;
9
+ contentHeight: number;
10
+ }
11
+ interface ScaleOutput {
12
+ scale: number;
13
+ translateX: number;
14
+ translateY: number;
15
+ }
16
+ /**
17
+ * Compute the scale factor and centering translation needed to fit
18
+ * content of a given size into a container while preserving aspect ratio.
19
+ *
20
+ * Returns `null` when any dimension is zero or negative (cannot compute).
21
+ */
22
+ declare function computeFitScale(input: ScaleInput): ScaleOutput | null;
5
23
  declare class EFFitScale extends LitElement {
6
24
  containerRef: lit_html_directives_ref1.Ref<HTMLDivElement>;
7
25
  contentRef: lit_html_directives_ref1.Ref<HTMLSlotElement>;
8
26
  createRenderRoot(): this;
9
27
  uniqueId: string;
10
- private scale;
11
- private animationFrameId?;
28
+ paused: boolean;
29
+ updated(changedProperties: Map<string, unknown>): void;
30
+ private containerResizeObserver?;
31
+ private contentResizeObserver?;
32
+ private childMutationObserver?;
33
+ private observedContentChild;
34
+ private hasWarnedZeroDimensions;
12
35
  get contentChild(): HTMLElement | null;
13
36
  get scaleInfo(): {
14
37
  scale: number;
@@ -18,7 +41,8 @@ declare class EFFitScale extends LitElement {
18
41
  contentHeight: number;
19
42
  };
20
43
  scaleLastSetOn: HTMLElement | null;
21
- setScale: () => void;
44
+ private updateScale;
45
+ private observeContentChild;
22
46
  removeScale: () => void;
23
47
  connectedCallback(): void;
24
48
  disconnectedCallback(): void;
@@ -29,5 +53,5 @@ declare global {
29
53
  }
30
54
  }
31
55
  //#endregion
32
- export { EFFitScale };
56
+ export { EFFitScale, ScaleInput, ScaleOutput, computeFitScale };
33
57
  //# sourceMappingURL=EFFitScale.d.ts.map
@@ -1,36 +1,64 @@
1
1
  import { __decorate } from "../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
2
2
  import { LitElement } from "lit";
3
- import { customElement, state } from "lit/decorators.js";
3
+ import { customElement, property } from "lit/decorators.js";
4
4
  import { createRef } from "lit/directives/ref.js";
5
5
 
6
6
  //#region src/gui/EFFitScale.ts
7
+ /**
8
+ * Compute the scale factor and centering translation needed to fit
9
+ * content of a given size into a container while preserving aspect ratio.
10
+ *
11
+ * Returns `null` when any dimension is zero or negative (cannot compute).
12
+ */
13
+ function computeFitScale(input) {
14
+ const { containerWidth, containerHeight, contentWidth, contentHeight } = input;
15
+ if (containerWidth <= 0 || containerHeight <= 0 || contentWidth <= 0 || contentHeight <= 0) return null;
16
+ const scale = containerWidth / containerHeight > contentWidth / contentHeight ? containerHeight / contentHeight : containerWidth / contentWidth;
17
+ const scaledWidth = contentWidth * scale;
18
+ const scaledHeight = contentHeight * scale;
19
+ return {
20
+ scale,
21
+ translateX: (containerWidth - scaledWidth) / 2,
22
+ translateY: (containerHeight - scaledHeight) / 2
23
+ };
24
+ }
7
25
  let EFFitScale = class EFFitScale$1 extends LitElement {
8
26
  constructor(..._args) {
9
27
  super(..._args);
10
28
  this.containerRef = createRef();
11
29
  this.contentRef = createRef();
12
30
  this.uniqueId = Math.random().toString(36).substring(2, 15);
13
- this.scale = 1;
31
+ this.paused = false;
32
+ this.observedContentChild = null;
33
+ this.hasWarnedZeroDimensions = false;
14
34
  this.scaleLastSetOn = null;
15
- this.setScale = () => {
16
- if (this.isConnected) {
17
- const { scale, containerWidth, containerHeight, contentWidth, contentHeight } = this.scaleInfo;
18
- if (this.contentChild && contentWidth > 0 && contentHeight > 0) {
19
- const scaledWidth = contentWidth * scale;
20
- const scaledHeight = contentHeight * scale;
21
- const translateX = (containerWidth - scaledWidth) / 2;
22
- const translateY = (containerHeight - scaledHeight) / 2;
23
- if (this.scaleLastSetOn !== this.contentChild) this.removeScale();
24
- Object.assign(this.contentChild.style, {
25
- width: `${contentWidth}px`,
26
- height: `${contentHeight}px`,
27
- transform: `translate(${translateX.toFixed(4)}px, ${translateY.toFixed(4)}px) scale(${scale.toFixed(4)})`,
28
- transformOrigin: "top left"
29
- });
30
- this.scale = scale;
31
- this.scaleLastSetOn = this.contentChild;
35
+ this.updateScale = () => {
36
+ if (!this.isConnected || this.paused) return;
37
+ const { containerWidth, containerHeight, contentWidth, contentHeight } = this.scaleInfo;
38
+ if (containerWidth === 0 || containerHeight === 0) {
39
+ if (!this.hasWarnedZeroDimensions) {
40
+ this.hasWarnedZeroDimensions = true;
41
+ console.warn(`[ef-fit-scale] Container has zero dimensions (${containerWidth}×${containerHeight}). Content will be invisible. Ensure all ancestors have resolved height.`, this);
32
42
  }
33
- this.animationFrameId = requestAnimationFrame(this.setScale);
43
+ return;
44
+ }
45
+ this.hasWarnedZeroDimensions = false;
46
+ if (this.contentChild && contentWidth > 0 && contentHeight > 0) {
47
+ const result = computeFitScale({
48
+ containerWidth,
49
+ containerHeight,
50
+ contentWidth,
51
+ contentHeight
52
+ });
53
+ if (!result) return;
54
+ if (this.scaleLastSetOn !== this.contentChild) this.removeScale();
55
+ Object.assign(this.contentChild.style, {
56
+ width: `${contentWidth}px`,
57
+ height: `${contentHeight}px`,
58
+ transform: `translate(${result.translateX.toFixed(4)}px, ${result.translateY.toFixed(4)}px) scale(${result.scale.toFixed(4)})`,
59
+ transformOrigin: "top left"
60
+ });
61
+ this.scaleLastSetOn = this.contentChild;
34
62
  }
35
63
  };
36
64
  this.removeScale = () => {
@@ -54,12 +82,15 @@ let EFFitScale = class EFFitScale$1 extends LitElement {
54
82
  gridTemplateRows: "100%",
55
83
  overflow: "hidden",
56
84
  boxSizing: "border-box",
57
- contain: "strict",
85
+ contain: "layout paint style",
58
86
  position: "relative"
59
87
  });
60
88
  this.id = `${this.uniqueId}`;
61
89
  return this;
62
90
  }
91
+ updated(changedProperties) {
92
+ if (changedProperties.has("paused") && !this.paused) this.updateScale();
93
+ }
63
94
  get contentChild() {
64
95
  if (!this.children.length) return null;
65
96
  const isNonContentElement = (element) => {
@@ -143,26 +174,57 @@ let EFFitScale = class EFFitScale$1 extends LitElement {
143
174
  contentHeight: 0
144
175
  };
145
176
  return {
146
- scale: containerWidth / containerHeight > contentWidth / contentHeight ? containerHeight / contentHeight : containerWidth / contentWidth,
177
+ scale: computeFitScale({
178
+ containerWidth,
179
+ containerHeight,
180
+ contentWidth,
181
+ contentHeight
182
+ })?.scale ?? 1,
147
183
  containerWidth,
148
184
  containerHeight,
149
185
  contentWidth,
150
186
  contentHeight
151
187
  };
152
188
  }
189
+ observeContentChild() {
190
+ const child = this.contentChild;
191
+ if (child === this.observedContentChild) return;
192
+ this.contentResizeObserver?.disconnect();
193
+ if (child) {
194
+ this.contentResizeObserver = new ResizeObserver(() => {
195
+ this.updateScale();
196
+ });
197
+ this.contentResizeObserver.observe(child);
198
+ }
199
+ this.observedContentChild = child;
200
+ }
153
201
  connectedCallback() {
154
202
  super.connectedCallback();
155
- this.animationFrameId = requestAnimationFrame(this.setScale);
203
+ this.hasWarnedZeroDimensions = false;
204
+ this.containerResizeObserver = new ResizeObserver(() => {
205
+ this.updateScale();
206
+ });
207
+ this.containerResizeObserver.observe(this);
208
+ this.childMutationObserver = new MutationObserver(() => {
209
+ this.observeContentChild();
210
+ this.updateScale();
211
+ });
212
+ this.childMutationObserver.observe(this, { childList: true });
213
+ this.observeContentChild();
214
+ requestAnimationFrame(() => this.updateScale());
156
215
  }
157
216
  disconnectedCallback() {
158
217
  super.disconnectedCallback();
159
218
  this.removeScale();
160
- if (this.animationFrameId) cancelAnimationFrame(this.animationFrameId);
219
+ this.containerResizeObserver?.disconnect();
220
+ this.contentResizeObserver?.disconnect();
221
+ this.childMutationObserver?.disconnect();
222
+ this.observedContentChild = null;
161
223
  }
162
224
  };
163
- __decorate([state()], EFFitScale.prototype, "scale", void 0);
225
+ __decorate([property({ type: Boolean })], EFFitScale.prototype, "paused", void 0);
164
226
  EFFitScale = __decorate([customElement("ef-fit-scale")], EFFitScale);
165
227
 
166
228
  //#endregion
167
- export { EFFitScale };
229
+ export { EFFitScale, computeFitScale };
168
230
  //# sourceMappingURL=EFFitScale.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EFFitScale.js","names":["EFFitScale","results: HTMLElement[]","children","allContentElements: HTMLElement[]"],"sources":["../../src/gui/EFFitScale.ts"],"sourcesContent":["import { LitElement } from \"lit\";\nimport { customElement, state } from \"lit/decorators.js\";\nimport { createRef } from \"lit/directives/ref.js\";\n\n@customElement(\"ef-fit-scale\")\nexport class EFFitScale extends LitElement {\n containerRef = createRef<HTMLDivElement>();\n contentRef = createRef<HTMLSlotElement>();\n\n createRenderRoot() {\n Object.assign(this.style, {\n display: \"grid\",\n width: \"100%\",\n height: \"100%\",\n gridTemplateColumns: \"100%\",\n gridTemplateRows: \"100%\",\n overflow: \"hidden\",\n boxSizing: \"border-box\",\n contain: \"strict\",\n position: \"relative\",\n });\n this.id = `${this.uniqueId}`;\n return this;\n }\n\n uniqueId = Math.random().toString(36).substring(2, 15);\n\n @state()\n private scale = 1;\n\n private animationFrameId?: number;\n\n get contentChild() {\n if (!this.children.length) return null;\n\n const isNonContentElement = (element: Element): boolean => {\n const tagName = element.tagName.toLowerCase();\n const nonContentTags = [\n \"style\",\n \"script\",\n \"meta\",\n \"link\",\n \"title\",\n \"noscript\",\n ];\n if (nonContentTags.includes(tagName)) return true;\n\n try {\n const display = window.getComputedStyle(element).display;\n return display === \"none\" || display === \"contents\";\n } catch {\n return false;\n }\n };\n\n const findAllContentElements = (element: Element): HTMLElement[] => {\n const results: HTMLElement[] = [];\n\n if (element instanceof HTMLSlotElement) {\n const assigned = element.assignedElements()[0];\n if (assigned) {\n results.push(...findAllContentElements(assigned));\n }\n return results;\n }\n\n if (!isNonContentElement(element)) {\n results.push(element as HTMLElement);\n }\n\n const children = Array.from(element.children);\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (child) {\n results.push(...findAllContentElements(child));\n }\n }\n\n return results;\n };\n\n const children = Array.from(this.children);\n const allContentElements: HTMLElement[] = [];\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (child) {\n allContentElements.push(...findAllContentElements(child));\n }\n }\n\n if (allContentElements.length === 0) return null;\n\n return allContentElements[0] ?? null;\n }\n\n get scaleInfo() {\n if (!this.contentChild) {\n return {\n scale: 1,\n containerWidth: 0,\n containerHeight: 0,\n contentWidth: 0,\n contentHeight: 0,\n };\n }\n\n const containerWidth = this.clientWidth;\n const containerHeight = this.clientHeight;\n\n // Try to get natural dimensions from media elements (ef-video, ef-image)\n let contentWidth = 0;\n let contentHeight = 0;\n\n if (typeof (this.contentChild as any).getNaturalDimensions === \"function\") {\n const naturalDimensions = (\n this.contentChild as any\n ).getNaturalDimensions() as { width: number; height: number } | null;\n if (\n naturalDimensions &&\n naturalDimensions.width > 0 &&\n naturalDimensions.height > 0\n ) {\n contentWidth = naturalDimensions.width;\n contentHeight = naturalDimensions.height;\n\n // ESSENTIAL: For ef-video, set canvas to explicit pixel dimensions to break 100% circular dependency\n // Canvas default CSS is width:100%, height:100% which would make ef-video collapse to 0x0\n // when ef-video is set to width:auto, height:auto by ElementRenderer\n if (this.contentChild.tagName === \"EF-VIDEO\") {\n const canvas = (this.contentChild as any).canvasElement;\n if (canvas) {\n canvas.style.setProperty(\"width\", `${contentWidth}px`, \"important\");\n canvas.style.setProperty(\n \"height\",\n `${contentHeight}px`,\n \"important\",\n );\n }\n }\n } else {\n // Natural dimensions not available yet, fall back to client dimensions\n contentWidth = this.contentChild.clientWidth;\n contentHeight = this.contentChild.clientHeight;\n }\n } else {\n // For other elements, use clientWidth/Height\n contentWidth = this.contentChild.clientWidth;\n contentHeight = this.contentChild.clientHeight;\n }\n\n if (contentWidth === 0 || contentHeight === 0) {\n return {\n scale: 1,\n containerWidth,\n containerHeight,\n contentWidth: 0,\n contentHeight: 0,\n };\n }\n\n const containerRatio = containerWidth / containerHeight;\n const contentRatio = contentWidth / contentHeight;\n\n const scale =\n containerRatio > contentRatio\n ? containerHeight / contentHeight\n : containerWidth / contentWidth;\n\n return {\n scale,\n containerWidth,\n containerHeight,\n contentWidth,\n contentHeight,\n };\n }\n\n scaleLastSetOn: HTMLElement | null = null;\n\n setScale = () => {\n if (this.isConnected) {\n const scaleInfo = this.scaleInfo;\n const {\n scale,\n containerWidth,\n containerHeight,\n contentWidth,\n contentHeight,\n } = scaleInfo;\n\n if (this.contentChild && contentWidth > 0 && contentHeight > 0) {\n // Calculate scaled dimensions using natural size from scaleInfo\n const scaledWidth = contentWidth * scale;\n const scaledHeight = contentHeight * scale;\n const translateX = (containerWidth - scaledWidth) / 2;\n const translateY = (containerHeight - scaledHeight) / 2;\n\n // In the rare event that the content child is changed, we need to remove the scale\n // because we don't want to have a scale on the old content child that is somewhere else in the DOM\n if (this.scaleLastSetOn !== this.contentChild) {\n this.removeScale();\n }\n // Use toFixed to avoid floating point precision issues\n // this will update every frame with sub-pixel changes if we don't pin it down\n Object.assign(this.contentChild.style, {\n width: `${contentWidth}px`,\n height: `${contentHeight}px`,\n transform: `translate(${translateX.toFixed(4)}px, ${translateY.toFixed(4)}px) scale(${scale.toFixed(4)})`,\n transformOrigin: \"top left\",\n });\n this.scale = scale;\n this.scaleLastSetOn = this.contentChild;\n }\n this.animationFrameId = requestAnimationFrame(this.setScale);\n }\n };\n\n removeScale = () => {\n if (this.scaleLastSetOn) {\n Object.assign(this.scaleLastSetOn.style, {\n width: \"\",\n height: \"\",\n transform: \"\",\n transformOrigin: \"\",\n });\n this.scaleLastSetOn = null;\n }\n };\n\n connectedCallback(): void {\n super.connectedCallback();\n this.animationFrameId = requestAnimationFrame(this.setScale);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeScale();\n if (this.animationFrameId) {\n cancelAnimationFrame(this.animationFrameId);\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-fit-scale\": EFFitScale;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"EFFitScale.js","names":["EFFitScale","results: HTMLElement[]","children","allContentElements: HTMLElement[]"],"sources":["../../src/gui/EFFitScale.ts"],"sourcesContent":["import { LitElement } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { createRef } from \"lit/directives/ref.js\";\n\n/* ━━ Pure scale calculation ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */\n\nexport interface ScaleInput {\n containerWidth: number;\n containerHeight: number;\n contentWidth: number;\n contentHeight: number;\n}\n\nexport interface ScaleOutput {\n scale: number;\n translateX: number;\n translateY: number;\n}\n\n/**\n * Compute the scale factor and centering translation needed to fit\n * content of a given size into a container while preserving aspect ratio.\n *\n * Returns `null` when any dimension is zero or negative (cannot compute).\n */\nexport function computeFitScale(input: ScaleInput): ScaleOutput | null {\n const { containerWidth, containerHeight, contentWidth, contentHeight } =\n input;\n\n if (\n containerWidth <= 0 ||\n containerHeight <= 0 ||\n contentWidth <= 0 ||\n contentHeight <= 0\n ) {\n return null;\n }\n\n const containerRatio = containerWidth / containerHeight;\n const contentRatio = contentWidth / contentHeight;\n\n const scale =\n containerRatio > contentRatio\n ? containerHeight / contentHeight\n : containerWidth / contentWidth;\n\n const scaledWidth = contentWidth * scale;\n const scaledHeight = contentHeight * scale;\n const translateX = (containerWidth - scaledWidth) / 2;\n const translateY = (containerHeight - scaledHeight) / 2;\n\n return { scale, translateX, translateY };\n}\n\n/* ━━ Component ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */\n\n@customElement(\"ef-fit-scale\")\nexport class EFFitScale extends LitElement {\n containerRef = createRef<HTMLDivElement>();\n contentRef = createRef<HTMLSlotElement>();\n\n createRenderRoot() {\n Object.assign(this.style, {\n display: \"grid\",\n width: \"100%\",\n height: \"100%\",\n gridTemplateColumns: \"100%\",\n gridTemplateRows: \"100%\",\n overflow: \"hidden\",\n boxSizing: \"border-box\",\n contain: \"layout paint style\",\n position: \"relative\",\n });\n this.id = `${this.uniqueId}`;\n return this;\n }\n\n uniqueId = Math.random().toString(36).substring(2, 15);\n\n @property({ type: Boolean })\n paused = false;\n\n updated(changedProperties: Map<string, unknown>): void {\n if (changedProperties.has(\"paused\") && !this.paused) {\n // When unpaused, immediately recalculate scale\n this.updateScale();\n }\n }\n\n private containerResizeObserver?: ResizeObserver;\n private contentResizeObserver?: ResizeObserver;\n private childMutationObserver?: MutationObserver;\n private observedContentChild: HTMLElement | null = null;\n private hasWarnedZeroDimensions = false;\n\n get contentChild() {\n if (!this.children.length) return null;\n\n const isNonContentElement = (element: Element): boolean => {\n const tagName = element.tagName.toLowerCase();\n const nonContentTags = [\n \"style\",\n \"script\",\n \"meta\",\n \"link\",\n \"title\",\n \"noscript\",\n ];\n if (nonContentTags.includes(tagName)) return true;\n\n try {\n const display = window.getComputedStyle(element).display;\n return display === \"none\" || display === \"contents\";\n } catch {\n return false;\n }\n };\n\n const findAllContentElements = (element: Element): HTMLElement[] => {\n const results: HTMLElement[] = [];\n\n if (element instanceof HTMLSlotElement) {\n const assigned = element.assignedElements()[0];\n if (assigned) {\n results.push(...findAllContentElements(assigned));\n }\n return results;\n }\n\n if (!isNonContentElement(element)) {\n results.push(element as HTMLElement);\n }\n\n const children = Array.from(element.children);\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (child) {\n results.push(...findAllContentElements(child));\n }\n }\n\n return results;\n };\n\n const children = Array.from(this.children);\n const allContentElements: HTMLElement[] = [];\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (child) {\n allContentElements.push(...findAllContentElements(child));\n }\n }\n\n if (allContentElements.length === 0) return null;\n\n return allContentElements[0] ?? null;\n }\n\n get scaleInfo() {\n if (!this.contentChild) {\n return {\n scale: 1,\n containerWidth: 0,\n containerHeight: 0,\n contentWidth: 0,\n contentHeight: 0,\n };\n }\n\n const containerWidth = this.clientWidth;\n const containerHeight = this.clientHeight;\n\n // Try to get natural dimensions from media elements (ef-video, ef-image)\n let contentWidth = 0;\n let contentHeight = 0;\n\n if (typeof (this.contentChild as any).getNaturalDimensions === \"function\") {\n const naturalDimensions = (\n this.contentChild as any\n ).getNaturalDimensions() as { width: number; height: number } | null;\n if (\n naturalDimensions &&\n naturalDimensions.width > 0 &&\n naturalDimensions.height > 0\n ) {\n contentWidth = naturalDimensions.width;\n contentHeight = naturalDimensions.height;\n\n // ESSENTIAL: For ef-video, set canvas to explicit pixel dimensions to break 100% circular dependency\n // Canvas default CSS is width:100%, height:100% which would make ef-video collapse to 0x0\n // when ef-video is set to width:auto, height:auto by ElementRenderer\n if (this.contentChild.tagName === \"EF-VIDEO\") {\n const canvas = (this.contentChild as any).canvasElement;\n if (canvas) {\n canvas.style.setProperty(\"width\", `${contentWidth}px`, \"important\");\n canvas.style.setProperty(\n \"height\",\n `${contentHeight}px`,\n \"important\",\n );\n }\n }\n } else {\n // Natural dimensions not available yet, fall back to client dimensions\n contentWidth = this.contentChild.clientWidth;\n contentHeight = this.contentChild.clientHeight;\n }\n } else {\n // For other elements, use clientWidth/Height\n contentWidth = this.contentChild.clientWidth;\n contentHeight = this.contentChild.clientHeight;\n }\n\n if (contentWidth === 0 || contentHeight === 0) {\n return {\n scale: 1,\n containerWidth,\n containerHeight,\n contentWidth: 0,\n contentHeight: 0,\n };\n }\n\n const result = computeFitScale({\n containerWidth,\n containerHeight,\n contentWidth,\n contentHeight,\n });\n\n return {\n scale: result?.scale ?? 1,\n containerWidth,\n containerHeight,\n contentWidth,\n contentHeight,\n };\n }\n\n scaleLastSetOn: HTMLElement | null = null;\n\n private updateScale = (): void => {\n if (!this.isConnected || this.paused) return;\n\n const { containerWidth, containerHeight, contentWidth, contentHeight } =\n this.scaleInfo;\n\n // Warn on zero container dimensions\n if (containerWidth === 0 || containerHeight === 0) {\n if (!this.hasWarnedZeroDimensions) {\n this.hasWarnedZeroDimensions = true;\n console.warn(\n `[ef-fit-scale] Container has zero dimensions (${containerWidth}×${containerHeight}). ` +\n `Content will be invisible. Ensure all ancestors have resolved height.`,\n this,\n );\n }\n return;\n }\n\n // Reset warning flag when dimensions become valid\n this.hasWarnedZeroDimensions = false;\n\n if (this.contentChild && contentWidth > 0 && contentHeight > 0) {\n const result = computeFitScale({\n containerWidth,\n containerHeight,\n contentWidth,\n contentHeight,\n });\n\n if (!result) return;\n\n // In the rare event that the content child is changed, we need to remove the scale\n // because we don't want to have a scale on the old content child that is somewhere else in the DOM\n if (this.scaleLastSetOn !== this.contentChild) {\n this.removeScale();\n }\n // Use toFixed to avoid floating point precision issues\n // this will update every frame with sub-pixel changes if we don't pin it down\n Object.assign(this.contentChild.style, {\n width: `${contentWidth}px`,\n height: `${contentHeight}px`,\n transform: `translate(${result.translateX.toFixed(4)}px, ${result.translateY.toFixed(4)}px) scale(${result.scale.toFixed(4)})`,\n transformOrigin: \"top left\",\n });\n this.scaleLastSetOn = this.contentChild;\n }\n };\n\n private observeContentChild(): void {\n const child = this.contentChild;\n if (child === this.observedContentChild) return;\n\n // Stop observing old child\n this.contentResizeObserver?.disconnect();\n\n // Observe new child\n if (child) {\n this.contentResizeObserver = new ResizeObserver(() => {\n this.updateScale();\n });\n this.contentResizeObserver.observe(child);\n }\n this.observedContentChild = child;\n }\n\n removeScale = () => {\n if (this.scaleLastSetOn) {\n Object.assign(this.scaleLastSetOn.style, {\n width: \"\",\n height: \"\",\n transform: \"\",\n transformOrigin: \"\",\n });\n this.scaleLastSetOn = null;\n }\n };\n\n connectedCallback(): void {\n super.connectedCallback();\n\n this.hasWarnedZeroDimensions = false;\n\n // Observe self for container size changes\n this.containerResizeObserver = new ResizeObserver(() => {\n this.updateScale();\n });\n this.containerResizeObserver.observe(this);\n\n // Observe child list for content child changes\n this.childMutationObserver = new MutationObserver(() => {\n this.observeContentChild();\n this.updateScale();\n });\n this.childMutationObserver.observe(this, { childList: true });\n\n // Initial content child observation\n this.observeContentChild();\n\n // Initial scale calculation (deferred to allow layout to settle)\n requestAnimationFrame(() => this.updateScale());\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeScale();\n this.containerResizeObserver?.disconnect();\n this.contentResizeObserver?.disconnect();\n this.childMutationObserver?.disconnect();\n this.observedContentChild = null;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-fit-scale\": EFFitScale;\n }\n}\n"],"mappings":"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"}
@@ -1,11 +1,11 @@
1
- import * as lit23 from "lit";
1
+ import * as lit24 from "lit";
2
2
  import { LitElement } from "lit";
3
3
  import * as lit_html22 from "lit-html";
4
4
  import * as lit_html_directives_ref_js3 from "lit-html/directives/ref.js";
5
5
 
6
6
  //#region src/gui/EFFocusOverlay.d.ts
7
7
  declare class EFFocusOverlay extends LitElement {
8
- static styles: lit23.CSSResult;
8
+ static styles: lit24.CSSResult;
9
9
  focusedElement?: HTMLElement | null;
10
10
  overlay: lit_html_directives_ref_js3.Ref<HTMLDivElement>;
11
11
  private animationFrame?;
@@ -36,9 +36,9 @@ let EFFocusOverlay = class EFFocusOverlay$1 extends LitElement {
36
36
  }
37
37
  .overlay {
38
38
  position: fixed;
39
- outline: 2px solid var(--ef-focus-overlay-color, rgb(59, 130, 246));
40
- background: var(--ef-focus-overlay-background, rgb(59, 130, 246));
41
- outline: 2px solid var(--ef-focus-overlay-color, rgb(59, 130, 246));
39
+ outline: 2px solid var(--ef-focus-overlay-color, var(--ef-color-primary));
40
+ background: var(--ef-focus-overlay-background, var(--ef-color-primary));
41
+ outline: 2px solid var(--ef-focus-overlay-color, var(--ef-color-primary));
42
42
  mix-blend-mode: multiply;
43
43
  opacity: 0.4;
44
44
  display: none;
@@ -1 +1 @@
1
- {"version":3,"file":"EFFocusOverlay.js","names":["EFFocusOverlay"],"sources":["../../src/gui/EFFocusOverlay.ts"],"sourcesContent":["import { consume } from \"@lit/context\";\nimport { css, html, LitElement } from \"lit\";\nimport { customElement } from \"lit/decorators.js\";\nimport { createRef, ref } from \"lit/directives/ref.js\";\nimport { focusedElementContext } from \"./focusedElementContext.js\";\n\n@customElement(\"ef-focus-overlay\")\nexport class EFFocusOverlay extends LitElement {\n static styles = css`\n :host {\n display: block;\n position: relative;\n width: 100%;\n height: 100%;\n pointer-events: none;\n }\n .overlay {\n position: fixed;\n outline: 2px solid var(--ef-focus-overlay-color, rgb(59, 130, 246));\n background: var(--ef-focus-overlay-background, rgb(59, 130, 246));\n outline: 2px solid var(--ef-focus-overlay-color, rgb(59, 130, 246));\n mix-blend-mode: multiply;\n opacity: 0.4;\n display: none;\n }\n `;\n\n @consume({ context: focusedElementContext, subscribe: true })\n focusedElement?: HTMLElement | null;\n\n overlay = createRef<HTMLDivElement>();\n\n private animationFrame?: number;\n\n drawOverlay = () => {\n const overlay = this.overlay.value;\n if (overlay) {\n if (this.focusedElement) {\n overlay.style.display = \"block\";\n const rect = this.focusedElement.getBoundingClientRect();\n Object.assign(overlay.style, {\n top: `${rect.top}px`,\n left: `${rect.left}px`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n });\n this.animationFrame = requestAnimationFrame(this.drawOverlay);\n } else {\n overlay.style.display = \"none\";\n }\n }\n };\n\n render() {\n return html`<div ${ref(this.overlay)} class=\"overlay\"></div>`;\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this.drawOverlay();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.animationFrame) {\n cancelAnimationFrame(this.animationFrame);\n }\n }\n\n protected updated(): void {\n this.drawOverlay();\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-focus-overlay\": EFFocusOverlay;\n }\n}\n"],"mappings":";;;;;;;;AAOO,2BAAMA,yBAAuB,WAAW;;;iBAuBnC,WAA2B;2BAIjB;GAClB,MAAM,UAAU,KAAK,QAAQ;AAC7B,OAAI,QACF,KAAI,KAAK,gBAAgB;AACvB,YAAQ,MAAM,UAAU;IACxB,MAAM,OAAO,KAAK,eAAe,uBAAuB;AACxD,WAAO,OAAO,QAAQ,OAAO;KAC3B,KAAK,GAAG,KAAK,IAAI;KACjB,MAAM,GAAG,KAAK,KAAK;KACnB,OAAO,GAAG,KAAK,MAAM;KACrB,QAAQ,GAAG,KAAK,OAAO;KACxB,CAAC;AACF,SAAK,iBAAiB,sBAAsB,KAAK,YAAY;SAE7D,SAAQ,MAAM,UAAU;;;;gBAxCd,GAAG;;;;;;;;;;;;;;;;;;;CA6CnB,SAAS;AACP,SAAO,IAAI,QAAQ,IAAI,KAAK,QAAQ,CAAC;;CAGvC,oBAA0B;AACxB,QAAM,mBAAmB;AACzB,OAAK,aAAa;;CAGpB,uBAA6B;AAC3B,QAAM,sBAAsB;AAC5B,MAAI,KAAK,eACP,sBAAqB,KAAK,eAAe;;CAI7C,AAAU,UAAgB;AACxB,OAAK,aAAa;;;YA3CnB,QAAQ;CAAE,SAAS;CAAuB,WAAW;CAAM,CAAC;6BArB9D,cAAc,mBAAmB"}
1
+ {"version":3,"file":"EFFocusOverlay.js","names":["EFFocusOverlay"],"sources":["../../src/gui/EFFocusOverlay.ts"],"sourcesContent":["import { consume } from \"@lit/context\";\nimport { css, html, LitElement } from \"lit\";\nimport { customElement } from \"lit/decorators.js\";\nimport { createRef, ref } from \"lit/directives/ref.js\";\nimport { focusedElementContext } from \"./focusedElementContext.js\";\n\n@customElement(\"ef-focus-overlay\")\nexport class EFFocusOverlay extends LitElement {\n static styles = css`\n :host {\n display: block;\n position: relative;\n width: 100%;\n height: 100%;\n pointer-events: none;\n }\n .overlay {\n position: fixed;\n outline: 2px solid var(--ef-focus-overlay-color, var(--ef-color-primary));\n background: var(--ef-focus-overlay-background, var(--ef-color-primary));\n outline: 2px solid var(--ef-focus-overlay-color, var(--ef-color-primary));\n mix-blend-mode: multiply;\n opacity: 0.4;\n display: none;\n }\n `;\n\n @consume({ context: focusedElementContext, subscribe: true })\n focusedElement?: HTMLElement | null;\n\n overlay = createRef<HTMLDivElement>();\n\n private animationFrame?: number;\n\n drawOverlay = () => {\n const overlay = this.overlay.value;\n if (overlay) {\n if (this.focusedElement) {\n overlay.style.display = \"block\";\n const rect = this.focusedElement.getBoundingClientRect();\n Object.assign(overlay.style, {\n top: `${rect.top}px`,\n left: `${rect.left}px`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n });\n this.animationFrame = requestAnimationFrame(this.drawOverlay);\n } else {\n overlay.style.display = \"none\";\n }\n }\n };\n\n render() {\n return html`<div ${ref(this.overlay)} class=\"overlay\"></div>`;\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this.drawOverlay();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.animationFrame) {\n cancelAnimationFrame(this.animationFrame);\n }\n }\n\n protected updated(): void {\n this.drawOverlay();\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-focus-overlay\": EFFocusOverlay;\n }\n}\n"],"mappings":";;;;;;;;AAOO,2BAAMA,yBAAuB,WAAW;;;iBAuBnC,WAA2B;2BAIjB;GAClB,MAAM,UAAU,KAAK,QAAQ;AAC7B,OAAI,QACF,KAAI,KAAK,gBAAgB;AACvB,YAAQ,MAAM,UAAU;IACxB,MAAM,OAAO,KAAK,eAAe,uBAAuB;AACxD,WAAO,OAAO,QAAQ,OAAO;KAC3B,KAAK,GAAG,KAAK,IAAI;KACjB,MAAM,GAAG,KAAK,KAAK;KACnB,OAAO,GAAG,KAAK,MAAM;KACrB,QAAQ,GAAG,KAAK,OAAO;KACxB,CAAC;AACF,SAAK,iBAAiB,sBAAsB,KAAK,YAAY;SAE7D,SAAQ,MAAM,UAAU;;;;gBAxCd,GAAG;;;;;;;;;;;;;;;;;;;CA6CnB,SAAS;AACP,SAAO,IAAI,QAAQ,IAAI,KAAK,QAAQ,CAAC;;CAGvC,oBAA0B;AACxB,QAAM,mBAAmB;AACzB,OAAK,aAAa;;CAGpB,uBAA6B;AAC3B,QAAM,sBAAsB;AAC5B,MAAI,KAAK,eACP,sBAAqB,KAAK,eAAe;;CAI7C,AAAU,UAAgB;AACxB,OAAK,aAAa;;;YA3CnB,QAAQ;CAAE,SAAS;CAAuB,WAAW;CAAM,CAAC;6BArB9D,cAAc,mBAAmB"}
@@ -1,6 +1,6 @@
1
1
  import * as lit32 from "lit";
2
2
  import { LitElement } from "lit";
3
- import * as lit_html31 from "lit-html";
3
+ import * as lit_html30 from "lit-html";
4
4
 
5
5
  //#region src/gui/EFOverlayItem.d.ts
6
6
  /**
@@ -36,7 +36,7 @@ declare class EFOverlayItem extends LitElement {
36
36
  updatePosition(): void;
37
37
  connectedCallback(): void;
38
38
  disconnectedCallback(): void;
39
- render(): lit_html31.TemplateResult<1>;
39
+ render(): lit_html30.TemplateResult<1>;
40
40
  }
41
41
  declare global {
42
42
  interface HTMLElementTagNameMap {
@@ -2,7 +2,7 @@ import { PanZoomTransform } from "../elements/EFPanZoom.js";
2
2
  import { EFOverlayItem } from "./EFOverlayItem.js";
3
3
  import * as lit31 from "lit";
4
4
  import { LitElement } from "lit";
5
- import * as lit_html30 from "lit-html";
5
+ import * as lit_html29 from "lit-html";
6
6
 
7
7
  //#region src/gui/EFOverlayLayer.d.ts
8
8
 
@@ -58,7 +58,7 @@ declare class EFOverlayLayer extends LitElement {
58
58
  connectedCallback(): void;
59
59
  disconnectedCallback(): void;
60
60
  updated(): void;
61
- render(): lit_html30.TemplateResult<1>;
61
+ render(): lit_html29.TemplateResult<1>;
62
62
  }
63
63
  declare global {
64
64
  interface HTMLElementTagNameMap {
@@ -1,5 +1,5 @@
1
1
  import { ControllableInterface } from "./Controllable.js";
2
- import * as lit16 from "lit";
2
+ import * as lit17 from "lit";
3
3
  import { LitElement } from "lit";
4
4
  import * as lit_html16 from "lit-html";
5
5
 
@@ -10,7 +10,7 @@ declare const EFPause_base: (new (...args: any[]) => {
10
10
  effectiveContext: ControllableInterface | null;
11
11
  }) & typeof LitElement;
12
12
  declare class EFPause extends EFPause_base {
13
- static styles: lit16.CSSResult[];
13
+ static styles: lit17.CSSResult[];
14
14
  playing: boolean;
15
15
  get efContext(): ControllableInterface | null;
16
16
  connectedCallback(): void;
@@ -1,6 +1,6 @@
1
+ import { efContext } from "./efContext.js";
1
2
  import { playingContext } from "./playingContext.js";
2
3
  import { __decorate } from "../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
3
- import { efContext } from "./efContext.js";
4
4
  import { attachContextRoot } from "../attachContextRoot.js";
5
5
  import { TargetOrContextMixin } from "./TargetOrContextMixin.js";
6
6
  import { consume } from "@lit/context";
@@ -1,5 +1,5 @@
1
1
  import { ControllableInterface } from "./Controllable.js";
2
- import * as lit15 from "lit";
2
+ import * as lit16 from "lit";
3
3
  import { LitElement } from "lit";
4
4
  import * as lit_html15 from "lit-html";
5
5
 
@@ -10,7 +10,7 @@ declare const EFPlay_base: (new (...args: any[]) => {
10
10
  effectiveContext: ControllableInterface | null;
11
11
  }) & typeof LitElement;
12
12
  declare class EFPlay extends EFPlay_base {
13
- static styles: lit15.CSSResult[];
13
+ static styles: lit16.CSSResult[];
14
14
  playing: boolean;
15
15
  get efContext(): ControllableInterface | null;
16
16
  connectedCallback(): void;
@@ -1,6 +1,6 @@
1
+ import { efContext } from "./efContext.js";
1
2
  import { playingContext } from "./playingContext.js";
2
3
  import { __decorate } from "../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
3
- import { efContext } from "./efContext.js";
4
4
  import { attachContextRoot } from "../attachContextRoot.js";
5
5
  import { TargetOrContextMixin } from "./TargetOrContextMixin.js";
6
6
  import { consume } from "@lit/context";
@@ -1,8 +1,8 @@
1
+ import { TWMixin } from "./TWMixin2.js";
1
2
  import { __decorate } from "../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
2
3
  import { isEFTemporal } from "../elements/EFTemporal.js";
3
4
  import { focusedElementContext } from "./focusedElementContext.js";
4
5
  import { ContextMixin } from "./ContextMixin.js";
5
- import { TWMixin } from "./TWMixin2.js";
6
6
  import { EFTargetable } from "../elements/TargetController.js";
7
7
  import { provide } from "@lit/context";
8
8
  import { LitElement, css, html } from "lit";
@@ -1,4 +1,4 @@
1
- import * as lit25 from "lit";
1
+ import * as lit26 from "lit";
2
2
  import { LitElement } from "lit";
3
3
  import * as lit_html24 from "lit-html";
4
4
 
@@ -21,7 +21,7 @@ declare class EFResizableBox extends LitElement {
21
21
  private resizeStartCorner;
22
22
  private resizeStartSize;
23
23
  private resizeStartPosition;
24
- static styles: lit25.CSSResult;
24
+ static styles: lit26.CSSResult;
25
25
  private resizeObserver?;
26
26
  connectedCallback(): void;
27
27
  disconnectedCallback(): void;
@@ -101,17 +101,17 @@ let EFResizableBox = class EFResizableBox$1 extends LitElement {
101
101
  this.styles = css`
102
102
  .box {
103
103
  position: absolute;
104
- border: 2px solid var(--ef-resizable-box-border-color, #3b82f6);
105
- background-color: var(--ef-resizable-box-bg-color, rgba(59, 130, 246, 0.2));
104
+ border: 2px solid var(--ef-resizable-box-border-color, var(--ef-color-primary));
105
+ background-color: var(--ef-resizable-box-bg-color, color-mix(in srgb, var(--ef-color-primary) 20%, transparent));
106
106
  cursor: grab;
107
107
  }
108
108
  .box.dragging {
109
- border-color: var(--ef-resizable-box-dragging-border-color, #2563eb);
110
- background-color: var(--ef-resizable-box-dragging-bg-color, rgba(37, 99, 235, 0.3));
109
+ border-color: var(--ef-resizable-box-dragging-border-color, var(--ef-color-primary));
110
+ background-color: var(--ef-resizable-box-dragging-bg-color, color-mix(in srgb, var(--ef-color-primary) 30%, transparent));
111
111
  }
112
112
  .handle {
113
113
  position: absolute;
114
- background-color: var(--ef-resizable-box-handle-color, #3b82f6);
114
+ background-color: var(--ef-resizable-box-handle-color, var(--ef-color-primary));
115
115
  touch-action: none;
116
116
  }
117
117
  .handle.nw { top: -4px; left: -4px; width: 8px; height: 8px; cursor: nwse-resize; }
@@ -1 +1 @@
1
- {"version":3,"file":"EFResizableBox.js","names":["EFResizableBox"],"sources":["../../src/gui/EFResizableBox.ts"],"sourcesContent":["import { css, html, LitElement } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { styleMap } from \"lit/directives/style-map.js\";\nimport { getCornerPoint, getOppositeCorner } from \"./transformUtils.js\";\n\nconst DEFAULT_MIN_SIZE = 10;\n\nexport interface BoxBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\ntype ResizeHandle = \"nw\" | \"n\" | \"ne\" | \"e\" | \"se\" | \"s\" | \"sw\" | \"w\";\n\nfunction mapHandleToLegacy(handle: ResizeHandle): string {\n const map: Record<ResizeHandle, string> = {\n nw: \"top-left\",\n n: \"top\",\n ne: \"top-right\",\n e: \"right\",\n se: \"bottom-right\",\n s: \"bottom\",\n sw: \"bottom-left\",\n w: \"left\",\n };\n return map[handle];\n}\n\n@customElement(\"ef-resizable-box\")\nexport class EFResizableBox extends LitElement {\n @property({ type: Object })\n bounds: BoxBounds = { x: 0, y: 0, width: 100, height: 100 };\n\n @state()\n private containerWidth = 0;\n\n @state()\n private containerHeight = 0;\n\n @property({ type: Number })\n minSize = DEFAULT_MIN_SIZE;\n\n @state()\n private isDragging = false;\n\n @state()\n private isResizing: ResizeHandle | null = null;\n\n private dragStart: { x: number; y: number } | null = null;\n private dragStartPosition: { x: number; y: number } = { x: 0, y: 0 };\n private resizeStartCorner: { x: number; y: number } | null = null;\n private resizeStartSize: { width: number; height: number } | null = null;\n private resizeStartPosition: { x: number; y: number } | null = null;\n\n static styles = css`\n .box {\n position: absolute;\n border: 2px solid var(--ef-resizable-box-border-color, #3b82f6);\n background-color: var(--ef-resizable-box-bg-color, rgba(59, 130, 246, 0.2));\n cursor: grab;\n }\n .box.dragging {\n border-color: var(--ef-resizable-box-dragging-border-color, #2563eb);\n background-color: var(--ef-resizable-box-dragging-bg-color, rgba(37, 99, 235, 0.3));\n }\n .handle {\n position: absolute;\n background-color: var(--ef-resizable-box-handle-color, #3b82f6);\n touch-action: none;\n }\n .handle.nw { top: -4px; left: -4px; width: 8px; height: 8px; cursor: nwse-resize; }\n .handle.ne { top: -4px; right: -4px; width: 8px; height: 8px; cursor: nesw-resize; }\n .handle.sw { bottom: -4px; left: -4px; width: 8px; height: 8px; cursor: nesw-resize; }\n .handle.se { bottom: -4px; right: -4px; width: 8px; height: 8px; cursor: nwse-resize; }\n .handle.n { top: -4px; left: 4px; right: 4px; height: 8px; cursor: ns-resize; }\n .handle.e { top: 4px; bottom: 4px; right: -4px; width: 8px; cursor: ew-resize; }\n .handle.s { bottom: -4px; left: 4px; right: 4px; height: 8px; cursor: ns-resize; }\n .handle.w { top: 4px; bottom: 4px; left: -4px; width: 8px; cursor: ew-resize; }\n `;\n\n private resizeObserver?: ResizeObserver;\n\n connectedCallback() {\n super.connectedCallback();\n if (this.offsetParent) {\n this.containerWidth = this.offsetParent.clientWidth;\n this.containerHeight = this.offsetParent.clientHeight;\n }\n this.resizeObserver = new ResizeObserver(() => {\n if (this.offsetParent) {\n this.containerWidth = this.offsetParent.clientWidth;\n this.containerHeight = this.offsetParent.clientHeight;\n }\n });\n if (this.offsetParent) {\n this.resizeObserver.observe(this.offsetParent);\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.resizeObserver?.disconnect();\n this.cleanup();\n }\n\n private handlePointerDown = (\n e: PointerEvent,\n mode: \"move\" | \"resize\",\n handle?: ResizeHandle,\n ) => {\n e.preventDefault();\n e.stopPropagation();\n this.isDragging = true;\n this.isResizing = mode === \"resize\" ? handle || null : null;\n\n this.dragStart = { x: e.clientX, y: e.clientY };\n this.dragStartPosition = { x: this.bounds.x, y: this.bounds.y };\n\n if (mode === \"resize\" && handle) {\n const oppositeCorner = getOppositeCorner(handle);\n const rotationRadians = 0;\n const initialCorner = getCornerPoint(\n this.bounds.x,\n this.bounds.y,\n this.bounds.width,\n this.bounds.height,\n rotationRadians,\n oppositeCorner.x,\n oppositeCorner.y,\n );\n this.resizeStartCorner = initialCorner;\n this.resizeStartSize = {\n width: this.bounds.width,\n height: this.bounds.height,\n };\n this.resizeStartPosition = { x: this.bounds.x, y: this.bounds.y };\n }\n\n document.addEventListener(\"pointermove\", this.handlePointerMove, {\n passive: false,\n });\n document.addEventListener(\"pointerup\", this.handlePointerUp, {\n passive: false,\n });\n };\n\n private handlePointerMove = (e: PointerEvent) => {\n if (!this.isDragging || !this.dragStart) return;\n\n e.preventDefault();\n\n const deltaX = e.clientX - this.dragStart.x;\n const deltaY = e.clientY - this.dragStart.y;\n\n if (\n this.isResizing &&\n this.resizeStartCorner &&\n this.resizeStartSize &&\n this.resizeStartPosition\n ) {\n const oppositeCorner = getOppositeCorner(this.isResizing);\n const rotationRadians = 0;\n\n let newWidth = this.resizeStartSize.width;\n let newHeight = this.resizeStartSize.height;\n\n if (this.isResizing.includes(\"e\")) {\n newWidth = this.resizeStartSize.width + deltaX;\n } else if (this.isResizing.includes(\"w\")) {\n newWidth = this.resizeStartSize.width - deltaX;\n }\n\n if (this.isResizing.includes(\"s\")) {\n newHeight = this.resizeStartSize.height + deltaY;\n } else if (this.isResizing.includes(\"n\")) {\n newHeight = this.resizeStartSize.height - deltaY;\n }\n\n newWidth = Math.max(\n this.minSize,\n Math.min(this.containerWidth - this.bounds.x, newWidth),\n );\n newHeight = Math.max(\n this.minSize,\n Math.min(this.containerHeight - this.bounds.y, newHeight),\n );\n\n const newOppositeCorner = getCornerPoint(\n this.resizeStartPosition.x,\n this.resizeStartPosition.y,\n newWidth,\n newHeight,\n rotationRadians,\n oppositeCorner.x,\n oppositeCorner.y,\n );\n\n const offsetX = this.resizeStartCorner.x - newOppositeCorner.x;\n const offsetY = this.resizeStartCorner.y - newOppositeCorner.y;\n\n const newX = Math.max(\n 0,\n Math.min(\n this.containerWidth - newWidth,\n this.resizeStartPosition.x + offsetX,\n ),\n );\n const newY = Math.max(\n 0,\n Math.min(\n this.containerHeight - newHeight,\n this.resizeStartPosition.y + offsetY,\n ),\n );\n\n this.bounds = {\n x: newX,\n y: newY,\n width: newWidth,\n height: newHeight,\n };\n } else {\n const constrainedX = Math.max(\n 0,\n Math.min(\n this.containerWidth - this.bounds.width,\n this.dragStartPosition.x + deltaX,\n ),\n );\n const constrainedY = Math.max(\n 0,\n Math.min(\n this.containerHeight - this.bounds.height,\n this.dragStartPosition.y + deltaY,\n ),\n );\n\n this.bounds = {\n ...this.bounds,\n x: constrainedX,\n y: constrainedY,\n };\n }\n\n this.dispatchBoundsChange();\n };\n\n private handlePointerUp = (e: PointerEvent) => {\n e.preventDefault();\n this.cleanup();\n };\n\n private cleanup() {\n this.isDragging = false;\n this.isResizing = null;\n this.dragStart = null;\n this.dragStartPosition = { x: 0, y: 0 };\n this.resizeStartCorner = null;\n this.resizeStartSize = null;\n this.resizeStartPosition = null;\n document.removeEventListener(\"pointermove\", this.handlePointerMove);\n document.removeEventListener(\"pointerup\", this.handlePointerUp);\n }\n\n private dispatchBoundsChange() {\n this.dispatchEvent(\n new CustomEvent(\"bounds-change\", {\n detail: { bounds: this.bounds },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n render() {\n const boxStyles = {\n left: `${this.bounds.x}px`,\n top: `${this.bounds.y}px`,\n width: `${this.bounds.width}px`,\n height: `${this.bounds.height}px`,\n };\n\n const handles: ResizeHandle[] = [\n \"nw\",\n \"n\",\n \"ne\",\n \"e\",\n \"se\",\n \"s\",\n \"sw\",\n \"w\",\n ];\n\n return html`\n <div\n class=\"box ${this.isDragging ? \"dragging\" : \"\"}\"\n style=${styleMap(boxStyles)}\n @pointerdown=${(e: PointerEvent) => this.handlePointerDown(e, \"move\")}\n >\n ${handles.map(\n (handle) => html`\n <div\n class=\"handle ${handle}\"\n @pointerdown=${(e: PointerEvent) => {\n e.stopPropagation();\n this.handlePointerDown(e, \"resize\", handle);\n }}\n ></div>\n `,\n )}\n <slot></slot>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"EFResizableBox.js","names":["EFResizableBox"],"sources":["../../src/gui/EFResizableBox.ts"],"sourcesContent":["import { css, html, LitElement } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { styleMap } from \"lit/directives/style-map.js\";\nimport { getCornerPoint, getOppositeCorner } from \"./transformUtils.js\";\n\nconst DEFAULT_MIN_SIZE = 10;\n\nexport interface BoxBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\ntype ResizeHandle = \"nw\" | \"n\" | \"ne\" | \"e\" | \"se\" | \"s\" | \"sw\" | \"w\";\n\n@customElement(\"ef-resizable-box\")\nexport class EFResizableBox extends LitElement {\n @property({ type: Object })\n bounds: BoxBounds = { x: 0, y: 0, width: 100, height: 100 };\n\n @state()\n private containerWidth = 0;\n\n @state()\n private containerHeight = 0;\n\n @property({ type: Number })\n minSize = DEFAULT_MIN_SIZE;\n\n @state()\n private isDragging = false;\n\n @state()\n private isResizing: ResizeHandle | null = null;\n\n private dragStart: { x: number; y: number } | null = null;\n private dragStartPosition: { x: number; y: number } = { x: 0, y: 0 };\n private resizeStartCorner: { x: number; y: number } | null = null;\n private resizeStartSize: { width: number; height: number } | null = null;\n private resizeStartPosition: { x: number; y: number } | null = null;\n\n static styles = css`\n .box {\n position: absolute;\n border: 2px solid var(--ef-resizable-box-border-color, var(--ef-color-primary));\n background-color: var(--ef-resizable-box-bg-color, color-mix(in srgb, var(--ef-color-primary) 20%, transparent));\n cursor: grab;\n }\n .box.dragging {\n border-color: var(--ef-resizable-box-dragging-border-color, var(--ef-color-primary));\n background-color: var(--ef-resizable-box-dragging-bg-color, color-mix(in srgb, var(--ef-color-primary) 30%, transparent));\n }\n .handle {\n position: absolute;\n background-color: var(--ef-resizable-box-handle-color, var(--ef-color-primary));\n touch-action: none;\n }\n .handle.nw { top: -4px; left: -4px; width: 8px; height: 8px; cursor: nwse-resize; }\n .handle.ne { top: -4px; right: -4px; width: 8px; height: 8px; cursor: nesw-resize; }\n .handle.sw { bottom: -4px; left: -4px; width: 8px; height: 8px; cursor: nesw-resize; }\n .handle.se { bottom: -4px; right: -4px; width: 8px; height: 8px; cursor: nwse-resize; }\n .handle.n { top: -4px; left: 4px; right: 4px; height: 8px; cursor: ns-resize; }\n .handle.e { top: 4px; bottom: 4px; right: -4px; width: 8px; cursor: ew-resize; }\n .handle.s { bottom: -4px; left: 4px; right: 4px; height: 8px; cursor: ns-resize; }\n .handle.w { top: 4px; bottom: 4px; left: -4px; width: 8px; cursor: ew-resize; }\n `;\n\n private resizeObserver?: ResizeObserver;\n\n connectedCallback() {\n super.connectedCallback();\n if (this.offsetParent) {\n this.containerWidth = this.offsetParent.clientWidth;\n this.containerHeight = this.offsetParent.clientHeight;\n }\n this.resizeObserver = new ResizeObserver(() => {\n if (this.offsetParent) {\n this.containerWidth = this.offsetParent.clientWidth;\n this.containerHeight = this.offsetParent.clientHeight;\n }\n });\n if (this.offsetParent) {\n this.resizeObserver.observe(this.offsetParent);\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.resizeObserver?.disconnect();\n this.cleanup();\n }\n\n private handlePointerDown = (\n e: PointerEvent,\n mode: \"move\" | \"resize\",\n handle?: ResizeHandle,\n ) => {\n e.preventDefault();\n e.stopPropagation();\n this.isDragging = true;\n this.isResizing = mode === \"resize\" ? handle || null : null;\n\n this.dragStart = { x: e.clientX, y: e.clientY };\n this.dragStartPosition = { x: this.bounds.x, y: this.bounds.y };\n\n if (mode === \"resize\" && handle) {\n const oppositeCorner = getOppositeCorner(handle);\n const rotationRadians = 0;\n const initialCorner = getCornerPoint(\n this.bounds.x,\n this.bounds.y,\n this.bounds.width,\n this.bounds.height,\n rotationRadians,\n oppositeCorner.x,\n oppositeCorner.y,\n );\n this.resizeStartCorner = initialCorner;\n this.resizeStartSize = {\n width: this.bounds.width,\n height: this.bounds.height,\n };\n this.resizeStartPosition = { x: this.bounds.x, y: this.bounds.y };\n }\n\n document.addEventListener(\"pointermove\", this.handlePointerMove, {\n passive: false,\n });\n document.addEventListener(\"pointerup\", this.handlePointerUp, {\n passive: false,\n });\n };\n\n private handlePointerMove = (e: PointerEvent) => {\n if (!this.isDragging || !this.dragStart) return;\n\n e.preventDefault();\n\n const deltaX = e.clientX - this.dragStart.x;\n const deltaY = e.clientY - this.dragStart.y;\n\n if (\n this.isResizing &&\n this.resizeStartCorner &&\n this.resizeStartSize &&\n this.resizeStartPosition\n ) {\n const oppositeCorner = getOppositeCorner(this.isResizing);\n const rotationRadians = 0;\n\n let newWidth = this.resizeStartSize.width;\n let newHeight = this.resizeStartSize.height;\n\n if (this.isResizing.includes(\"e\")) {\n newWidth = this.resizeStartSize.width + deltaX;\n } else if (this.isResizing.includes(\"w\")) {\n newWidth = this.resizeStartSize.width - deltaX;\n }\n\n if (this.isResizing.includes(\"s\")) {\n newHeight = this.resizeStartSize.height + deltaY;\n } else if (this.isResizing.includes(\"n\")) {\n newHeight = this.resizeStartSize.height - deltaY;\n }\n\n newWidth = Math.max(\n this.minSize,\n Math.min(this.containerWidth - this.bounds.x, newWidth),\n );\n newHeight = Math.max(\n this.minSize,\n Math.min(this.containerHeight - this.bounds.y, newHeight),\n );\n\n const newOppositeCorner = getCornerPoint(\n this.resizeStartPosition.x,\n this.resizeStartPosition.y,\n newWidth,\n newHeight,\n rotationRadians,\n oppositeCorner.x,\n oppositeCorner.y,\n );\n\n const offsetX = this.resizeStartCorner.x - newOppositeCorner.x;\n const offsetY = this.resizeStartCorner.y - newOppositeCorner.y;\n\n const newX = Math.max(\n 0,\n Math.min(\n this.containerWidth - newWidth,\n this.resizeStartPosition.x + offsetX,\n ),\n );\n const newY = Math.max(\n 0,\n Math.min(\n this.containerHeight - newHeight,\n this.resizeStartPosition.y + offsetY,\n ),\n );\n\n this.bounds = {\n x: newX,\n y: newY,\n width: newWidth,\n height: newHeight,\n };\n } else {\n const constrainedX = Math.max(\n 0,\n Math.min(\n this.containerWidth - this.bounds.width,\n this.dragStartPosition.x + deltaX,\n ),\n );\n const constrainedY = Math.max(\n 0,\n Math.min(\n this.containerHeight - this.bounds.height,\n this.dragStartPosition.y + deltaY,\n ),\n );\n\n this.bounds = {\n ...this.bounds,\n x: constrainedX,\n y: constrainedY,\n };\n }\n\n this.dispatchBoundsChange();\n };\n\n private handlePointerUp = (e: PointerEvent) => {\n e.preventDefault();\n this.cleanup();\n };\n\n private cleanup() {\n this.isDragging = false;\n this.isResizing = null;\n this.dragStart = null;\n this.dragStartPosition = { x: 0, y: 0 };\n this.resizeStartCorner = null;\n this.resizeStartSize = null;\n this.resizeStartPosition = null;\n document.removeEventListener(\"pointermove\", this.handlePointerMove);\n document.removeEventListener(\"pointerup\", this.handlePointerUp);\n }\n\n private dispatchBoundsChange() {\n this.dispatchEvent(\n new CustomEvent(\"bounds-change\", {\n detail: { bounds: this.bounds },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n render() {\n const boxStyles = {\n left: `${this.bounds.x}px`,\n top: `${this.bounds.y}px`,\n width: `${this.bounds.width}px`,\n height: `${this.bounds.height}px`,\n };\n\n const handles: ResizeHandle[] = [\n \"nw\",\n \"n\",\n \"ne\",\n \"e\",\n \"se\",\n \"s\",\n \"sw\",\n \"w\",\n ];\n\n return html`\n <div\n class=\"box ${this.isDragging ? \"dragging\" : \"\"}\"\n style=${styleMap(boxStyles)}\n @pointerdown=${(e: PointerEvent) => this.handlePointerDown(e, \"move\")}\n >\n ${handles.map(\n (handle) => html`\n <div\n class=\"handle ${handle}\"\n @pointerdown=${(e: PointerEvent) => {\n e.stopPropagation();\n this.handlePointerDown(e, \"resize\", handle);\n }}\n ></div>\n `,\n )}\n <slot></slot>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { ControllableInterface } from "./Controllable.js";
2
- import * as lit18 from "lit";
2
+ import * as lit19 from "lit";
3
3
  import { LitElement } from "lit";
4
4
  import * as lit_html18 from "lit-html";
5
5
 
@@ -10,7 +10,7 @@ declare const EFScrubber_base: (new (...args: any[]) => {
10
10
  effectiveContext: ControllableInterface | null;
11
11
  }) & typeof LitElement;
12
12
  declare class EFScrubber extends EFScrubber_base {
13
- static styles: lit18.CSSResult[];
13
+ static styles: lit19.CSSResult[];
14
14
  playing: boolean;
15
15
  contextCurrentTimeMs: number;
16
16
  contextDurationMs: number;
@@ -1,8 +1,8 @@
1
+ import { efContext } from "./efContext.js";
1
2
  import { currentTimeContext } from "./currentTimeContext.js";
2
3
  import { durationContext } from "./durationContext.js";
3
4
  import { playingContext } from "./playingContext.js";
4
5
  import { __decorate } from "../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
5
- import { efContext } from "./efContext.js";
6
6
  import { quantizeToFrameTimeMs } from "./EFTimelineRuler.js";
7
7
  import { TargetOrContextMixin } from "./TargetOrContextMixin.js";
8
8
  import { consume } from "@lit/context";
@@ -12,12 +12,12 @@ import { createRef, ref } from "lit/directives/ref.js";
12
12
 
13
13
  //#region src/gui/EFScrubber.ts
14
14
  const BASE_PIXELS_PER_SECOND = 100;
15
- function timeToPixels(timeMs, durationMs, containerWidth, zoomScale) {
15
+ function timeToPixels(timeMs, durationMs, _containerWidth, zoomScale) {
16
16
  if (durationMs <= 0) return 0;
17
17
  const pixelsPerSecond = BASE_PIXELS_PER_SECOND * zoomScale;
18
18
  return timeMs / 1e3 * pixelsPerSecond;
19
19
  }
20
- function pixelsToTime(pixels, durationMs, containerWidth, zoomScale) {
20
+ function pixelsToTime(pixels, durationMs, _containerWidth, zoomScale) {
21
21
  if (durationMs <= 0) return 0;
22
22
  return pixels / (BASE_PIXELS_PER_SECOND * zoomScale) * 1e3;
23
23
  }
@@ -78,8 +78,8 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
78
78
  this.styles = [css`
79
79
  :host {
80
80
  --ef-scrubber-height: 4px;
81
- --ef-scrubber-background: rgb(209 213 219);
82
- --ef-scrubber-progress-color: rgb(37 99 235);
81
+ --ef-scrubber-background: var(--ef-color-border, rgba(255, 255, 255, 0.2));
82
+ --ef-scrubber-progress-color: var(--ef-color-primary, #fff);
83
83
  --ef-scrubber-handle-size: 12px;
84
84
  width: 100%;
85
85
  display: flex;
@@ -87,11 +87,6 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
87
87
  justify-content: center;
88
88
  }
89
89
 
90
- :host(.dark), :host-context(.dark) {
91
- --ef-scrubber-background: rgb(75 85 99);
92
- --ef-scrubber-progress-color: rgb(96 165 250);
93
- }
94
-
95
90
  :host([orientation="vertical"]) {
96
91
  width: 100%;
97
92
  height: 100%;
@@ -175,7 +170,7 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
175
170
  top: 0;
176
171
  bottom: 0;
177
172
  width: 2px;
178
- background: rgba(37, 99, 235, 0.2);
173
+ background: color-mix(in srgb, var(--ef-color-primary) 20%, transparent);
179
174
  pointer-events: none;
180
175
  z-index: 20;
181
176
  }
@@ -303,8 +298,8 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
303
298
  @pointerdown=${this.handlePointerDown}
304
299
  @contextmenu=${this.boundHandleContextMenu}
305
300
  >
306
- <div class="progress" style="width: ${displayProgress * 100}%"></div>
307
- <div class="handle" style="left: ${displayProgress * 100}%"></div>
301
+ <div part="progress" class="progress" style="width: ${displayProgress * 100}%"></div>
302
+ <div part="handle" class="handle" style="left: ${displayProgress * 100}%"></div>
308
303
  </div>
309
304
  `;
310
305
  }