@editframe/elements 0.30.1-beta.0 → 0.31.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EF_FRAMEGEN.d.ts +5 -0
- package/dist/EF_FRAMEGEN.js +20 -4
- package/dist/EF_FRAMEGEN.js.map +1 -1
- package/dist/EF_INTERACTIVE.js.map +1 -1
- package/dist/_virtual/rolldown_runtime.js +27 -0
- package/dist/canvas/EFCanvas.d.ts +311 -0
- package/dist/canvas/EFCanvas.js +1089 -0
- package/dist/canvas/EFCanvas.js.map +1 -0
- package/dist/canvas/EFCanvasItem.d.ts +55 -0
- package/dist/canvas/EFCanvasItem.js +72 -0
- package/dist/canvas/EFCanvasItem.js.map +1 -0
- package/dist/canvas/api/CanvasAPI.d.ts +115 -0
- package/dist/canvas/api/CanvasAPI.js +182 -0
- package/dist/canvas/api/CanvasAPI.js.map +1 -0
- package/dist/canvas/api/types.d.ts +42 -0
- package/dist/canvas/coordinateTransform.js +90 -0
- package/dist/canvas/coordinateTransform.js.map +1 -0
- package/dist/canvas/getElementBounds.js +40 -0
- package/dist/canvas/getElementBounds.js.map +1 -0
- package/dist/canvas/overlays/SelectionOverlay.js +265 -0
- package/dist/canvas/overlays/SelectionOverlay.js.map +1 -0
- package/dist/canvas/overlays/overlayState.js +153 -0
- package/dist/canvas/overlays/overlayState.js.map +1 -0
- package/dist/canvas/selection/SelectionController.js +105 -0
- package/dist/canvas/selection/SelectionController.js.map +1 -0
- package/dist/canvas/selection/SelectionModel.d.ts +98 -0
- package/dist/canvas/selection/SelectionModel.js +229 -0
- package/dist/canvas/selection/SelectionModel.js.map +1 -0
- package/dist/canvas/selection/selectionContext.d.ts +31 -0
- package/dist/canvas/selection/selectionContext.js +12 -0
- package/dist/canvas/selection/selectionContext.js.map +1 -0
- package/dist/elements/ContainerInfo.d.ts +29 -0
- package/dist/elements/ContainerInfo.js +30 -0
- package/dist/elements/ContainerInfo.js.map +1 -0
- package/dist/elements/EFAudio.d.ts +13 -3
- package/dist/elements/EFAudio.js +64 -10
- package/dist/elements/EFAudio.js.map +1 -1
- package/dist/elements/EFCaptions.d.ts +18 -16
- package/dist/elements/EFCaptions.js +110 -19
- package/dist/elements/EFCaptions.js.map +1 -1
- package/dist/elements/EFImage.d.ts +16 -6
- package/dist/elements/EFImage.js +79 -9
- package/dist/elements/EFImage.js.map +1 -1
- package/dist/elements/EFMedia/AssetIdMediaEngine.js +51 -4
- package/dist/elements/EFMedia/AssetIdMediaEngine.js.map +1 -1
- package/dist/elements/EFMedia/AssetMediaEngine.js +125 -52
- package/dist/elements/EFMedia/AssetMediaEngine.js.map +1 -1
- package/dist/elements/EFMedia/BaseMediaEngine.js +24 -6
- package/dist/elements/EFMedia/BaseMediaEngine.js.map +1 -1
- package/dist/elements/EFMedia/JitMediaEngine.js +12 -8
- package/dist/elements/EFMedia/JitMediaEngine.js.map +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +46 -7
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js.map +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +98 -73
- package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js.map +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js +28 -5
- package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js.map +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +18 -6
- package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js.map +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +8 -2
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js.map +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +31 -6
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js.map +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +28 -5
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js.map +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +97 -72
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js.map +1 -1
- package/dist/elements/EFMedia/shared/AudioSpanUtils.js +3 -1
- package/dist/elements/EFMedia/shared/AudioSpanUtils.js.map +1 -1
- package/dist/elements/EFMedia/shared/BufferUtils.js +1 -1
- package/dist/elements/EFMedia/shared/BufferUtils.js.map +1 -1
- package/dist/elements/EFMedia/shared/ThumbnailExtractor.js +25 -14
- package/dist/elements/EFMedia/shared/ThumbnailExtractor.js.map +1 -1
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js +47 -16
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js.map +1 -1
- package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js +37 -19
- package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js.map +1 -1
- package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js +65 -21
- package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js.map +1 -1
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js +8 -3
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js.map +1 -1
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.js +32 -9
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.js.map +1 -1
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js +33 -10
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js.map +1 -1
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js +23 -8
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js.map +1 -1
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.js +34 -10
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.js.map +1 -1
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js +31 -8
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js.map +1 -1
- package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js +31 -114
- package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js.map +1 -1
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +44 -8
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js.map +1 -1
- package/dist/elements/EFMedia.d.ts +18 -7
- package/dist/elements/EFMedia.js +23 -3
- package/dist/elements/EFMedia.js.map +1 -1
- package/dist/elements/EFPanZoom.d.ts +96 -0
- package/dist/elements/EFPanZoom.js +290 -0
- package/dist/elements/EFPanZoom.js.map +1 -0
- package/dist/elements/EFSourceMixin.js +7 -6
- package/dist/elements/EFSourceMixin.js.map +1 -1
- package/dist/elements/EFSurface.d.ts +6 -6
- package/dist/elements/EFSurface.js +7 -2
- package/dist/elements/EFSurface.js.map +1 -1
- package/dist/elements/EFTemporal.d.ts +2 -1
- package/dist/elements/EFTemporal.js +192 -71
- package/dist/elements/EFTemporal.js.map +1 -1
- package/dist/elements/EFText.d.ts +5 -4
- package/dist/elements/EFText.js +102 -13
- package/dist/elements/EFText.js.map +1 -1
- package/dist/elements/EFTextSegment.d.ts +32 -6
- package/dist/elements/EFTextSegment.js +53 -15
- package/dist/elements/EFTextSegment.js.map +1 -1
- package/dist/elements/EFThumbnailStrip.d.ts +118 -56
- package/dist/elements/EFThumbnailStrip.js +522 -358
- package/dist/elements/EFThumbnailStrip.js.map +1 -1
- package/dist/elements/EFTimegroup.d.ts +223 -27
- package/dist/elements/EFTimegroup.js +851 -148
- package/dist/elements/EFTimegroup.js.map +1 -1
- package/dist/elements/EFVideo.d.ts +42 -5
- package/dist/elements/EFVideo.js +165 -11
- package/dist/elements/EFVideo.js.map +1 -1
- package/dist/elements/EFWaveform.d.ts +6 -6
- package/dist/elements/EFWaveform.js +2 -1
- package/dist/elements/EFWaveform.js.map +1 -1
- package/dist/elements/ElementPositionInfo.d.ts +35 -0
- package/dist/elements/ElementPositionInfo.js +49 -0
- package/dist/elements/ElementPositionInfo.js.map +1 -0
- package/dist/elements/FetchMixin.js +16 -1
- package/dist/elements/FetchMixin.js.map +1 -1
- package/dist/elements/SessionThumbnailCache.js +152 -0
- package/dist/elements/SessionThumbnailCache.js.map +1 -0
- package/dist/elements/TargetController.js +3 -1
- package/dist/elements/TargetController.js.map +1 -1
- package/dist/elements/TimegroupController.js +9 -3
- package/dist/elements/TimegroupController.js.map +1 -1
- package/dist/elements/findRootTemporal.js +30 -0
- package/dist/elements/findRootTemporal.js.map +1 -0
- package/dist/elements/renderTemporalAudio.js +18 -5
- package/dist/elements/renderTemporalAudio.js.map +1 -1
- package/dist/elements/updateAnimations.js +492 -109
- package/dist/elements/updateAnimations.js.map +1 -1
- package/dist/getRenderInfo.d.ts +2 -2
- package/dist/gui/ContextMixin.js +4 -2
- package/dist/gui/ContextMixin.js.map +1 -1
- package/dist/gui/Controllable.js +74 -1
- package/dist/gui/Controllable.js.map +1 -1
- package/dist/gui/EFActiveRootTemporal.d.ts +50 -0
- package/dist/gui/EFActiveRootTemporal.js +94 -0
- package/dist/gui/EFActiveRootTemporal.js.map +1 -0
- package/dist/gui/EFConfiguration.d.ts +11 -5
- package/dist/gui/EFConfiguration.js.map +1 -1
- package/dist/gui/EFControls.d.ts +2 -2
- package/dist/gui/EFControls.js +109 -13
- package/dist/gui/EFControls.js.map +1 -1
- package/dist/gui/EFDial.d.ts +4 -4
- package/dist/gui/EFFilmstrip.d.ts +11 -214
- package/dist/gui/EFFilmstrip.js +53 -1152
- package/dist/gui/EFFilmstrip.js.map +1 -1
- package/dist/gui/EFFitScale.d.ts +3 -3
- package/dist/gui/EFFitScale.js +39 -12
- package/dist/gui/EFFitScale.js.map +1 -1
- package/dist/gui/EFFocusOverlay.d.ts +4 -4
- package/dist/gui/EFOverlayItem.d.ts +48 -0
- package/dist/gui/EFOverlayItem.js +97 -0
- package/dist/gui/EFOverlayItem.js.map +1 -0
- package/dist/gui/EFOverlayLayer.d.ts +70 -0
- package/dist/gui/EFOverlayLayer.js +104 -0
- package/dist/gui/EFOverlayLayer.js.map +1 -0
- package/dist/gui/EFPause.d.ts +4 -4
- package/dist/gui/EFPlay.d.ts +4 -4
- package/dist/gui/EFPreview.d.ts +4 -4
- package/dist/gui/EFResizableBox.d.ts +12 -16
- package/dist/gui/EFResizableBox.js +109 -451
- package/dist/gui/EFResizableBox.js.map +1 -1
- package/dist/gui/EFScrubber.d.ts +30 -5
- package/dist/gui/EFScrubber.js +224 -31
- package/dist/gui/EFScrubber.js.map +1 -1
- package/dist/gui/EFTimeDisplay.d.ts +4 -4
- package/dist/gui/EFTimeDisplay.js +4 -1
- package/dist/gui/EFTimeDisplay.js.map +1 -1
- package/dist/gui/EFTimelineRuler.d.ts +71 -0
- package/dist/gui/EFTimelineRuler.js +320 -0
- package/dist/gui/EFTimelineRuler.js.map +1 -0
- package/dist/gui/EFToggleLoop.d.ts +4 -4
- package/dist/gui/EFTogglePlay.d.ts +4 -4
- package/dist/gui/EFTransformHandles.d.ts +91 -0
- package/dist/gui/EFTransformHandles.js +393 -0
- package/dist/gui/EFTransformHandles.js.map +1 -0
- package/dist/gui/EFWorkbench.d.ts +182 -4
- package/dist/gui/EFWorkbench.js +2067 -22
- package/dist/gui/EFWorkbench.js.map +1 -1
- package/dist/gui/FitScaleHelpers.d.ts +31 -0
- package/dist/gui/FitScaleHelpers.js +41 -0
- package/dist/gui/FitScaleHelpers.js.map +1 -0
- package/dist/gui/PlaybackController.d.ts +2 -1
- package/dist/gui/PlaybackController.js +46 -15
- package/dist/gui/PlaybackController.js.map +1 -1
- package/dist/gui/TWMixin.js +1 -1
- package/dist/gui/TWMixin.js.map +1 -1
- package/dist/gui/hierarchy/EFHierarchy.d.ts +65 -0
- package/dist/gui/hierarchy/EFHierarchy.js +338 -0
- package/dist/gui/hierarchy/EFHierarchy.js.map +1 -0
- package/dist/gui/hierarchy/EFHierarchyItem.d.ts +118 -0
- package/dist/gui/hierarchy/EFHierarchyItem.js +551 -0
- package/dist/gui/hierarchy/EFHierarchyItem.js.map +1 -0
- package/dist/gui/hierarchy/hierarchyContext.d.ts +38 -0
- package/dist/gui/hierarchy/hierarchyContext.js +8 -0
- package/dist/gui/hierarchy/hierarchyContext.js.map +1 -0
- package/dist/gui/icons.js +34 -0
- package/dist/gui/icons.js.map +1 -0
- package/dist/gui/panZoomTransformContext.js +12 -0
- package/dist/gui/panZoomTransformContext.js.map +1 -0
- package/dist/gui/previewSettingsContext.js +12 -0
- package/dist/gui/previewSettingsContext.js.map +1 -0
- package/dist/gui/timeline/EFTimeline.d.ts +270 -0
- package/dist/gui/timeline/EFTimeline.js +1369 -0
- package/dist/gui/timeline/EFTimeline.js.map +1 -0
- package/dist/gui/timeline/EFTimelineRow.js +374 -0
- package/dist/gui/timeline/EFTimelineRow.js.map +1 -0
- package/dist/gui/timeline/TrimHandles.d.ts +36 -0
- package/dist/gui/timeline/TrimHandles.js +204 -0
- package/dist/gui/timeline/TrimHandles.js.map +1 -0
- package/dist/gui/timeline/flattenHierarchy.js +31 -0
- package/dist/gui/timeline/flattenHierarchy.js.map +1 -0
- package/dist/gui/timeline/timelineStateContext.d.ts +26 -0
- package/dist/gui/timeline/timelineStateContext.js +42 -0
- package/dist/gui/timeline/timelineStateContext.js.map +1 -0
- package/dist/gui/timeline/tracks/AudioTrack.js +264 -0
- package/dist/gui/timeline/tracks/AudioTrack.js.map +1 -0
- package/dist/gui/timeline/tracks/CaptionsTrack.js +595 -0
- package/dist/gui/timeline/tracks/CaptionsTrack.js.map +1 -0
- package/dist/gui/timeline/tracks/HTMLTrack.js +19 -0
- package/dist/gui/timeline/tracks/HTMLTrack.js.map +1 -0
- package/dist/gui/timeline/tracks/ImageTrack.js +53 -0
- package/dist/gui/timeline/tracks/ImageTrack.js.map +1 -0
- package/dist/gui/timeline/tracks/TextTrack.js +250 -0
- package/dist/gui/timeline/tracks/TextTrack.js.map +1 -0
- package/dist/gui/timeline/tracks/TimegroupTrack.js +143 -0
- package/dist/gui/timeline/tracks/TimegroupTrack.js.map +1 -0
- package/dist/gui/timeline/tracks/TrackItem.js +269 -0
- package/dist/gui/timeline/tracks/TrackItem.js.map +1 -0
- package/dist/gui/timeline/tracks/VideoTrack.js +265 -0
- package/dist/gui/timeline/tracks/VideoTrack.js.map +1 -0
- package/dist/gui/timeline/tracks/WaveformTrack.js +19 -0
- package/dist/gui/timeline/tracks/WaveformTrack.js.map +1 -0
- package/dist/gui/timeline/tracks/ensureTrackItemInit.js +1 -0
- package/dist/gui/timeline/tracks/preloadTracks.js +9 -0
- package/dist/gui/timeline/tracks/renderTrackChildren.js +119 -0
- package/dist/gui/timeline/tracks/renderTrackChildren.js.map +1 -0
- package/dist/gui/timeline/tracks/waveformUtils.js +80 -0
- package/dist/gui/timeline/tracks/waveformUtils.js.map +1 -0
- package/dist/gui/transformCalculations.js +217 -0
- package/dist/gui/transformCalculations.js.map +1 -0
- package/dist/gui/transformUtils.d.ts +37 -0
- package/dist/gui/transformUtils.js +77 -0
- package/dist/gui/transformUtils.js.map +1 -0
- package/dist/gui/tree/EFTree.d.ts +59 -0
- package/dist/gui/tree/EFTree.js +174 -0
- package/dist/gui/tree/EFTree.js.map +1 -0
- package/dist/gui/tree/EFTreeItem.d.ts +38 -0
- package/dist/gui/tree/EFTreeItem.js +146 -0
- package/dist/gui/tree/EFTreeItem.js.map +1 -0
- package/dist/gui/tree/treeContext.d.ts +60 -0
- package/dist/gui/tree/treeContext.js +23 -0
- package/dist/gui/tree/treeContext.js.map +1 -0
- package/dist/index.d.ts +32 -8
- package/dist/index.js +30 -6
- package/dist/index.js.map +1 -1
- package/dist/node_modules/react/cjs/react-jsx-runtime.development.js +688 -0
- package/dist/node_modules/react/cjs/react-jsx-runtime.development.js.map +1 -0
- package/dist/node_modules/react/cjs/react.development.js +1521 -0
- package/dist/node_modules/react/cjs/react.development.js.map +1 -0
- package/dist/node_modules/react/index.js +13 -0
- package/dist/node_modules/react/index.js.map +1 -0
- package/dist/node_modules/react/jsx-runtime.js +13 -0
- package/dist/node_modules/react/jsx-runtime.js.map +1 -0
- package/dist/preview/AdaptiveResolutionTracker.js +228 -0
- package/dist/preview/AdaptiveResolutionTracker.js.map +1 -0
- package/dist/preview/RenderProfiler.js +135 -0
- package/dist/preview/RenderProfiler.js.map +1 -0
- package/dist/preview/previewSettings.js +131 -0
- package/dist/preview/previewSettings.js.map +1 -0
- package/dist/preview/previewTypes.js +64 -0
- package/dist/preview/previewTypes.js.map +1 -0
- package/dist/preview/renderTimegroupPreview.js +656 -0
- package/dist/preview/renderTimegroupPreview.js.map +1 -0
- package/dist/preview/renderTimegroupToCanvas.d.ts +37 -0
- package/dist/preview/renderTimegroupToCanvas.js +840 -0
- package/dist/preview/renderTimegroupToCanvas.js.map +1 -0
- package/dist/preview/renderTimegroupToVideo.d.ts +39 -0
- package/dist/preview/renderTimegroupToVideo.js +274 -0
- package/dist/preview/renderTimegroupToVideo.js.map +1 -0
- package/dist/preview/renderers.js +16 -0
- package/dist/preview/renderers.js.map +1 -0
- package/dist/preview/statsTrackingStrategy.js +201 -0
- package/dist/preview/statsTrackingStrategy.js.map +1 -0
- package/dist/preview/thumbnailCacheSettings.js +52 -0
- package/dist/preview/thumbnailCacheSettings.js.map +1 -0
- package/dist/preview/workers/WorkerPool.js +178 -0
- package/dist/preview/workers/WorkerPool.js.map +1 -0
- package/dist/sandbox/PlaybackControls.js +10 -0
- package/dist/sandbox/PlaybackControls.js.map +1 -0
- package/dist/sandbox/ScenarioRunner.js +1 -0
- package/dist/sandbox/index.js +2 -0
- package/dist/style.css +66 -69
- package/dist/transcoding/types/index.d.ts +2 -1
- package/dist/transcoding/utils/UrlGenerator.d.ts +6 -1
- package/dist/transcoding/utils/UrlGenerator.js +12 -3
- package/dist/transcoding/utils/UrlGenerator.js.map +1 -1
- package/dist/utils/LRUCache.js +1 -375
- package/dist/utils/LRUCache.js.map +1 -1
- package/dist/utils/frameTime.js +14 -0
- package/dist/utils/frameTime.js.map +1 -0
- package/package.json +3 -3
- package/test/profilingPlugin.ts +223 -0
- package/test/recordReplayProxyPlugin.js +22 -27
- package/test/thumbnail-performance-test.html +116 -0
- package/test/visualRegressionUtils.ts +286 -0
- package/types.json +1 -1
- package/dist/elements/TimegroupController.d.ts +0 -18
- package/dist/msToTimeCode.js +0 -17
- package/dist/msToTimeCode.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EFResizableBox.js","names":["movementValue: number","newBounds: BoxBounds","EFResizableBox","context: ResizeContext","idealBounds: BoxBounds","result: BoxBounds"],"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\";\n\n// Constants\nconst DEFAULT_MIN_SIZE = 10;\nconst CENTER_RESIZE_MULTIPLIER = 2;\n\nexport interface BoxBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\ntype ResizeCorner = \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\";\ntype ResizeSide = \"top\" | \"right\" | \"bottom\" | \"left\";\ntype ResizeHandle = ResizeCorner | ResizeSide;\n\ninterface Dimensions {\n width: number;\n height: number;\n}\n\ninterface ResizeContext {\n readonly initialBounds: BoxBounds;\n readonly container: Dimensions;\n readonly constraints: {\n minSize: number;\n aspectRatio?: number;\n };\n readonly movement: {\n deltaX: number;\n deltaY: number;\n };\n readonly modifiers: {\n centerResize: boolean;\n preserveAspectRatio: boolean;\n };\n}\n\n// Pure calculation functions\nfunction constrainMovementDeltas(\n initialBounds: BoxBounds,\n deltaX: number,\n deltaY: number,\n container: Dimensions,\n): { deltaX: number; deltaY: number } {\n const maxLeftMovement = -initialBounds.x;\n const maxRightMovement =\n container.width - (initialBounds.x + initialBounds.width);\n const maxUpMovement = -initialBounds.y;\n const maxDownMovement =\n container.height - (initialBounds.y + initialBounds.height);\n\n return {\n deltaX: Math.max(maxLeftMovement, Math.min(maxRightMovement, deltaX)),\n deltaY: Math.max(maxUpMovement, Math.min(maxDownMovement, deltaY)),\n };\n}\n\nfunction calculateNormalResize(\n context: ResizeContext,\n handle: ResizeHandle,\n): BoxBounds {\n const { initialBounds, movement } = context;\n const { deltaX, deltaY } = movement;\n\n switch (handle) {\n case \"bottom-right\":\n return {\n ...initialBounds,\n width: initialBounds.width + deltaX,\n height: initialBounds.height + deltaY,\n };\n\n case \"top-left\": {\n const rightEdge = initialBounds.x + initialBounds.width;\n const bottomEdge = initialBounds.y + initialBounds.height;\n const newX = initialBounds.x + deltaX;\n const newY = initialBounds.y + deltaY;\n\n return {\n x: newX,\n y: newY,\n width: rightEdge - newX,\n height: bottomEdge - newY,\n };\n }\n\n case \"top-right\": {\n const bottomEdge = initialBounds.y + initialBounds.height;\n const newY = initialBounds.y + deltaY;\n\n return {\n ...initialBounds,\n y: newY,\n width: initialBounds.width + deltaX,\n height: bottomEdge - newY,\n };\n }\n\n case \"bottom-left\": {\n const rightEdge = initialBounds.x + initialBounds.width;\n const newX = initialBounds.x + deltaX;\n\n return {\n ...initialBounds,\n x: newX,\n width: rightEdge - newX,\n height: initialBounds.height + deltaY,\n };\n }\n\n case \"top\": {\n const bottomEdge = initialBounds.y + initialBounds.height;\n const newY = initialBounds.y + deltaY;\n\n return {\n ...initialBounds,\n y: newY,\n height: bottomEdge - newY,\n };\n }\n\n case \"right\":\n return {\n ...initialBounds,\n width: initialBounds.width + deltaX,\n };\n\n case \"bottom\":\n return {\n ...initialBounds,\n height: initialBounds.height + deltaY,\n };\n\n case \"left\": {\n const rightEdge = initialBounds.x + initialBounds.width;\n const newX = initialBounds.x + deltaX;\n\n return {\n ...initialBounds,\n x: newX,\n width: rightEdge - newX,\n };\n }\n\n default:\n return initialBounds;\n }\n}\n\nfunction calculateAspectRatioResize(\n context: ResizeContext,\n handle: ResizeHandle,\n): BoxBounds {\n const { initialBounds, movement, constraints } = context;\n const { deltaX, deltaY } = movement;\n if (!constraints.aspectRatio) {\n return initialBounds;\n }\n const aspectRatio = constraints.aspectRatio;\n\n const widthMovement = deltaX;\n const heightMovement = deltaY * aspectRatio;\n\n let movementValue: number;\n switch (handle) {\n case \"bottom-right\":\n case \"top-left\":\n movementValue = (widthMovement + heightMovement) / 2;\n break;\n case \"top-right\":\n case \"bottom-left\":\n movementValue = (widthMovement - heightMovement) / 2;\n break;\n default:\n movementValue = widthMovement;\n }\n\n const baseWidth =\n handle === \"top-left\" || handle === \"bottom-left\"\n ? initialBounds.width - movementValue\n : initialBounds.width + movementValue;\n\n const width = Math.max(constraints.minSize, baseWidth);\n const height = width / aspectRatio;\n\n const newBounds: BoxBounds = { ...initialBounds, width, height };\n\n // Adjust position for handles that move the origin\n switch (handle) {\n case \"top-left\":\n newBounds.x = initialBounds.x + initialBounds.width - width;\n newBounds.y = initialBounds.y + initialBounds.height - height;\n break;\n case \"top-right\":\n newBounds.y = initialBounds.y + initialBounds.height - height;\n break;\n case \"bottom-left\":\n newBounds.x = initialBounds.x + initialBounds.width - width;\n break;\n }\n\n return newBounds;\n}\n\nfunction calculateCenterResize(\n context: ResizeContext,\n handle: ResizeHandle,\n): BoxBounds {\n const { initialBounds, movement } = context;\n const { deltaX, deltaY } = movement;\n\n const centerX = initialBounds.x + initialBounds.width / 2;\n const centerY = initialBounds.y + initialBounds.height / 2;\n\n let widthChange = 0;\n let heightChange = 0;\n\n switch (handle) {\n case \"bottom-right\":\n widthChange = deltaX * CENTER_RESIZE_MULTIPLIER;\n heightChange = deltaY * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"top-left\":\n widthChange = -deltaX * CENTER_RESIZE_MULTIPLIER;\n heightChange = -deltaY * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"top-right\":\n widthChange = deltaX * CENTER_RESIZE_MULTIPLIER;\n heightChange = -deltaY * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"bottom-left\":\n widthChange = -deltaX * CENTER_RESIZE_MULTIPLIER;\n heightChange = deltaY * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"top\":\n case \"bottom\":\n heightChange =\n (handle === \"bottom\" ? deltaY : -deltaY) * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"left\":\n case \"right\":\n widthChange =\n (handle === \"right\" ? deltaX : -deltaX) * CENTER_RESIZE_MULTIPLIER;\n break;\n }\n\n const newWidth = initialBounds.width + widthChange;\n const newHeight = initialBounds.height + heightChange;\n\n return {\n x: centerX - newWidth / 2,\n y: centerY - newHeight / 2,\n width: newWidth,\n height: newHeight,\n };\n}\n\nfunction calculateCenterResizeWithAspectRatio(\n context: ResizeContext,\n handle: ResizeHandle,\n): BoxBounds {\n const { initialBounds, movement, constraints } = context;\n const { deltaX, deltaY } = movement;\n if (!constraints.aspectRatio) {\n return initialBounds;\n }\n const aspectRatio = constraints.aspectRatio;\n\n const centerX = initialBounds.x + initialBounds.width / 2;\n const centerY = initialBounds.y + initialBounds.height / 2;\n\n let movementValue: number;\n switch (handle) {\n case \"bottom-right\":\n movementValue = Math.max(deltaX, deltaY);\n break;\n case \"top-left\":\n movementValue = -Math.max(-deltaX, -deltaY);\n break;\n case \"top-right\":\n movementValue = Math.max(deltaX, -deltaY);\n break;\n case \"bottom-left\":\n movementValue = Math.max(-deltaX, deltaY);\n break;\n case \"top\":\n case \"bottom\":\n movementValue = handle === \"bottom\" ? deltaY : -deltaY;\n break;\n case \"left\":\n case \"right\":\n movementValue = handle === \"right\" ? deltaX : -deltaX;\n break;\n default:\n movementValue = Math.max(deltaX, deltaY);\n }\n\n const newWidth = Math.max(\n constraints.minSize,\n initialBounds.width + movementValue * CENTER_RESIZE_MULTIPLIER,\n );\n const newHeight = newWidth / aspectRatio;\n\n return {\n x: centerX - newWidth / 2,\n y: centerY - newHeight / 2,\n width: newWidth,\n height: newHeight,\n };\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 dragMode: \"move\" | \"resize\" | null = null;\n\n private interaction: {\n startPoint: { x: number; y: number };\n target: { mode: \"move\" | \"resize\"; handle?: ResizeHandle };\n initialBounds: BoxBounds;\n pointerId: number;\n } | null = null;\n\n private modifiers = { shift: false, alt: false };\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 .top-left { top: -4px; left: -4px; width: 8px; height: 8px; cursor: nwse-resize; }\n .top-right { top: -4px; right: -4px; width: 8px; height: 8px; cursor: nesw-resize; }\n .bottom-left { bottom: -4px; left: -4px; width: 8px; height: 8px; cursor: nesw-resize; }\n .bottom-right { bottom: -4px; right: -4px; width: 8px; height: 8px; cursor: nwse-resize; }\n .top { top: -4px; left: 4px; right: 4px; height: 8px; cursor: ns-resize; }\n .right { top: 4px; bottom: 4px; right: -4px; width: 8px; cursor: ew-resize; }\n .bottom { bottom: -4px; left: 4px; right: 4px; height: 8px; cursor: ns-resize; }\n .left { 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 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.dragMode = mode;\n\n this.interaction = {\n startPoint: { x: e.clientX, y: e.clientY },\n target: { mode, handle },\n initialBounds: { ...this.bounds },\n pointerId: e.pointerId,\n };\n this.modifiers = { shift: e.shiftKey, alt: e.altKey };\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 (\n !this.isDragging ||\n !this.interaction ||\n e.pointerId !== this.interaction.pointerId\n )\n return;\n\n e.preventDefault();\n\n const deltaX = e.clientX - this.interaction.startPoint.x;\n const deltaY = e.clientY - this.interaction.startPoint.y;\n\n this.modifiers = { shift: e.shiftKey, alt: e.altKey };\n\n if (this.dragMode === \"move\") {\n const constrainedMovement = constrainMovementDeltas(\n this.interaction.initialBounds,\n deltaX,\n deltaY,\n { width: this.containerWidth, height: this.containerHeight },\n );\n this.bounds = {\n ...this.interaction.initialBounds,\n x: this.interaction.initialBounds.x + constrainedMovement.deltaX,\n y: this.interaction.initialBounds.y + constrainedMovement.deltaY,\n };\n } else if (this.dragMode === \"resize\" && this.interaction.target.handle) {\n const context: ResizeContext = {\n initialBounds: this.interaction.initialBounds,\n container: { width: this.containerWidth, height: this.containerHeight },\n constraints: {\n minSize: this.minSize,\n aspectRatio: this.modifiers.shift\n ? this.interaction.initialBounds.width /\n this.interaction.initialBounds.height\n : undefined,\n },\n movement: { deltaX, deltaY },\n modifiers: {\n centerResize: this.modifiers.alt,\n preserveAspectRatio: this.modifiers.shift,\n },\n };\n this.bounds = this.calculateBoundsWithModeAwareConstraints(\n context,\n this.interaction.target.handle,\n );\n }\n\n this.dispatchBoundsChange();\n };\n\n private handlePointerUp = (e: PointerEvent) => {\n if (this.interaction && e.pointerId !== this.interaction.pointerId) {\n return;\n }\n e.preventDefault();\n this.isDragging = false;\n this.dragMode = null;\n this.interaction = null;\n document.removeEventListener(\"pointermove\", this.handlePointerMove);\n document.removeEventListener(\"pointerup\", this.handlePointerUp);\n };\n\n private calculateBoundsWithModeAwareConstraints(\n context: ResizeContext,\n handle: ResizeHandle,\n ): BoxBounds {\n const { modifiers, constraints, container, initialBounds } = context;\n\n // For normal resize, use the simple delta constraint approach\n if (!modifiers.centerResize && !modifiers.preserveAspectRatio) {\n const constrainedMovement = this.constrainResizeDeltas(\n initialBounds,\n context.movement.deltaX,\n context.movement.deltaY,\n handle,\n container,\n constraints.minSize,\n );\n\n return calculateNormalResize(\n {\n ...context,\n movement: constrainedMovement,\n },\n handle,\n );\n }\n\n // For modifier-based resizes, calculate ideal bounds then constrain smartly\n let idealBounds: BoxBounds;\n\n if (modifiers.centerResize && modifiers.preserveAspectRatio) {\n idealBounds = calculateCenterResizeWithAspectRatio(context, handle);\n } else if (modifiers.centerResize) {\n idealBounds = calculateCenterResize(context, handle);\n } else {\n idealBounds = calculateAspectRatioResize(context, handle);\n }\n\n // Smart constraint that preserves the resize mode's behavior\n return this.constrainBoundsForMode(idealBounds, context, handle);\n }\n\n private constrainBoundsForMode(\n idealBounds: BoxBounds,\n context: ResizeContext,\n handle: ResizeHandle,\n ): BoxBounds {\n const { container, constraints, modifiers } = context;\n\n // Check if bounds are already valid\n if (this.isValidBounds(idealBounds, container, constraints.minSize)) {\n return idealBounds;\n }\n\n // For combined center + aspect ratio, need special handling\n if (\n modifiers.centerResize &&\n modifiers.preserveAspectRatio &&\n constraints.aspectRatio\n ) {\n return this.constrainCenterResizeWithAspectRatio(idealBounds, context);\n }\n\n // For aspect ratio modes, we need to scale the bounds proportionally\n if (modifiers.preserveAspectRatio && constraints.aspectRatio) {\n return this.constrainWithAspectRatio(idealBounds, context, handle);\n }\n\n // For center resize, we need to adjust from the center\n if (modifiers.centerResize) {\n return this.constrainCenterResize(idealBounds, context);\n }\n\n // Fallback to simple constraint\n return this.simpleConstrainBounds(\n idealBounds,\n container,\n constraints.minSize,\n );\n }\n\n private isValidBounds(\n bounds: BoxBounds,\n container: Dimensions,\n minSize: number,\n ): boolean {\n return (\n bounds.x >= 0 &&\n bounds.y >= 0 &&\n bounds.width >= minSize &&\n bounds.height >= minSize &&\n bounds.x + bounds.width <= container.width &&\n bounds.y + bounds.height <= container.height\n );\n }\n\n private constrainWithAspectRatio(\n idealBounds: BoxBounds,\n context: ResizeContext,\n handle: ResizeHandle,\n ): BoxBounds {\n const { container, constraints, initialBounds } = context;\n if (!constraints.aspectRatio) {\n return initialBounds;\n }\n const aspectRatio = constraints.aspectRatio;\n\n // Calculate maximum allowed dimensions\n const maxWidth = container.width - Math.max(0, idealBounds.x);\n const maxHeight = container.height - Math.max(0, idealBounds.y);\n\n // Find the largest size that fits both constraints\n let constrainedWidth = Math.max(\n constraints.minSize,\n Math.min(maxWidth, idealBounds.width),\n );\n let constrainedHeight = constrainedWidth / aspectRatio;\n\n // If height is too big, constrain by height instead\n if (constrainedHeight > maxHeight) {\n constrainedHeight = Math.max(constraints.minSize, maxHeight);\n constrainedWidth = constrainedHeight * aspectRatio;\n }\n\n // Ensure we don't go smaller than minimum\n if (constrainedWidth < constraints.minSize) {\n constrainedWidth = constraints.minSize;\n constrainedHeight = constrainedWidth / aspectRatio;\n }\n\n const result: BoxBounds = {\n ...idealBounds,\n width: constrainedWidth,\n height: constrainedHeight,\n };\n\n // Adjust position for handles that move the origin\n switch (handle) {\n case \"top-left\":\n result.x = initialBounds.x + initialBounds.width - constrainedWidth;\n result.y = initialBounds.y + initialBounds.height - constrainedHeight;\n break;\n case \"top-right\":\n result.y = initialBounds.y + initialBounds.height - constrainedHeight;\n break;\n case \"bottom-left\":\n result.x = initialBounds.x + initialBounds.width - constrainedWidth;\n break;\n }\n\n // Ensure position is within bounds\n result.x = Math.max(0, Math.min(container.width - result.width, result.x));\n result.y = Math.max(\n 0,\n Math.min(container.height - result.height, result.y),\n );\n\n return result;\n }\n\n private constrainCenterResize(\n idealBounds: BoxBounds,\n context: ResizeContext,\n ): BoxBounds {\n const { container, constraints, initialBounds } = context;\n\n const centerX = initialBounds.x + initialBounds.width / 2;\n const centerY = initialBounds.y + initialBounds.height / 2;\n\n // Calculate maximum dimensions from center\n const maxWidthFromCenter = Math.min(\n centerX * 2,\n (container.width - centerX) * 2,\n );\n const maxHeightFromCenter = Math.min(\n centerY * 2,\n (container.height - centerY) * 2,\n );\n\n const constrainedWidth = Math.max(\n constraints.minSize,\n Math.min(maxWidthFromCenter, idealBounds.width),\n );\n const constrainedHeight = Math.max(\n constraints.minSize,\n Math.min(maxHeightFromCenter, idealBounds.height),\n );\n\n return {\n x: centerX - constrainedWidth / 2,\n y: centerY - constrainedHeight / 2,\n width: constrainedWidth,\n height: constrainedHeight,\n };\n }\n\n private constrainCenterResizeWithAspectRatio(\n idealBounds: BoxBounds,\n context: ResizeContext,\n ): BoxBounds {\n const { container, constraints, initialBounds } = context;\n if (!constraints.aspectRatio) {\n return initialBounds;\n }\n const aspectRatio = constraints.aspectRatio;\n\n const centerX = initialBounds.x + initialBounds.width / 2;\n const centerY = initialBounds.y + initialBounds.height / 2;\n\n // Calculate maximum dimensions from center while maintaining aspect ratio\n const maxWidthFromCenter = Math.min(\n centerX * 2,\n (container.width - centerX) * 2,\n );\n const maxHeightFromCenter = Math.min(\n centerY * 2,\n (container.height - centerY) * 2,\n );\n\n // Start with the ideal width, then constrain\n let constrainedWidth = Math.max(\n constraints.minSize,\n Math.min(maxWidthFromCenter, idealBounds.width),\n );\n let constrainedHeight = constrainedWidth / aspectRatio;\n\n // If height doesn't fit, constrain by height instead\n if (constrainedHeight > maxHeightFromCenter) {\n constrainedHeight = Math.max(constraints.minSize, maxHeightFromCenter);\n constrainedWidth = constrainedHeight * aspectRatio;\n }\n\n // Ensure minimum size\n if (constrainedWidth < constraints.minSize) {\n constrainedWidth = constraints.minSize;\n constrainedHeight = constrainedWidth / aspectRatio;\n }\n\n if (constrainedHeight < constraints.minSize) {\n constrainedHeight = constraints.minSize;\n constrainedWidth = constrainedHeight * aspectRatio;\n }\n\n return {\n x: centerX - constrainedWidth / 2,\n y: centerY - constrainedHeight / 2,\n width: constrainedWidth,\n height: constrainedHeight,\n };\n }\n\n private simpleConstrainBounds(\n bounds: BoxBounds,\n container: Dimensions,\n minSize: number,\n ): BoxBounds {\n return {\n x: Math.max(0, Math.min(container.width - bounds.width, bounds.x)),\n y: Math.max(0, Math.min(container.height - bounds.height, bounds.y)),\n width: Math.max(\n minSize,\n Math.min(container.width - bounds.x, bounds.width),\n ),\n height: Math.max(\n minSize,\n Math.min(container.height - bounds.y, bounds.height),\n ),\n };\n }\n\n private constrainResizeDeltas(\n initialBounds: BoxBounds,\n deltaX: number,\n deltaY: number,\n handle: ResizeHandle,\n container: Dimensions,\n minSize: number,\n ): { deltaX: number; deltaY: number } {\n let constrainedDeltaX = deltaX;\n let constrainedDeltaY = deltaY;\n\n switch (handle) {\n case \"bottom-right\":\n // Can't make smaller than minSize, can't go beyond container\n constrainedDeltaX = Math.max(\n minSize - initialBounds.width,\n Math.min(\n container.width - initialBounds.x - initialBounds.width,\n deltaX,\n ),\n );\n constrainedDeltaY = Math.max(\n minSize - initialBounds.height,\n Math.min(\n container.height - initialBounds.y - initialBounds.height,\n deltaY,\n ),\n );\n break;\n\n case \"top-left\":\n // Can't make smaller than minSize, can't go beyond 0\n constrainedDeltaX = Math.max(\n -initialBounds.x,\n Math.min(initialBounds.width - minSize, deltaX),\n );\n constrainedDeltaY = Math.max(\n -initialBounds.y,\n Math.min(initialBounds.height - minSize, deltaY),\n );\n break;\n\n case \"top-right\":\n constrainedDeltaX = Math.max(\n minSize - initialBounds.width,\n Math.min(\n container.width - initialBounds.x - initialBounds.width,\n deltaX,\n ),\n );\n constrainedDeltaY = Math.max(\n -initialBounds.y,\n Math.min(initialBounds.height - minSize, deltaY),\n );\n break;\n\n case \"bottom-left\":\n constrainedDeltaX = Math.max(\n -initialBounds.x,\n Math.min(initialBounds.width - minSize, deltaX),\n );\n constrainedDeltaY = Math.max(\n minSize - initialBounds.height,\n Math.min(\n container.height - initialBounds.y - initialBounds.height,\n deltaY,\n ),\n );\n break;\n\n case \"right\":\n constrainedDeltaX = Math.max(\n minSize - initialBounds.width,\n Math.min(\n container.width - initialBounds.x - initialBounds.width,\n deltaX,\n ),\n );\n break;\n\n case \"left\":\n constrainedDeltaX = Math.max(\n -initialBounds.x,\n Math.min(initialBounds.width - minSize, deltaX),\n );\n break;\n\n case \"bottom\":\n constrainedDeltaY = Math.max(\n minSize - initialBounds.height,\n Math.min(\n container.height - initialBounds.y - initialBounds.height,\n deltaY,\n ),\n );\n break;\n\n case \"top\":\n constrainedDeltaY = Math.max(\n -initialBounds.y,\n Math.min(initialBounds.height - minSize, deltaY),\n );\n break;\n }\n\n return { deltaX: constrainedDeltaX, deltaY: constrainedDeltaY };\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 return html`\n <div\n class=\"box ${this.isDragging ? \"dragging\" : \"\"}\"\n style=${styleMap(boxStyles)}\n @pointerdown=${(e: PointerEvent) => this.handlePointerDown(e, \"move\")}\n >\n ${this.renderHandles()}\n <slot></slot>\n </div>\n `;\n }\n\n private renderHandles() {\n const handles: ResizeHandle[] = [\n \"top-left\",\n \"top-right\",\n \"bottom-left\",\n \"bottom-right\",\n \"top\",\n \"right\",\n \"bottom\",\n \"left\",\n ];\n return handles.map(\n (handle) => html`\n <div\n class=\"handle ${handle}\"\n @pointerdown=${(e: PointerEvent) => this.handlePointerDown(e, \"resize\", handle)}\n ></div>\n `,\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\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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"}
|
package/dist/gui/EFScrubber.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ControllableInterface } from "./Controllable.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as lit22 from "lit";
|
|
3
3
|
import { LitElement } from "lit";
|
|
4
|
-
import * as
|
|
4
|
+
import * as lit_html22 from "lit-html";
|
|
5
5
|
|
|
6
6
|
//#region src/gui/EFScrubber.d.ts
|
|
7
7
|
declare const EFScrubber_base: (new (...args: any[]) => {
|
|
@@ -10,14 +10,39 @@ 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:
|
|
13
|
+
static styles: lit22.CSSResult[];
|
|
14
14
|
playing: boolean;
|
|
15
|
+
contextCurrentTimeMs: number;
|
|
16
|
+
contextDurationMs: number;
|
|
17
|
+
orientation: "horizontal" | "vertical";
|
|
15
18
|
currentTimeMs: number;
|
|
16
19
|
durationMs: number;
|
|
20
|
+
zoomScale: number;
|
|
21
|
+
containerWidth: number;
|
|
22
|
+
fps?: number;
|
|
23
|
+
rawScrubTimeMs?: number | null;
|
|
24
|
+
scrollContainerRef?: {
|
|
25
|
+
current: HTMLElement | null;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Reference to the element that represents the actual track content area.
|
|
29
|
+
* Used to calculate the offset between the scroll container and where tracks begin.
|
|
30
|
+
*/
|
|
31
|
+
trackContentRef?: {
|
|
32
|
+
current: HTMLElement | null;
|
|
33
|
+
};
|
|
34
|
+
onSeek?: (time: number) => void;
|
|
35
|
+
isScrubbingRef?: {
|
|
36
|
+
current: boolean;
|
|
37
|
+
};
|
|
17
38
|
get context(): ControllableInterface | null;
|
|
39
|
+
get effectiveCurrentTimeMs(): number;
|
|
40
|
+
get effectiveDurationMs(): number;
|
|
41
|
+
get isTimelineMode(): boolean;
|
|
18
42
|
private scrubProgress;
|
|
19
43
|
private isMoving;
|
|
20
|
-
private scrubberRef
|
|
44
|
+
private scrubberRef;
|
|
45
|
+
private _scrubberElement?;
|
|
21
46
|
private capturedPointerId;
|
|
22
47
|
private updateProgress;
|
|
23
48
|
private handlePointerDown;
|
|
@@ -25,7 +50,7 @@ declare class EFScrubber extends EFScrubber_base {
|
|
|
25
50
|
private boundHandlePointerUp;
|
|
26
51
|
private boundHandlePointerCancel;
|
|
27
52
|
private boundHandleContextMenu;
|
|
28
|
-
render():
|
|
53
|
+
render(): lit_html22.TemplateResult<1>;
|
|
29
54
|
connectedCallback(): void;
|
|
30
55
|
disconnectedCallback(): void;
|
|
31
56
|
}
|
package/dist/gui/EFScrubber.js
CHANGED
|
@@ -3,21 +3,38 @@ import { durationContext } from "./durationContext.js";
|
|
|
3
3
|
import { playingContext } from "./playingContext.js";
|
|
4
4
|
import { __decorate } from "../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js";
|
|
5
5
|
import { efContext } from "./efContext.js";
|
|
6
|
+
import { quantizeToFrameTimeMs } from "./EFTimelineRuler.js";
|
|
6
7
|
import { TargetOrContextMixin } from "./TargetOrContextMixin.js";
|
|
7
8
|
import { consume } from "@lit/context";
|
|
8
9
|
import { LitElement, css, html } from "lit";
|
|
9
|
-
import { customElement, eventOptions, state } from "lit/decorators.js";
|
|
10
|
-
import { ref } from "lit/directives/ref.js";
|
|
10
|
+
import { customElement, eventOptions, property, state } from "lit/decorators.js";
|
|
11
|
+
import { createRef, ref } from "lit/directives/ref.js";
|
|
11
12
|
|
|
12
13
|
//#region src/gui/EFScrubber.ts
|
|
14
|
+
const BASE_PIXELS_PER_SECOND = 100;
|
|
15
|
+
function timeToPixels(timeMs, durationMs, containerWidth, zoomScale) {
|
|
16
|
+
if (durationMs <= 0) return 0;
|
|
17
|
+
const pixelsPerSecond = BASE_PIXELS_PER_SECOND * zoomScale;
|
|
18
|
+
return timeMs / 1e3 * pixelsPerSecond;
|
|
19
|
+
}
|
|
20
|
+
function pixelsToTime(pixels, durationMs, containerWidth, zoomScale) {
|
|
21
|
+
if (durationMs <= 0) return 0;
|
|
22
|
+
return pixels / (BASE_PIXELS_PER_SECOND * zoomScale) * 1e3;
|
|
23
|
+
}
|
|
13
24
|
let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efContext) {
|
|
14
25
|
constructor(..._args) {
|
|
15
26
|
super(..._args);
|
|
16
27
|
this.playing = false;
|
|
28
|
+
this.contextCurrentTimeMs = NaN;
|
|
29
|
+
this.contextDurationMs = 0;
|
|
30
|
+
this.orientation = "horizontal";
|
|
17
31
|
this.currentTimeMs = NaN;
|
|
18
32
|
this.durationMs = 0;
|
|
33
|
+
this.zoomScale = 1;
|
|
34
|
+
this.containerWidth = 0;
|
|
19
35
|
this.scrubProgress = 0;
|
|
20
36
|
this.isMoving = false;
|
|
37
|
+
this.scrubberRef = createRef();
|
|
21
38
|
this.capturedPointerId = null;
|
|
22
39
|
this.boundHandlePointerMove = (e) => {
|
|
23
40
|
if (this.isMoving && e.pointerId === this.capturedPointerId) {
|
|
@@ -27,23 +44,27 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
|
|
|
27
44
|
}
|
|
28
45
|
};
|
|
29
46
|
this.boundHandlePointerUp = (e) => {
|
|
30
|
-
|
|
47
|
+
const scrubberEl = this.scrubberRef.value || this._scrubberElement;
|
|
48
|
+
if (e.pointerId === this.capturedPointerId && scrubberEl) {
|
|
31
49
|
e.preventDefault();
|
|
32
50
|
e.stopPropagation();
|
|
33
51
|
try {
|
|
34
|
-
|
|
52
|
+
scrubberEl.releasePointerCapture(e.pointerId);
|
|
35
53
|
} catch (_err) {}
|
|
36
54
|
this.capturedPointerId = null;
|
|
37
55
|
this.isMoving = false;
|
|
56
|
+
if (this.isScrubbingRef) this.isScrubbingRef.current = false;
|
|
38
57
|
}
|
|
39
58
|
};
|
|
40
59
|
this.boundHandlePointerCancel = (e) => {
|
|
41
|
-
|
|
60
|
+
const scrubberEl = this.scrubberRef.value || this._scrubberElement;
|
|
61
|
+
if (e.pointerId === this.capturedPointerId && scrubberEl) {
|
|
42
62
|
try {
|
|
43
|
-
|
|
63
|
+
scrubberEl.releasePointerCapture(e.pointerId);
|
|
44
64
|
} catch (_err) {}
|
|
45
65
|
this.capturedPointerId = null;
|
|
46
66
|
this.isMoving = false;
|
|
67
|
+
if (this.isScrubbingRef) this.isScrubbingRef.current = false;
|
|
47
68
|
}
|
|
48
69
|
};
|
|
49
70
|
this.boundHandleContextMenu = (e) => {
|
|
@@ -71,6 +92,14 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
|
|
|
71
92
|
--ef-scrubber-progress-color: rgb(96 165 250);
|
|
72
93
|
}
|
|
73
94
|
|
|
95
|
+
:host([orientation="vertical"]) {
|
|
96
|
+
width: 100%;
|
|
97
|
+
height: 100%;
|
|
98
|
+
position: absolute;
|
|
99
|
+
inset: 0;
|
|
100
|
+
pointer-events: auto;
|
|
101
|
+
}
|
|
102
|
+
|
|
74
103
|
.scrubber {
|
|
75
104
|
width: 100%;
|
|
76
105
|
height: var(--ef-scrubber-height);
|
|
@@ -82,6 +111,13 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
|
|
|
82
111
|
user-select: none;
|
|
83
112
|
}
|
|
84
113
|
|
|
114
|
+
:host([orientation="vertical"]) .scrubber {
|
|
115
|
+
width: 100%;
|
|
116
|
+
height: 100%;
|
|
117
|
+
background: transparent;
|
|
118
|
+
cursor: ew-resize;
|
|
119
|
+
}
|
|
120
|
+
|
|
85
121
|
.progress {
|
|
86
122
|
position: absolute;
|
|
87
123
|
height: 100%;
|
|
@@ -89,6 +125,10 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
|
|
|
89
125
|
border-radius: 2px;
|
|
90
126
|
}
|
|
91
127
|
|
|
128
|
+
:host([orientation="vertical"]) .progress {
|
|
129
|
+
display: none;
|
|
130
|
+
}
|
|
131
|
+
|
|
92
132
|
.handle {
|
|
93
133
|
position: absolute;
|
|
94
134
|
width: var(--ef-scrubber-handle-size);
|
|
@@ -100,6 +140,46 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
|
|
|
100
140
|
cursor: grab;
|
|
101
141
|
}
|
|
102
142
|
|
|
143
|
+
:host([orientation="vertical"]) .handle {
|
|
144
|
+
display: none;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.playhead {
|
|
148
|
+
position: absolute;
|
|
149
|
+
top: 0;
|
|
150
|
+
bottom: 0;
|
|
151
|
+
width: 2px;
|
|
152
|
+
background: var(--ef-scrubber-progress-color);
|
|
153
|
+
pointer-events: auto;
|
|
154
|
+
cursor: ew-resize;
|
|
155
|
+
z-index: 30;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
::part(playhead) {
|
|
159
|
+
z-index: 30;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.playhead-handle {
|
|
163
|
+
position: absolute;
|
|
164
|
+
top: 0;
|
|
165
|
+
left: 50%;
|
|
166
|
+
transform: translate(-50%, -50%);
|
|
167
|
+
width: 12px;
|
|
168
|
+
height: 12px;
|
|
169
|
+
background: var(--ef-scrubber-progress-color);
|
|
170
|
+
border-radius: 50%;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.raw-preview {
|
|
174
|
+
position: absolute;
|
|
175
|
+
top: 0;
|
|
176
|
+
bottom: 0;
|
|
177
|
+
width: 2px;
|
|
178
|
+
background: rgba(37, 99, 235, 0.2);
|
|
179
|
+
pointer-events: none;
|
|
180
|
+
z-index: 20;
|
|
181
|
+
}
|
|
182
|
+
|
|
103
183
|
/* Add CSS Shadow Parts */
|
|
104
184
|
::part(scrubber) { }
|
|
105
185
|
::part(progress) { }
|
|
@@ -109,44 +189,125 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
|
|
|
109
189
|
get context() {
|
|
110
190
|
return this.effectiveContext;
|
|
111
191
|
}
|
|
192
|
+
get effectiveCurrentTimeMs() {
|
|
193
|
+
if (!Number.isNaN(this.currentTimeMs)) return this.currentTimeMs;
|
|
194
|
+
if (!Number.isNaN(this.contextCurrentTimeMs)) return this.contextCurrentTimeMs;
|
|
195
|
+
return 0;
|
|
196
|
+
}
|
|
197
|
+
get effectiveDurationMs() {
|
|
198
|
+
return this.durationMs || this.contextDurationMs || 0;
|
|
199
|
+
}
|
|
200
|
+
get isTimelineMode() {
|
|
201
|
+
return this.orientation === "vertical" && this.zoomScale > 0;
|
|
202
|
+
}
|
|
112
203
|
updateProgress(e) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
this.
|
|
118
|
-
|
|
204
|
+
const scrubberEl = this.scrubberRef.value || this._scrubberElement;
|
|
205
|
+
if (!scrubberEl) return;
|
|
206
|
+
const duration = this.effectiveDurationMs;
|
|
207
|
+
if (duration <= 0) return;
|
|
208
|
+
if (this.isTimelineMode) {
|
|
209
|
+
const scrollContainer = this.scrollContainerRef?.current || scrubberEl.parentElement;
|
|
210
|
+
if (!scrollContainer) return;
|
|
211
|
+
const scrollContainerRect = scrollContainer.getBoundingClientRect();
|
|
212
|
+
const scrollLeft = scrollContainer.scrollLeft || 0;
|
|
213
|
+
let pixelOffset = 0;
|
|
214
|
+
if (this.trackContentRef?.current) pixelOffset = this.trackContentRef.current.getBoundingClientRect().left - scrollContainerRect.left + scrollContainer.scrollLeft;
|
|
215
|
+
const pixelPosition = scrollLeft + (e.clientX - scrollContainerRect.left - pixelOffset);
|
|
216
|
+
const effectiveWidth = this.containerWidth > 0 ? this.containerWidth : scrollContainerRect.width;
|
|
217
|
+
if (effectiveWidth <= 0) return;
|
|
218
|
+
let rawTime = pixelsToTime(pixelPosition, duration, effectiveWidth, this.zoomScale);
|
|
219
|
+
rawTime = Math.max(0, Math.min(rawTime, duration));
|
|
220
|
+
let quantizedTime = this.fps && this.fps > 0 ? quantizeToFrameTimeMs(rawTime, this.fps) : rawTime;
|
|
221
|
+
quantizedTime = Math.max(0, Math.min(quantizedTime, duration));
|
|
222
|
+
this.scrubProgress = quantizedTime / duration;
|
|
223
|
+
if (this.onSeek) this.onSeek(quantizedTime);
|
|
224
|
+
else {
|
|
225
|
+
this.dispatchEvent(new CustomEvent("seek", {
|
|
226
|
+
detail: quantizedTime,
|
|
227
|
+
bubbles: true,
|
|
228
|
+
composed: true
|
|
229
|
+
}));
|
|
230
|
+
if (this.context) this.context.currentTimeMs = quantizedTime;
|
|
231
|
+
}
|
|
232
|
+
} else {
|
|
233
|
+
const rect = scrubberEl.getBoundingClientRect();
|
|
234
|
+
const x = e.clientX - rect.left;
|
|
235
|
+
const progress = Math.max(0, Math.min(1, x / rect.width));
|
|
236
|
+
this.scrubProgress = progress;
|
|
237
|
+
const timeMs = progress * duration;
|
|
238
|
+
if (this.onSeek) this.onSeek(timeMs);
|
|
239
|
+
else {
|
|
240
|
+
this.dispatchEvent(new CustomEvent("seek", {
|
|
241
|
+
detail: timeMs,
|
|
242
|
+
bubbles: true,
|
|
243
|
+
composed: true
|
|
244
|
+
}));
|
|
245
|
+
if (this.context) this.context.currentTimeMs = timeMs;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
119
248
|
}
|
|
120
249
|
handlePointerDown(e) {
|
|
121
|
-
|
|
250
|
+
const scrubberEl = this.scrubberRef.value || this._scrubberElement;
|
|
251
|
+
if (!scrubberEl) return;
|
|
122
252
|
this.isMoving = true;
|
|
253
|
+
if (this.isScrubbingRef) this.isScrubbingRef.current = true;
|
|
123
254
|
e.preventDefault();
|
|
124
255
|
e.stopPropagation();
|
|
125
256
|
this.capturedPointerId = e.pointerId;
|
|
126
257
|
try {
|
|
127
|
-
|
|
258
|
+
scrubberEl.setPointerCapture(e.pointerId);
|
|
128
259
|
} catch (err) {
|
|
129
260
|
console.warn("Failed to set pointer capture:", err);
|
|
130
261
|
}
|
|
131
262
|
this.updateProgress(e);
|
|
132
263
|
}
|
|
133
264
|
render() {
|
|
134
|
-
const
|
|
135
|
-
const
|
|
136
|
-
return html
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
this.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
<div
|
|
148
|
-
|
|
149
|
-
|
|
265
|
+
const duration = this.effectiveDurationMs;
|
|
266
|
+
const currentTime = this.effectiveCurrentTimeMs;
|
|
267
|
+
if (duration <= 0) return html``;
|
|
268
|
+
if (this.isTimelineMode) {
|
|
269
|
+
const scrubberEl = this.scrubberRef.value || this._scrubberElement;
|
|
270
|
+
const effectiveWidth = this.containerWidth > 0 ? this.containerWidth : scrubberEl?.parentElement?.getBoundingClientRect().width || 0;
|
|
271
|
+
const positionPixels = effectiveWidth > 0 ? timeToPixels(currentTime, duration, effectiveWidth, this.zoomScale) : 0;
|
|
272
|
+
const rawScrubPositionPixels = this.rawScrubTimeMs !== null && this.rawScrubTimeMs !== void 0 && effectiveWidth > 0 ? timeToPixels(this.rawScrubTimeMs, duration, effectiveWidth, this.zoomScale) : null;
|
|
273
|
+
return html`
|
|
274
|
+
${rawScrubPositionPixels !== null && rawScrubPositionPixels !== positionPixels ? html`<div
|
|
275
|
+
class="raw-preview"
|
|
276
|
+
style="left: ${rawScrubPositionPixels}px"
|
|
277
|
+
></div>` : html``}
|
|
278
|
+
<div
|
|
279
|
+
${ref(this.scrubberRef)}
|
|
280
|
+
part="scrubber"
|
|
281
|
+
class="scrubber"
|
|
282
|
+
@pointerdown=${this.handlePointerDown}
|
|
283
|
+
@contextmenu=${this.boundHandleContextMenu}
|
|
284
|
+
>
|
|
285
|
+
<div
|
|
286
|
+
part="playhead"
|
|
287
|
+
class="playhead"
|
|
288
|
+
style="left: ${positionPixels}px"
|
|
289
|
+
@pointerdown=${this.handlePointerDown}
|
|
290
|
+
>
|
|
291
|
+
<div class="playhead-handle"></div>
|
|
292
|
+
</div>
|
|
293
|
+
</div>
|
|
294
|
+
`;
|
|
295
|
+
} else {
|
|
296
|
+
const currentProgress = duration > 0 ? currentTime / duration : 0;
|
|
297
|
+
const displayProgress = this.isMoving ? this.scrubProgress : currentProgress;
|
|
298
|
+
return html`
|
|
299
|
+
<div
|
|
300
|
+
${ref(this.scrubberRef)}
|
|
301
|
+
part="scrubber"
|
|
302
|
+
class="scrubber"
|
|
303
|
+
@pointerdown=${this.handlePointerDown}
|
|
304
|
+
@contextmenu=${this.boundHandleContextMenu}
|
|
305
|
+
>
|
|
306
|
+
<div class="progress" style="width: ${displayProgress * 100}%"></div>
|
|
307
|
+
<div class="handle" style="left: ${displayProgress * 100}%"></div>
|
|
308
|
+
</div>
|
|
309
|
+
`;
|
|
310
|
+
}
|
|
150
311
|
}
|
|
151
312
|
connectedCallback() {
|
|
152
313
|
super.connectedCallback();
|
|
@@ -170,11 +331,43 @@ __decorate([consume({
|
|
|
170
331
|
__decorate([consume({
|
|
171
332
|
context: currentTimeContext,
|
|
172
333
|
subscribe: true
|
|
173
|
-
})], EFScrubber.prototype, "
|
|
334
|
+
})], EFScrubber.prototype, "contextCurrentTimeMs", void 0);
|
|
174
335
|
__decorate([consume({
|
|
175
336
|
context: durationContext,
|
|
176
337
|
subscribe: true
|
|
338
|
+
})], EFScrubber.prototype, "contextDurationMs", void 0);
|
|
339
|
+
__decorate([property({
|
|
340
|
+
type: String,
|
|
341
|
+
attribute: "orientation"
|
|
342
|
+
})], EFScrubber.prototype, "orientation", void 0);
|
|
343
|
+
__decorate([property({
|
|
344
|
+
type: Number,
|
|
345
|
+
attribute: "current-time-ms"
|
|
346
|
+
})], EFScrubber.prototype, "currentTimeMs", void 0);
|
|
347
|
+
__decorate([property({
|
|
348
|
+
type: Number,
|
|
349
|
+
attribute: "duration-ms"
|
|
177
350
|
})], EFScrubber.prototype, "durationMs", void 0);
|
|
351
|
+
__decorate([property({
|
|
352
|
+
type: Number,
|
|
353
|
+
attribute: "zoom-scale"
|
|
354
|
+
})], EFScrubber.prototype, "zoomScale", void 0);
|
|
355
|
+
__decorate([property({
|
|
356
|
+
type: Number,
|
|
357
|
+
attribute: "container-width"
|
|
358
|
+
})], EFScrubber.prototype, "containerWidth", void 0);
|
|
359
|
+
__decorate([property({
|
|
360
|
+
type: Number,
|
|
361
|
+
attribute: "fps"
|
|
362
|
+
})], EFScrubber.prototype, "fps", void 0);
|
|
363
|
+
__decorate([property({
|
|
364
|
+
type: Number,
|
|
365
|
+
attribute: "raw-scrub-time-ms"
|
|
366
|
+
})], EFScrubber.prototype, "rawScrubTimeMs", void 0);
|
|
367
|
+
__decorate([property({ attribute: false })], EFScrubber.prototype, "scrollContainerRef", void 0);
|
|
368
|
+
__decorate([property({ attribute: false })], EFScrubber.prototype, "trackContentRef", void 0);
|
|
369
|
+
__decorate([property({ attribute: false })], EFScrubber.prototype, "onSeek", void 0);
|
|
370
|
+
__decorate([property({ attribute: false })], EFScrubber.prototype, "isScrubbingRef", void 0);
|
|
178
371
|
__decorate([state()], EFScrubber.prototype, "scrubProgress", void 0);
|
|
179
372
|
__decorate([state()], EFScrubber.prototype, "isMoving", void 0);
|
|
180
373
|
__decorate([eventOptions({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EFScrubber.js","names":["EFScrubber"],"sources":["../../src/gui/EFScrubber.ts"],"sourcesContent":["import { consume } from \"@lit/context\";\nimport { css, html, LitElement } from \"lit\";\nimport { customElement, eventOptions, state } from \"lit/decorators.js\";\n\nimport { ref } from \"lit/directives/ref.js\";\nimport type { ControllableInterface } from \"./Controllable.js\";\nimport { currentTimeContext } from \"./currentTimeContext.js\";\nimport { durationContext } from \"./durationContext.js\";\nimport { efContext } from \"./efContext.js\";\nimport { playingContext } from \"./playingContext.js\";\nimport { TargetOrContextMixin } from \"./TargetOrContextMixin.js\";\n\n@customElement(\"ef-scrubber\")\nexport class EFScrubber extends TargetOrContextMixin(LitElement, efContext) {\n static styles = [\n css`\n :host {\n --ef-scrubber-height: 4px;\n --ef-scrubber-background: rgb(209 213 219);\n --ef-scrubber-progress-color: rgb(37 99 235);\n --ef-scrubber-handle-size: 12px;\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n :host(.dark), :host-context(.dark) {\n --ef-scrubber-background: rgb(75 85 99);\n --ef-scrubber-progress-color: rgb(96 165 250);\n }\n \n .scrubber {\n width: 100%;\n height: var(--ef-scrubber-height);\n background: var(--ef-scrubber-background);\n position: relative;\n cursor: pointer;\n border-radius: 2px;\n touch-action: none;\n user-select: none;\n }\n\n .progress {\n position: absolute;\n height: 100%;\n background: var(--ef-scrubber-progress-color);\n border-radius: 2px;\n }\n\n .handle {\n position: absolute;\n width: var(--ef-scrubber-handle-size);\n height: var(--ef-scrubber-handle-size);\n background: var(--ef-scrubber-progress-color);\n border-radius: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n cursor: grab;\n }\n\n /* Add CSS Shadow Parts */\n ::part(scrubber) { }\n ::part(progress) { }\n ::part(handle) { }\n `,\n ];\n\n @consume({ context: playingContext, subscribe: true })\n playing = false;\n\n @consume({ context: currentTimeContext, subscribe: true })\n currentTimeMs = Number.NaN;\n\n @consume({ context: durationContext, subscribe: true })\n durationMs = 0;\n\n get context(): ControllableInterface | null {\n return this.effectiveContext;\n }\n\n @state()\n private scrubProgress = 0;\n\n @state()\n private isMoving = false;\n\n private scrubberRef?: HTMLElement;\n private capturedPointerId: number | null = null;\n\n private updateProgress(e: PointerEvent) {\n if (!this.context || !this.scrubberRef) return;\n\n const rect = this.scrubberRef.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const progress = Math.max(0, Math.min(1, x / rect.width));\n\n this.scrubProgress = progress;\n this.context.currentTimeMs = progress * this.durationMs;\n }\n\n @eventOptions({ passive: false, capture: false })\n private handlePointerDown(e: PointerEvent) {\n if (!this.scrubberRef) return;\n\n this.isMoving = true;\n e.preventDefault();\n e.stopPropagation();\n this.capturedPointerId = e.pointerId;\n try {\n this.scrubberRef.setPointerCapture(e.pointerId);\n } catch (err) {\n // setPointerCapture may fail in some cases, continue anyway\n console.warn(\"Failed to set pointer capture:\", err);\n }\n this.updateProgress(e);\n }\n\n private boundHandlePointerMove = (e: PointerEvent) => {\n if (this.isMoving && e.pointerId === this.capturedPointerId) {\n e.preventDefault();\n e.stopPropagation();\n this.updateProgress(e);\n }\n };\n\n private boundHandlePointerUp = (e: PointerEvent) => {\n if (e.pointerId === this.capturedPointerId && this.scrubberRef) {\n e.preventDefault();\n e.stopPropagation();\n try {\n this.scrubberRef.releasePointerCapture(e.pointerId);\n } catch (_err) {\n // releasePointerCapture may fail if capture was already lost\n }\n this.capturedPointerId = null;\n this.isMoving = false;\n }\n };\n\n private boundHandlePointerCancel = (e: PointerEvent) => {\n if (e.pointerId === this.capturedPointerId && this.scrubberRef) {\n try {\n this.scrubberRef.releasePointerCapture(e.pointerId);\n } catch (_err) {\n // releasePointerCapture may fail if capture was already lost\n }\n this.capturedPointerId = null;\n this.isMoving = false;\n }\n };\n\n private boundHandleContextMenu = (e: Event) => {\n if (this.isMoving) {\n e.preventDefault();\n e.stopPropagation();\n }\n };\n\n render() {\n // Calculate progress from currentTimeMs and duration\n const currentProgress =\n this.durationMs > 0 ? (this.currentTimeMs ?? 0) / this.durationMs : 0;\n\n const displayProgress = this.isMoving\n ? this.scrubProgress\n : currentProgress;\n\n return html`\n <div \n ${ref((el) => {\n this.scrubberRef = el as HTMLElement;\n })}\n part=\"scrubber\"\n class=\"scrubber\"\n @pointerdown=${this.handlePointerDown}\n @contextmenu=${this.boundHandleContextMenu}\n >\n <div class=\"progress\" style=\"width: ${displayProgress * 100}%\"></div>\n <div class=\"handle\" style=\"left: ${displayProgress * 100}%\"></div>\n </div>\n `;\n }\n\n connectedCallback() {\n super.connectedCallback();\n window.addEventListener(\n \"pointerup\",\n this.boundHandlePointerUp as EventListener,\n { passive: false },\n );\n window.addEventListener(\"pointermove\", this.boundHandlePointerMove, {\n passive: false,\n });\n window.addEventListener(\n \"pointercancel\",\n this.boundHandlePointerCancel as EventListener,\n { passive: false },\n );\n this.addEventListener(\"contextmenu\", this.boundHandleContextMenu, {\n passive: false,\n });\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n window.removeEventListener(\n \"pointerup\",\n this.boundHandlePointerUp as EventListener,\n );\n window.removeEventListener(\"pointermove\", this.boundHandlePointerMove);\n window.removeEventListener(\n \"pointercancel\",\n this.boundHandlePointerCancel as EventListener,\n );\n this.removeEventListener(\"contextmenu\", this.boundHandleContextMenu);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-scrubber\": EFScrubber;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EFScrubber.js","names":["EFScrubber"],"sources":["../../src/gui/EFScrubber.ts"],"sourcesContent":["import { consume } from \"@lit/context\";\nimport { css, html, LitElement } from \"lit\";\nimport {\n customElement,\n eventOptions,\n property,\n state,\n} from \"lit/decorators.js\";\n\nimport { createRef, ref } from \"lit/directives/ref.js\";\nimport type { ControllableInterface } from \"./Controllable.js\";\nimport { currentTimeContext } from \"./currentTimeContext.js\";\nimport { durationContext } from \"./durationContext.js\";\nimport { efContext } from \"./efContext.js\";\nimport { playingContext } from \"./playingContext.js\";\nimport { TargetOrContextMixin } from \"./TargetOrContextMixin.js\";\nimport { quantizeToFrameTimeMs } from \"./EFTimelineRuler.js\";\n\nconst BASE_PIXELS_PER_SECOND = 100;\n\nfunction timeToPixels(\n timeMs: number,\n durationMs: number,\n containerWidth: number,\n zoomScale: number,\n): number {\n if (durationMs <= 0) return 0;\n const pixelsPerSecond = BASE_PIXELS_PER_SECOND * zoomScale;\n return (timeMs / 1000) * pixelsPerSecond;\n}\n\nfunction pixelsToTime(\n pixels: number,\n durationMs: number,\n containerWidth: number,\n zoomScale: number,\n): number {\n if (durationMs <= 0) return 0;\n const pixelsPerSecond = BASE_PIXELS_PER_SECOND * zoomScale;\n return (pixels / pixelsPerSecond) * 1000;\n}\n\n@customElement(\"ef-scrubber\")\nexport class EFScrubber extends TargetOrContextMixin(LitElement, efContext) {\n static styles = [\n css`\n :host {\n --ef-scrubber-height: 4px;\n --ef-scrubber-background: rgb(209 213 219);\n --ef-scrubber-progress-color: rgb(37 99 235);\n --ef-scrubber-handle-size: 12px;\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n :host(.dark), :host-context(.dark) {\n --ef-scrubber-background: rgb(75 85 99);\n --ef-scrubber-progress-color: rgb(96 165 250);\n }\n \n :host([orientation=\"vertical\"]) {\n width: 100%;\n height: 100%;\n position: absolute;\n inset: 0;\n pointer-events: auto;\n }\n\n .scrubber {\n width: 100%;\n height: var(--ef-scrubber-height);\n background: var(--ef-scrubber-background);\n position: relative;\n cursor: pointer;\n border-radius: 2px;\n touch-action: none;\n user-select: none;\n }\n\n :host([orientation=\"vertical\"]) .scrubber {\n width: 100%;\n height: 100%;\n background: transparent;\n cursor: ew-resize;\n }\n\n .progress {\n position: absolute;\n height: 100%;\n background: var(--ef-scrubber-progress-color);\n border-radius: 2px;\n }\n\n :host([orientation=\"vertical\"]) .progress {\n display: none;\n }\n\n .handle {\n position: absolute;\n width: var(--ef-scrubber-handle-size);\n height: var(--ef-scrubber-handle-size);\n background: var(--ef-scrubber-progress-color);\n border-radius: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n cursor: grab;\n }\n\n :host([orientation=\"vertical\"]) .handle {\n display: none;\n }\n\n .playhead {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--ef-scrubber-progress-color);\n pointer-events: auto;\n cursor: ew-resize;\n z-index: 30;\n }\n\n ::part(playhead) {\n z-index: 30;\n }\n\n .playhead-handle {\n position: absolute;\n top: 0;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 12px;\n height: 12px;\n background: var(--ef-scrubber-progress-color);\n border-radius: 50%;\n }\n\n .raw-preview {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 2px;\n background: rgba(37, 99, 235, 0.2);\n pointer-events: none;\n z-index: 20;\n }\n\n /* Add CSS Shadow Parts */\n ::part(scrubber) { }\n ::part(progress) { }\n ::part(handle) { }\n `,\n ];\n\n @consume({ context: playingContext, subscribe: true })\n playing = false;\n\n @consume({ context: currentTimeContext, subscribe: true })\n contextCurrentTimeMs = Number.NaN;\n\n @consume({ context: durationContext, subscribe: true })\n contextDurationMs = 0;\n\n @property({ type: String, attribute: \"orientation\" })\n orientation: \"horizontal\" | \"vertical\" = \"horizontal\";\n\n @property({ type: Number, attribute: \"current-time-ms\" })\n currentTimeMs = Number.NaN;\n\n @property({ type: Number, attribute: \"duration-ms\" })\n durationMs = 0;\n\n @property({ type: Number, attribute: \"zoom-scale\" })\n zoomScale = 1.0;\n\n @property({ type: Number, attribute: \"container-width\" })\n containerWidth = 0;\n\n @property({ type: Number, attribute: \"fps\" })\n fps?: number;\n\n @property({ type: Number, attribute: \"raw-scrub-time-ms\" })\n rawScrubTimeMs?: number | null;\n\n @property({ attribute: false })\n scrollContainerRef?: { current: HTMLElement | null };\n\n /**\n * Reference to the element that represents the actual track content area.\n * Used to calculate the offset between the scroll container and where tracks begin.\n */\n @property({ attribute: false })\n trackContentRef?: { current: HTMLElement | null };\n\n @property({ attribute: false })\n onSeek?: (time: number) => void;\n\n @property({ attribute: false })\n isScrubbingRef?: { current: boolean };\n\n get context(): ControllableInterface | null {\n return this.effectiveContext;\n }\n\n get effectiveCurrentTimeMs(): number {\n if (!Number.isNaN(this.currentTimeMs)) {\n return this.currentTimeMs;\n }\n if (!Number.isNaN(this.contextCurrentTimeMs)) {\n return this.contextCurrentTimeMs;\n }\n return 0;\n }\n\n get effectiveDurationMs(): number {\n return this.durationMs || this.contextDurationMs || 0;\n }\n\n get isTimelineMode(): boolean {\n return this.orientation === \"vertical\" && this.zoomScale > 0;\n }\n\n @state()\n private scrubProgress = 0;\n\n @state()\n private isMoving = false;\n\n private scrubberRef = createRef<HTMLElement>();\n private _scrubberElement?: HTMLElement;\n private capturedPointerId: number | null = null;\n\n private updateProgress(e: PointerEvent) {\n const scrubberEl = this.scrubberRef.value || this._scrubberElement;\n if (!scrubberEl) return;\n\n const duration = this.effectiveDurationMs;\n if (duration <= 0) return;\n\n if (this.isTimelineMode) {\n // Timeline mode: use pixel-based positioning with zoom\n const scrollContainer =\n this.scrollContainerRef?.current || scrubberEl.parentElement;\n if (!scrollContainer) return;\n\n const scrollContainerRect = scrollContainer.getBoundingClientRect();\n const scrollLeft = scrollContainer.scrollLeft || 0;\n\n // Calculate pixel offset dynamically from the track content element\n // This accounts for any hierarchy panel or other elements before the tracks\n let pixelOffset = 0;\n if (this.trackContentRef?.current) {\n const trackRect = this.trackContentRef.current.getBoundingClientRect();\n pixelOffset =\n trackRect.left -\n scrollContainerRect.left +\n scrollContainer.scrollLeft;\n }\n\n const x = e.clientX - scrollContainerRect.left - pixelOffset;\n const pixelPosition = scrollLeft + x;\n const effectiveWidth =\n this.containerWidth > 0\n ? this.containerWidth\n : scrollContainerRect.width;\n if (effectiveWidth <= 0) return;\n\n let rawTime = pixelsToTime(\n pixelPosition,\n duration,\n effectiveWidth,\n this.zoomScale,\n );\n rawTime = Math.max(0, Math.min(rawTime, duration));\n\n // Quantize to frame boundaries if FPS is provided, then clamp to duration\n let quantizedTime =\n this.fps && this.fps > 0\n ? quantizeToFrameTimeMs(rawTime, this.fps)\n : rawTime;\n quantizedTime = Math.max(0, Math.min(quantizedTime, duration));\n\n this.scrubProgress = quantizedTime / duration;\n\n if (this.onSeek) {\n this.onSeek(quantizedTime);\n } else {\n // Emit seek event for event listeners\n this.dispatchEvent(\n new CustomEvent(\"seek\", {\n detail: quantizedTime,\n bubbles: true,\n composed: true,\n }),\n );\n if (this.context) {\n this.context.currentTimeMs = quantizedTime;\n }\n }\n } else {\n // Horizontal mode: simple progress calculation\n const rect = scrubberEl.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const progress = Math.max(0, Math.min(1, x / rect.width));\n\n this.scrubProgress = progress;\n const timeMs = progress * duration;\n\n if (this.onSeek) {\n this.onSeek(timeMs);\n } else {\n // Emit seek event for event listeners\n this.dispatchEvent(\n new CustomEvent(\"seek\", {\n detail: timeMs,\n bubbles: true,\n composed: true,\n }),\n );\n if (this.context) {\n this.context.currentTimeMs = timeMs;\n }\n }\n }\n }\n\n @eventOptions({ passive: false, capture: false })\n private handlePointerDown(e: PointerEvent) {\n const scrubberEl = this.scrubberRef.value || this._scrubberElement;\n if (!scrubberEl) return;\n\n this.isMoving = true;\n if (this.isScrubbingRef) {\n this.isScrubbingRef.current = true;\n }\n e.preventDefault();\n e.stopPropagation();\n this.capturedPointerId = e.pointerId;\n try {\n scrubberEl.setPointerCapture(e.pointerId);\n } catch (err) {\n // setPointerCapture may fail in some cases, continue anyway\n console.warn(\"Failed to set pointer capture:\", err);\n }\n this.updateProgress(e);\n }\n\n private boundHandlePointerMove = (e: PointerEvent) => {\n if (this.isMoving && e.pointerId === this.capturedPointerId) {\n e.preventDefault();\n e.stopPropagation();\n this.updateProgress(e);\n }\n };\n\n private boundHandlePointerUp = (e: PointerEvent) => {\n const scrubberEl = this.scrubberRef.value || this._scrubberElement;\n if (e.pointerId === this.capturedPointerId && scrubberEl) {\n e.preventDefault();\n e.stopPropagation();\n try {\n scrubberEl.releasePointerCapture(e.pointerId);\n } catch (_err) {\n // releasePointerCapture may fail if capture was already lost\n }\n this.capturedPointerId = null;\n this.isMoving = false;\n if (this.isScrubbingRef) {\n this.isScrubbingRef.current = false;\n }\n }\n };\n\n private boundHandlePointerCancel = (e: PointerEvent) => {\n const scrubberEl = this.scrubberRef.value || this._scrubberElement;\n if (e.pointerId === this.capturedPointerId && scrubberEl) {\n try {\n scrubberEl.releasePointerCapture(e.pointerId);\n } catch (_err) {\n // releasePointerCapture may fail if capture was already lost\n }\n this.capturedPointerId = null;\n this.isMoving = false;\n if (this.isScrubbingRef) {\n this.isScrubbingRef.current = false;\n }\n }\n };\n\n private boundHandleContextMenu = (e: Event) => {\n if (this.isMoving) {\n e.preventDefault();\n e.stopPropagation();\n }\n };\n\n render() {\n const duration = this.effectiveDurationMs;\n const currentTime = this.effectiveCurrentTimeMs;\n\n if (duration <= 0) {\n return html``;\n }\n\n if (this.isTimelineMode) {\n // Vertical timeline mode: render playhead line\n const scrubberEl = this.scrubberRef.value || this._scrubberElement;\n const effectiveWidth =\n this.containerWidth > 0\n ? this.containerWidth\n : scrubberEl?.parentElement?.getBoundingClientRect().width || 0;\n\n const positionPixels =\n effectiveWidth > 0\n ? timeToPixels(currentTime, duration, effectiveWidth, this.zoomScale)\n : 0;\n\n const rawScrubPositionPixels =\n this.rawScrubTimeMs !== null &&\n this.rawScrubTimeMs !== undefined &&\n effectiveWidth > 0\n ? timeToPixels(\n this.rawScrubTimeMs,\n duration,\n effectiveWidth,\n this.zoomScale,\n )\n : null;\n\n return html`\n ${\n rawScrubPositionPixels !== null &&\n rawScrubPositionPixels !== positionPixels\n ? html`<div\n class=\"raw-preview\"\n style=\"left: ${rawScrubPositionPixels}px\"\n ></div>`\n : html``\n }\n <div\n ${ref(this.scrubberRef)}\n part=\"scrubber\"\n class=\"scrubber\"\n @pointerdown=${this.handlePointerDown}\n @contextmenu=${this.boundHandleContextMenu}\n >\n <div\n part=\"playhead\"\n class=\"playhead\"\n style=\"left: ${positionPixels}px\"\n @pointerdown=${this.handlePointerDown}\n >\n <div class=\"playhead-handle\"></div>\n </div>\n </div>\n `;\n } else {\n // Horizontal mode: render progress bar\n const currentProgress = duration > 0 ? currentTime / duration : 0;\n const displayProgress = this.isMoving\n ? this.scrubProgress\n : currentProgress;\n\n return html`\n <div\n ${ref(this.scrubberRef)}\n part=\"scrubber\"\n class=\"scrubber\"\n @pointerdown=${this.handlePointerDown}\n @contextmenu=${this.boundHandleContextMenu}\n >\n <div class=\"progress\" style=\"width: ${displayProgress * 100}%\"></div>\n <div class=\"handle\" style=\"left: ${displayProgress * 100}%\"></div>\n </div>\n `;\n }\n }\n\n connectedCallback() {\n super.connectedCallback();\n window.addEventListener(\n \"pointerup\",\n this.boundHandlePointerUp as EventListener,\n { passive: false },\n );\n window.addEventListener(\"pointermove\", this.boundHandlePointerMove, {\n passive: false,\n });\n window.addEventListener(\n \"pointercancel\",\n this.boundHandlePointerCancel as EventListener,\n { passive: false },\n );\n this.addEventListener(\"contextmenu\", this.boundHandleContextMenu, {\n passive: false,\n });\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n window.removeEventListener(\n \"pointerup\",\n this.boundHandlePointerUp as EventListener,\n );\n window.removeEventListener(\"pointermove\", this.boundHandlePointerMove);\n window.removeEventListener(\n \"pointercancel\",\n this.boundHandlePointerCancel as EventListener,\n );\n this.removeEventListener(\"contextmenu\", this.boundHandleContextMenu);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-scrubber\": EFScrubber;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ControllableInterface } from "./Controllable.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as lit23 from "lit";
|
|
3
3
|
import { LitElement } from "lit";
|
|
4
|
-
import * as
|
|
4
|
+
import * as lit_html23 from "lit-html";
|
|
5
5
|
|
|
6
6
|
//#region src/gui/EFTimeDisplay.d.ts
|
|
7
7
|
declare const EFTimeDisplay_base: (new (...args: any[]) => {
|
|
@@ -10,11 +10,11 @@ declare const EFTimeDisplay_base: (new (...args: any[]) => {
|
|
|
10
10
|
effectiveContext: ControllableInterface | null;
|
|
11
11
|
}) & typeof LitElement;
|
|
12
12
|
declare class EFTimeDisplay extends EFTimeDisplay_base {
|
|
13
|
-
static styles:
|
|
13
|
+
static styles: lit23.CSSResult;
|
|
14
14
|
currentTimeMs: number;
|
|
15
15
|
durationMs: number;
|
|
16
16
|
private formatTime;
|
|
17
|
-
render():
|
|
17
|
+
render(): lit_html23.TemplateResult<1>;
|
|
18
18
|
}
|
|
19
19
|
declare global {
|
|
20
20
|
interface HTMLElementTagNameMap {
|
|
@@ -17,12 +17,15 @@ let EFTimeDisplay = class EFTimeDisplay$1 extends TargetOrContextMixin(LitElemen
|
|
|
17
17
|
static {
|
|
18
18
|
this.styles = css`
|
|
19
19
|
:host {
|
|
20
|
-
display: inline-
|
|
20
|
+
display: inline-flex;
|
|
21
|
+
align-items: center;
|
|
21
22
|
font-family: var(--ef-font-family, system-ui);
|
|
22
23
|
font-size: var(--ef-font-size-xs, 0.75rem);
|
|
23
24
|
color: var(--ef-text-color, rgb(75 85 99));
|
|
24
25
|
white-space: nowrap;
|
|
25
26
|
}
|
|
27
|
+
|
|
28
|
+
::part(time) {}
|
|
26
29
|
`;
|
|
27
30
|
}
|
|
28
31
|
formatTime(ms) {
|