@editframe/elements 0.30.2-beta.0 → 0.31.0-beta.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.
- 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 +129 -56
- package/dist/elements/EFThumbnailStrip.js +605 -359
- package/dist/elements/EFThumbnailStrip.js.map +1 -1
- package/dist/elements/EFTimegroup.d.ts +233 -25
- package/dist/elements/EFTimegroup.js +865 -144
- 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 +154 -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 +171 -28
- 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 +7 -1
- 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/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 +178 -0
- 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 +833 -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/preview/workers/encoderWorkerInline.js +103 -0
- package/dist/preview/workers/encoderWorkerInline.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 +71 -67
- 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
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import * as lit32 from "lit";
|
|
2
|
+
import { LitElement } from "lit";
|
|
3
|
+
import * as lit_html31 from "lit-html";
|
|
4
|
+
|
|
5
|
+
//#region src/elements/EFPanZoom.d.ts
|
|
6
|
+
interface PanZoomTransform {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
scale: number;
|
|
10
|
+
}
|
|
11
|
+
declare class EFPanZoom extends LitElement {
|
|
12
|
+
static styles: lit32.CSSResult[];
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
scale: number;
|
|
16
|
+
/**
|
|
17
|
+
* When true, automatically fits content to view on first render.
|
|
18
|
+
* Centers content and scales it to fit within the container with padding.
|
|
19
|
+
*/
|
|
20
|
+
autoFit: boolean;
|
|
21
|
+
panZoomTransform: PanZoomTransform;
|
|
22
|
+
private _isDragging;
|
|
23
|
+
private _dragStartPointerPos;
|
|
24
|
+
private _dragStartTransform;
|
|
25
|
+
private _capturedPointerId;
|
|
26
|
+
/**
|
|
27
|
+
* Document-level wheel handler in capture phase to prevent browser navigation.
|
|
28
|
+
* This prevents back/forward navigation on two-finger swipe gestures.
|
|
29
|
+
* We use capture phase to catch events before they bubble, but only prevent default
|
|
30
|
+
* (not stop propagation) so the normal wheel handler can still process them.
|
|
31
|
+
*/
|
|
32
|
+
private _onDocumentWheelCapture;
|
|
33
|
+
connectedCallback(): void;
|
|
34
|
+
disconnectedCallback(): void;
|
|
35
|
+
private _updateTransform;
|
|
36
|
+
private _onPointerDown;
|
|
37
|
+
private _onPointerMove;
|
|
38
|
+
private _onPointerUp;
|
|
39
|
+
private _onWheel;
|
|
40
|
+
firstUpdated(changedProperties: Map<PropertyKey, unknown>): void;
|
|
41
|
+
/**
|
|
42
|
+
* Convert screen coordinates (e.g., mouse event clientX/clientY) to canvas coordinates.
|
|
43
|
+
* This handles all pan/zoom transformations automatically.
|
|
44
|
+
*
|
|
45
|
+
* @param screenX - X coordinate in screen space (e.g., event.clientX)
|
|
46
|
+
* @param screenY - Y coordinate in screen space (e.g., event.clientY)
|
|
47
|
+
* @returns Object with x, y in canvas coordinate space
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* handleClick(e: MouseEvent) {
|
|
51
|
+
* const canvasPos = panZoom.screenToCanvas(e.clientX, e.clientY);
|
|
52
|
+
* console.log(`Clicked at canvas position: ${canvasPos.x}, ${canvasPos.y}`);
|
|
53
|
+
* }
|
|
54
|
+
*/
|
|
55
|
+
screenToCanvas(screenX: number, screenY: number): {
|
|
56
|
+
x: number;
|
|
57
|
+
y: number;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Convert canvas coordinates to screen coordinates.
|
|
61
|
+
* Useful for positioning overlays or tooltips relative to canvas elements.
|
|
62
|
+
*
|
|
63
|
+
* @param canvasX - X coordinate in canvas space
|
|
64
|
+
* @param canvasY - Y coordinate in canvas space
|
|
65
|
+
* @returns Object with x, y in screen coordinate space
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* const screenPos = panZoom.canvasToScreen(element.x, element.y);
|
|
69
|
+
* tooltip.style.left = `${screenPos.x}px`;
|
|
70
|
+
* tooltip.style.top = `${screenPos.y}px`;
|
|
71
|
+
*/
|
|
72
|
+
canvasToScreen(canvasX: number, canvasY: number): {
|
|
73
|
+
x: number;
|
|
74
|
+
y: number;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Reset the pan-zoom transform to its default values (x: 0, y: 0, scale: 1).
|
|
78
|
+
* This method can be called programmatically to reset the view.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* const panZoomRef = useRef(null);
|
|
82
|
+
* <button onClick={() => panZoomRef.current.reset()}>Reset View</button>
|
|
83
|
+
*/
|
|
84
|
+
reset(): void;
|
|
85
|
+
/**
|
|
86
|
+
* Fit content to the container, centering it and scaling to fit.
|
|
87
|
+
* Uses a padding factor to leave some margin around the content.
|
|
88
|
+
*
|
|
89
|
+
* @param padding - Padding factor (0-1), e.g., 0.1 = 10% padding on each side. Default: 0.05
|
|
90
|
+
*/
|
|
91
|
+
fitToContent(padding?: number): void;
|
|
92
|
+
render(): lit_html31.TemplateResult<1>;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { EFPanZoom, PanZoomTransform };
|
|
96
|
+
//# sourceMappingURL=EFPanZoom.d.ts.map
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { __decorate } from "../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js";
|
|
2
|
+
import { panZoomTransformContext } from "../gui/panZoomTransformContext.js";
|
|
3
|
+
import { provide } from "@lit/context";
|
|
4
|
+
import { LitElement, css, html } from "lit";
|
|
5
|
+
import { customElement, property } from "lit/decorators.js";
|
|
6
|
+
|
|
7
|
+
//#region src/elements/EFPanZoom.ts
|
|
8
|
+
let EFPanZoom = class EFPanZoom$1 extends LitElement {
|
|
9
|
+
constructor(..._args) {
|
|
10
|
+
super(..._args);
|
|
11
|
+
this.x = 0;
|
|
12
|
+
this.y = 0;
|
|
13
|
+
this.scale = 1;
|
|
14
|
+
this.autoFit = false;
|
|
15
|
+
this.panZoomTransform = {
|
|
16
|
+
x: 0,
|
|
17
|
+
y: 0,
|
|
18
|
+
scale: 1
|
|
19
|
+
};
|
|
20
|
+
this._isDragging = false;
|
|
21
|
+
this._dragStartPointerPos = null;
|
|
22
|
+
this._dragStartTransform = null;
|
|
23
|
+
this._capturedPointerId = null;
|
|
24
|
+
this._onDocumentWheelCapture = (e) => {
|
|
25
|
+
let panZoom = null;
|
|
26
|
+
if (e.target instanceof Element) {
|
|
27
|
+
panZoom = e.target.closest("ef-pan-zoom");
|
|
28
|
+
if (!panZoom && e.target.closest("ef-canvas-selection-overlay")) {
|
|
29
|
+
const rect = this.getBoundingClientRect();
|
|
30
|
+
if (e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom) panZoom = this;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (panZoom === this) e.preventDefault();
|
|
34
|
+
};
|
|
35
|
+
this._onPointerDown = (e) => {
|
|
36
|
+
if (e.button !== 0) return;
|
|
37
|
+
this._isDragging = true;
|
|
38
|
+
this._capturedPointerId = e.pointerId;
|
|
39
|
+
this._dragStartPointerPos = {
|
|
40
|
+
x: e.clientX,
|
|
41
|
+
y: e.clientY
|
|
42
|
+
};
|
|
43
|
+
this._dragStartTransform = {
|
|
44
|
+
x: this.x,
|
|
45
|
+
y: this.y,
|
|
46
|
+
scale: this.scale
|
|
47
|
+
};
|
|
48
|
+
try {
|
|
49
|
+
this.setPointerCapture(e.pointerId);
|
|
50
|
+
} catch (err) {}
|
|
51
|
+
};
|
|
52
|
+
this._onPointerMove = (e) => {
|
|
53
|
+
if (!this._isDragging || !this._dragStartPointerPos || !this._dragStartTransform) return;
|
|
54
|
+
const deltaX = e.clientX - this._dragStartPointerPos.x;
|
|
55
|
+
const deltaY = e.clientY - this._dragStartPointerPos.y;
|
|
56
|
+
this._updateTransform({
|
|
57
|
+
x: this._dragStartTransform.x - deltaX,
|
|
58
|
+
y: this._dragStartTransform.y - deltaY
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
this._onPointerUp = (e) => {
|
|
62
|
+
if (!this._isDragging) return;
|
|
63
|
+
if (this._capturedPointerId !== null) try {
|
|
64
|
+
this.releasePointerCapture(e.pointerId);
|
|
65
|
+
} catch (err) {}
|
|
66
|
+
this._isDragging = false;
|
|
67
|
+
this._capturedPointerId = null;
|
|
68
|
+
this._dragStartPointerPos = null;
|
|
69
|
+
this._dragStartTransform = null;
|
|
70
|
+
};
|
|
71
|
+
this._onWheel = (e) => {
|
|
72
|
+
e.preventDefault();
|
|
73
|
+
e.stopPropagation();
|
|
74
|
+
if (e.metaKey || e.ctrlKey) {
|
|
75
|
+
const containerRect = this.getBoundingClientRect();
|
|
76
|
+
const pointerX = e.clientX - containerRect.left;
|
|
77
|
+
const pointerY = e.clientY - containerRect.top;
|
|
78
|
+
const currentX = this.x;
|
|
79
|
+
const currentY = this.y;
|
|
80
|
+
const currentScale = this.scale;
|
|
81
|
+
const canvasX = (pointerX - currentX) / currentScale;
|
|
82
|
+
const canvasY = (pointerY - currentY) / currentScale;
|
|
83
|
+
const delta = e.deltaY > 0 ? .95 : 1.05;
|
|
84
|
+
const newScale = Math.max(.1, Math.min(5, currentScale * delta));
|
|
85
|
+
const newX = pointerX - canvasX * newScale;
|
|
86
|
+
const newY = pointerY - canvasY * newScale;
|
|
87
|
+
this._updateTransform({
|
|
88
|
+
x: newX,
|
|
89
|
+
y: newY,
|
|
90
|
+
scale: newScale
|
|
91
|
+
});
|
|
92
|
+
} else {
|
|
93
|
+
const deltaX = -e.deltaX;
|
|
94
|
+
const deltaY = -e.deltaY;
|
|
95
|
+
this._updateTransform({
|
|
96
|
+
x: this.x + deltaX,
|
|
97
|
+
y: this.y + deltaY
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
static {
|
|
103
|
+
this.styles = [css`
|
|
104
|
+
:host {
|
|
105
|
+
display: block;
|
|
106
|
+
overflow: hidden;
|
|
107
|
+
position: relative;
|
|
108
|
+
touch-action: none;
|
|
109
|
+
}
|
|
110
|
+
.content-wrapper {
|
|
111
|
+
position: absolute;
|
|
112
|
+
inset: 0;
|
|
113
|
+
width: 100%;
|
|
114
|
+
height: 100%;
|
|
115
|
+
transform-origin: 0 0;
|
|
116
|
+
}
|
|
117
|
+
`];
|
|
118
|
+
}
|
|
119
|
+
connectedCallback() {
|
|
120
|
+
super.connectedCallback();
|
|
121
|
+
document.addEventListener("wheel", this._onDocumentWheelCapture, {
|
|
122
|
+
passive: false,
|
|
123
|
+
capture: true
|
|
124
|
+
});
|
|
125
|
+
this.addEventListener("wheel", this._onWheel, { passive: false });
|
|
126
|
+
this.addEventListener("pointerdown", this._onPointerDown);
|
|
127
|
+
this.addEventListener("pointermove", this._onPointerMove);
|
|
128
|
+
this.addEventListener("pointerup", this._onPointerUp);
|
|
129
|
+
this.addEventListener("pointercancel", this._onPointerUp);
|
|
130
|
+
}
|
|
131
|
+
disconnectedCallback() {
|
|
132
|
+
super.disconnectedCallback();
|
|
133
|
+
document.removeEventListener("wheel", this._onDocumentWheelCapture, { capture: true });
|
|
134
|
+
this.removeEventListener("wheel", this._onWheel);
|
|
135
|
+
this.removeEventListener("pointerdown", this._onPointerDown);
|
|
136
|
+
this.removeEventListener("pointermove", this._onPointerMove);
|
|
137
|
+
this.removeEventListener("pointerup", this._onPointerUp);
|
|
138
|
+
this.removeEventListener("pointercancel", this._onPointerUp);
|
|
139
|
+
if (this._isDragging && this._capturedPointerId !== null) try {
|
|
140
|
+
this.releasePointerCapture(this._capturedPointerId);
|
|
141
|
+
} catch (err) {}
|
|
142
|
+
}
|
|
143
|
+
_updateTransform(updates) {
|
|
144
|
+
const newTransform = {
|
|
145
|
+
x: updates.x !== void 0 ? updates.x : this.x,
|
|
146
|
+
y: updates.y !== void 0 ? updates.y : this.y,
|
|
147
|
+
scale: updates.scale !== void 0 ? Math.max(.1, Math.min(5, updates.scale)) : this.scale
|
|
148
|
+
};
|
|
149
|
+
if (newTransform.x !== this.x || newTransform.y !== this.y || newTransform.scale !== this.scale) {
|
|
150
|
+
this.x = newTransform.x;
|
|
151
|
+
this.y = newTransform.y;
|
|
152
|
+
this.scale = newTransform.scale;
|
|
153
|
+
this.panZoomTransform = { ...newTransform };
|
|
154
|
+
this.dispatchEvent(new CustomEvent("transform-changed", {
|
|
155
|
+
detail: { ...newTransform },
|
|
156
|
+
bubbles: true,
|
|
157
|
+
composed: true
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
firstUpdated(changedProperties) {
|
|
162
|
+
super.firstUpdated(changedProperties);
|
|
163
|
+
this.panZoomTransform = {
|
|
164
|
+
x: this.x,
|
|
165
|
+
y: this.y,
|
|
166
|
+
scale: this.scale
|
|
167
|
+
};
|
|
168
|
+
if (this.autoFit) requestAnimationFrame(() => {
|
|
169
|
+
this.fitToContent();
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Convert screen coordinates (e.g., mouse event clientX/clientY) to canvas coordinates.
|
|
174
|
+
* This handles all pan/zoom transformations automatically.
|
|
175
|
+
*
|
|
176
|
+
* @param screenX - X coordinate in screen space (e.g., event.clientX)
|
|
177
|
+
* @param screenY - Y coordinate in screen space (e.g., event.clientY)
|
|
178
|
+
* @returns Object with x, y in canvas coordinate space
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* handleClick(e: MouseEvent) {
|
|
182
|
+
* const canvasPos = panZoom.screenToCanvas(e.clientX, e.clientY);
|
|
183
|
+
* console.log(`Clicked at canvas position: ${canvasPos.x}, ${canvasPos.y}`);
|
|
184
|
+
* }
|
|
185
|
+
*/
|
|
186
|
+
screenToCanvas(screenX, screenY) {
|
|
187
|
+
const rect = this.getBoundingClientRect();
|
|
188
|
+
return {
|
|
189
|
+
x: (screenX - rect.left - this.x) / this.scale,
|
|
190
|
+
y: (screenY - rect.top - this.y) / this.scale
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Convert canvas coordinates to screen coordinates.
|
|
195
|
+
* Useful for positioning overlays or tooltips relative to canvas elements.
|
|
196
|
+
*
|
|
197
|
+
* @param canvasX - X coordinate in canvas space
|
|
198
|
+
* @param canvasY - Y coordinate in canvas space
|
|
199
|
+
* @returns Object with x, y in screen coordinate space
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* const screenPos = panZoom.canvasToScreen(element.x, element.y);
|
|
203
|
+
* tooltip.style.left = `${screenPos.x}px`;
|
|
204
|
+
* tooltip.style.top = `${screenPos.y}px`;
|
|
205
|
+
*/
|
|
206
|
+
canvasToScreen(canvasX, canvasY) {
|
|
207
|
+
const rect = this.getBoundingClientRect();
|
|
208
|
+
return {
|
|
209
|
+
x: rect.left + canvasX * this.scale + this.x,
|
|
210
|
+
y: rect.top + canvasY * this.scale + this.y
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Reset the pan-zoom transform to its default values (x: 0, y: 0, scale: 1).
|
|
215
|
+
* This method can be called programmatically to reset the view.
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* const panZoomRef = useRef(null);
|
|
219
|
+
* <button onClick={() => panZoomRef.current.reset()}>Reset View</button>
|
|
220
|
+
*/
|
|
221
|
+
reset() {
|
|
222
|
+
this._updateTransform({
|
|
223
|
+
x: 0,
|
|
224
|
+
y: 0,
|
|
225
|
+
scale: 1
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Fit content to the container, centering it and scaling to fit.
|
|
230
|
+
* Uses a padding factor to leave some margin around the content.
|
|
231
|
+
*
|
|
232
|
+
* @param padding - Padding factor (0-1), e.g., 0.1 = 10% padding on each side. Default: 0.05
|
|
233
|
+
*/
|
|
234
|
+
fitToContent(padding = .05) {
|
|
235
|
+
const containerRect = this.getBoundingClientRect();
|
|
236
|
+
if (containerRect.width === 0 || containerRect.height === 0) return;
|
|
237
|
+
const slottedContent = (this.shadowRoot?.querySelector(".content-wrapper"))?.querySelector("slot")?.assignedElements()[0];
|
|
238
|
+
if (!slottedContent) return;
|
|
239
|
+
const contentRect = slottedContent.getBoundingClientRect();
|
|
240
|
+
const contentWidth = contentRect.width / this.scale;
|
|
241
|
+
const contentHeight = contentRect.height / this.scale;
|
|
242
|
+
if (contentWidth === 0 || contentHeight === 0) return;
|
|
243
|
+
const availableWidth = containerRect.width * (1 - 2 * padding);
|
|
244
|
+
const availableHeight = containerRect.height * (1 - 2 * padding);
|
|
245
|
+
const scaleX = availableWidth / contentWidth;
|
|
246
|
+
const scaleY = availableHeight / contentHeight;
|
|
247
|
+
const newScale = Math.min(scaleX, scaleY, 1);
|
|
248
|
+
const scaledWidth = contentWidth * newScale;
|
|
249
|
+
const scaledHeight = contentHeight * newScale;
|
|
250
|
+
const newX = (containerRect.width - scaledWidth) / 2;
|
|
251
|
+
const newY = (containerRect.height - scaledHeight) / 2;
|
|
252
|
+
this._updateTransform({
|
|
253
|
+
x: newX,
|
|
254
|
+
y: newY,
|
|
255
|
+
scale: newScale
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
render() {
|
|
259
|
+
return html`
|
|
260
|
+
<div
|
|
261
|
+
class="content-wrapper"
|
|
262
|
+
style="transform: translate(${this.x}px, ${this.y}px) scale(${this.scale});"
|
|
263
|
+
>
|
|
264
|
+
<slot></slot>
|
|
265
|
+
</div>
|
|
266
|
+
`;
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
__decorate([property({
|
|
270
|
+
type: Number,
|
|
271
|
+
reflect: true
|
|
272
|
+
})], EFPanZoom.prototype, "x", void 0);
|
|
273
|
+
__decorate([property({
|
|
274
|
+
type: Number,
|
|
275
|
+
reflect: true
|
|
276
|
+
})], EFPanZoom.prototype, "y", void 0);
|
|
277
|
+
__decorate([property({
|
|
278
|
+
type: Number,
|
|
279
|
+
reflect: true
|
|
280
|
+
})], EFPanZoom.prototype, "scale", void 0);
|
|
281
|
+
__decorate([property({
|
|
282
|
+
type: Boolean,
|
|
283
|
+
attribute: "auto-fit"
|
|
284
|
+
})], EFPanZoom.prototype, "autoFit", void 0);
|
|
285
|
+
__decorate([provide({ context: panZoomTransformContext })], EFPanZoom.prototype, "panZoomTransform", void 0);
|
|
286
|
+
EFPanZoom = __decorate([customElement("ef-pan-zoom")], EFPanZoom);
|
|
287
|
+
|
|
288
|
+
//#endregion
|
|
289
|
+
export { EFPanZoom };
|
|
290
|
+
//# sourceMappingURL=EFPanZoom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EFPanZoom.js","names":["EFPanZoom","panZoom: Element | null"],"sources":["../../src/elements/EFPanZoom.ts"],"sourcesContent":["import { css, html, LitElement } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { provide } from \"@lit/context\";\nimport { panZoomTransformContext } from \"../gui/panZoomTransformContext.js\";\n\nexport interface PanZoomTransform {\n x: number;\n y: number;\n scale: number;\n}\n\n@customElement(\"ef-pan-zoom\")\nexport class EFPanZoom extends LitElement {\n static styles = [\n css`\n :host {\n display: block;\n overflow: hidden;\n position: relative;\n touch-action: none;\n }\n .content-wrapper {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n transform-origin: 0 0;\n }\n `,\n ];\n\n @property({ type: Number, reflect: true })\n x = 0;\n\n @property({ type: Number, reflect: true })\n y = 0;\n\n @property({ type: Number, reflect: true })\n scale = 1;\n\n /**\n * When true, automatically fits content to view on first render.\n * Centers content and scales it to fit within the container with padding.\n */\n @property({ type: Boolean, attribute: \"auto-fit\" })\n autoFit = false;\n\n @provide({ context: panZoomTransformContext })\n panZoomTransform: PanZoomTransform = { x: 0, y: 0, scale: 1 };\n\n private _isDragging = false;\n private _dragStartPointerPos: { x: number; y: number } | null = null;\n private _dragStartTransform: PanZoomTransform | null = null;\n private _capturedPointerId: number | null = null;\n\n /**\n * Document-level wheel handler in capture phase to prevent browser navigation.\n * This prevents back/forward navigation on two-finger swipe gestures.\n * We use capture phase to catch events before they bubble, but only prevent default\n * (not stop propagation) so the normal wheel handler can still process them.\n */\n private _onDocumentWheelCapture = (e: WheelEvent) => {\n // Check if event is over this panzoom element or its children\n let panZoom: Element | null = null;\n if (e.target instanceof Element) {\n panZoom = e.target.closest(\"ef-pan-zoom\");\n // Also check if target is an overlay sibling (selection overlay, etc.)\n // Overlays have pointer-events: none but can still be the event target\n if (!panZoom && e.target.closest(\"ef-canvas-selection-overlay\")) {\n // Event is over selection overlay - check if it's over this panzoom's area\n const rect = this.getBoundingClientRect();\n if (\n e.clientX >= rect.left &&\n e.clientX <= rect.right &&\n e.clientY >= rect.top &&\n e.clientY <= rect.bottom\n ) {\n panZoom = this;\n }\n }\n }\n if (panZoom === this) {\n // Prevent browser navigation gestures (back/forward on swipe)\n // Don't stop propagation - let the normal wheel handler process the event\n e.preventDefault();\n }\n };\n\n connectedCallback() {\n super.connectedCallback();\n // Add document-level capture listener to prevent browser navigation\n document.addEventListener(\"wheel\", this._onDocumentWheelCapture, {\n passive: false,\n capture: true,\n });\n // Add element-level event listeners\n this.addEventListener(\"wheel\", this._onWheel, { passive: false });\n this.addEventListener(\"pointerdown\", this._onPointerDown);\n this.addEventListener(\"pointermove\", this._onPointerMove);\n this.addEventListener(\"pointerup\", this._onPointerUp);\n this.addEventListener(\"pointercancel\", this._onPointerUp);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n // Remove document-level capture listener\n document.removeEventListener(\"wheel\", this._onDocumentWheelCapture, {\n capture: true,\n });\n // Remove element-level event listeners\n this.removeEventListener(\"wheel\", this._onWheel);\n this.removeEventListener(\"pointerdown\", this._onPointerDown);\n this.removeEventListener(\"pointermove\", this._onPointerMove);\n this.removeEventListener(\"pointerup\", this._onPointerUp);\n this.removeEventListener(\"pointercancel\", this._onPointerUp);\n // Clean up pointer capture if dragging\n if (this._isDragging && this._capturedPointerId !== null) {\n try {\n this.releasePointerCapture(this._capturedPointerId);\n } catch (err) {\n // Ignore pointer capture errors (e.g., in test environments)\n }\n }\n }\n\n private _updateTransform(updates: Partial<PanZoomTransform>) {\n const newTransform = {\n x: updates.x !== undefined ? updates.x : this.x,\n y: updates.y !== undefined ? updates.y : this.y,\n scale:\n updates.scale !== undefined\n ? Math.max(0.1, Math.min(5, updates.scale))\n : this.scale,\n };\n\n const changed =\n newTransform.x !== this.x ||\n newTransform.y !== this.y ||\n newTransform.scale !== this.scale;\n\n if (changed) {\n this.x = newTransform.x;\n this.y = newTransform.y;\n this.scale = newTransform.scale;\n\n // Update context for overlay components\n this.panZoomTransform = { ...newTransform };\n\n this.dispatchEvent(\n new CustomEvent<PanZoomTransform>(\"transform-changed\", {\n detail: { ...newTransform },\n bubbles: true,\n composed: true,\n }),\n );\n }\n }\n\n private _onPointerDown = (e: PointerEvent) => {\n if (e.button !== 0) return;\n\n this._isDragging = true;\n this._capturedPointerId = e.pointerId;\n this._dragStartPointerPos = { x: e.clientX, y: e.clientY };\n this._dragStartTransform = {\n x: this.x,\n y: this.y,\n scale: this.scale,\n };\n\n try {\n this.setPointerCapture(e.pointerId);\n } catch (err) {\n // Ignore pointer capture errors (e.g., in test environments)\n }\n };\n\n private _onPointerMove = (e: PointerEvent) => {\n if (\n !this._isDragging ||\n !this._dragStartPointerPos ||\n !this._dragStartTransform\n )\n return;\n\n const deltaX = e.clientX - this._dragStartPointerPos.x;\n const deltaY = e.clientY - this._dragStartPointerPos.y;\n\n this._updateTransform({\n x: this._dragStartTransform.x - deltaX,\n y: this._dragStartTransform.y - deltaY,\n });\n };\n\n private _onPointerUp = (e: PointerEvent) => {\n if (!this._isDragging) return;\n if (this._capturedPointerId !== null) {\n try {\n this.releasePointerCapture(e.pointerId);\n } catch (err) {\n // Ignore pointer capture errors (e.g., in test environments)\n }\n }\n\n this._isDragging = false;\n this._capturedPointerId = null;\n this._dragStartPointerPos = null;\n this._dragStartTransform = null;\n };\n\n private _onWheel = (e: WheelEvent) => {\n // Always prevent default to prevent browser navigation (back/forward on swipe)\n // This is critical for full-page app interfaces\n e.preventDefault();\n e.stopPropagation();\n\n const isZoom = e.metaKey || e.ctrlKey;\n\n if (isZoom) {\n const containerRect = this.getBoundingClientRect();\n const pointerX = e.clientX - containerRect.left;\n const pointerY = e.clientY - containerRect.top;\n\n const currentX = this.x;\n const currentY = this.y;\n const currentScale = this.scale;\n\n const canvasX = (pointerX - currentX) / currentScale;\n const canvasY = (pointerY - currentY) / currentScale;\n\n const delta = e.deltaY > 0 ? 0.95 : 1.05;\n const newScale = Math.max(0.1, Math.min(5, currentScale * delta));\n\n const newX = pointerX - canvasX * newScale;\n const newY = pointerY - canvasY * newScale;\n\n this._updateTransform({\n x: newX,\n y: newY,\n scale: newScale,\n });\n } else {\n const deltaX = -e.deltaX;\n const deltaY = -e.deltaY;\n\n this._updateTransform({\n x: this.x + deltaX,\n y: this.y + deltaY,\n });\n }\n };\n\n firstUpdated(changedProperties: Map<PropertyKey, unknown>) {\n super.firstUpdated(changedProperties);\n // Initialize context with current transform\n this.panZoomTransform = { x: this.x, y: this.y, scale: this.scale };\n\n // Auto-fit content if enabled (use RAF to ensure content is rendered)\n if (this.autoFit) {\n requestAnimationFrame(() => {\n this.fitToContent();\n });\n }\n }\n\n /**\n * Convert screen coordinates (e.g., mouse event clientX/clientY) to canvas coordinates.\n * This handles all pan/zoom transformations automatically.\n *\n * @param screenX - X coordinate in screen space (e.g., event.clientX)\n * @param screenY - Y coordinate in screen space (e.g., event.clientY)\n * @returns Object with x, y in canvas coordinate space\n *\n * @example\n * handleClick(e: MouseEvent) {\n * const canvasPos = panZoom.screenToCanvas(e.clientX, e.clientY);\n * console.log(`Clicked at canvas position: ${canvasPos.x}, ${canvasPos.y}`);\n * }\n */\n screenToCanvas(screenX: number, screenY: number): { x: number; y: number } {\n const rect = this.getBoundingClientRect();\n return {\n x: (screenX - rect.left - this.x) / this.scale,\n y: (screenY - rect.top - this.y) / this.scale,\n };\n }\n\n /**\n * Convert canvas coordinates to screen coordinates.\n * Useful for positioning overlays or tooltips relative to canvas elements.\n *\n * @param canvasX - X coordinate in canvas space\n * @param canvasY - Y coordinate in canvas space\n * @returns Object with x, y in screen coordinate space\n *\n * @example\n * const screenPos = panZoom.canvasToScreen(element.x, element.y);\n * tooltip.style.left = `${screenPos.x}px`;\n * tooltip.style.top = `${screenPos.y}px`;\n */\n canvasToScreen(canvasX: number, canvasY: number): { x: number; y: number } {\n const rect = this.getBoundingClientRect();\n return {\n x: rect.left + canvasX * this.scale + this.x,\n y: rect.top + canvasY * this.scale + this.y,\n };\n }\n\n /**\n * Reset the pan-zoom transform to its default values (x: 0, y: 0, scale: 1).\n * This method can be called programmatically to reset the view.\n *\n * @example\n * const panZoomRef = useRef(null);\n * <button onClick={() => panZoomRef.current.reset()}>Reset View</button>\n */\n reset(): void {\n this._updateTransform({ x: 0, y: 0, scale: 1 });\n }\n\n /**\n * Fit content to the container, centering it and scaling to fit.\n * Uses a padding factor to leave some margin around the content.\n *\n * @param padding - Padding factor (0-1), e.g., 0.1 = 10% padding on each side. Default: 0.05\n */\n fitToContent(padding = 0.05): void {\n const containerRect = this.getBoundingClientRect();\n if (containerRect.width === 0 || containerRect.height === 0) return;\n\n // Find the first child element to measure\n const contentWrapper = this.shadowRoot?.querySelector(\".content-wrapper\");\n const slottedContent = contentWrapper\n ?.querySelector(\"slot\")\n ?.assignedElements()[0] as HTMLElement | undefined;\n\n if (!slottedContent) return;\n\n // Get content dimensions\n const contentRect = slottedContent.getBoundingClientRect();\n const contentWidth = contentRect.width / this.scale;\n const contentHeight = contentRect.height / this.scale;\n\n if (contentWidth === 0 || contentHeight === 0) return;\n\n // Calculate available space with padding\n const availableWidth = containerRect.width * (1 - 2 * padding);\n const availableHeight = containerRect.height * (1 - 2 * padding);\n\n // Calculate scale to fit\n const scaleX = availableWidth / contentWidth;\n const scaleY = availableHeight / contentHeight;\n const newScale = Math.min(scaleX, scaleY, 1); // Don't scale up beyond 1:1\n\n // Calculate position to center\n const scaledWidth = contentWidth * newScale;\n const scaledHeight = contentHeight * newScale;\n const newX = (containerRect.width - scaledWidth) / 2;\n const newY = (containerRect.height - scaledHeight) / 2;\n\n this._updateTransform({\n x: newX,\n y: newY,\n scale: newScale,\n });\n }\n\n render() {\n return html`\n <div\n class=\"content-wrapper\"\n style=\"transform: translate(${this.x}px, ${this.y}px) scale(${this.scale});\"\n >\n <slot></slot>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
|
|
@@ -12,16 +12,17 @@ function EFSourceMixin(superClass, options) {
|
|
|
12
12
|
autoRun: false,
|
|
13
13
|
args: () => [this.src],
|
|
14
14
|
task: async ([src], { signal }) => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
let normalizedSrc = src.startsWith("/") ? src.slice(1) : src;
|
|
16
|
+
normalizedSrc = normalizedSrc.replace(/^\/+/, "");
|
|
17
|
+
const md5Path = `/api/v1/isobmff_files/local/md5?src=${encodeURIComponent(normalizedSrc)}`;
|
|
18
|
+
const response = await fetch(md5Path, { signal });
|
|
19
|
+
if (!response.ok) return;
|
|
20
|
+
return (await response.json()).md5 ?? void 0;
|
|
20
21
|
}
|
|
21
22
|
});
|
|
22
23
|
}
|
|
23
24
|
get apiHost() {
|
|
24
|
-
return
|
|
25
|
+
return this.closest("ef-configuration")?.apiHost ?? this.closest("ef-workbench")?.apiHost ?? this.closest("ef-preview")?.apiHost;
|
|
25
26
|
}
|
|
26
27
|
productionSrc() {
|
|
27
28
|
if (!this.md5SumLoader.value) throw new Error(`MD5 sum not available for ${this}. Cannot generate production URL`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EFSourceMixin.js","names":[],"sources":["../../src/elements/EFSourceMixin.ts"],"sourcesContent":["import { Task } from \"@lit/task\";\nimport type { LitElement } from \"lit\";\nimport { property } from \"lit/decorators/property.js\";\n\nexport declare class EFSourceMixinInterface {\n apiHost?: string;\n productionSrc(): string;\n src: string;\n}\n\ninterface EFSourceMixinOptions {\n assetType: string;\n}\ntype Constructor<T = {}> = new (...args: any[]) => T;\nexport function EFSourceMixin<T extends Constructor<LitElement>>(\n superClass: T,\n options: EFSourceMixinOptions,\n) {\n class EFSourceElement extends superClass {\n get apiHost() {\n const apiHost =\n this.closest(\"ef-configuration\")?.apiHost ??\n this.closest(\"ef-workbench\")?.apiHost ??\n this.closest(\"ef-preview\")?.apiHost;\n\n
|
|
1
|
+
{"version":3,"file":"EFSourceMixin.js","names":[],"sources":["../../src/elements/EFSourceMixin.ts"],"sourcesContent":["import { Task } from \"@lit/task\";\nimport type { LitElement } from \"lit\";\nimport { property } from \"lit/decorators/property.js\";\n\nexport declare class EFSourceMixinInterface {\n apiHost?: string;\n productionSrc(): string;\n src: string;\n}\n\ninterface EFSourceMixinOptions {\n assetType: string;\n}\ntype Constructor<T = {}> = new (...args: any[]) => T;\nexport function EFSourceMixin<T extends Constructor<LitElement>>(\n superClass: T,\n options: EFSourceMixinOptions,\n) {\n class EFSourceElement extends superClass {\n get apiHost() {\n const apiHost =\n this.closest(\"ef-configuration\")?.apiHost ??\n this.closest(\"ef-workbench\")?.apiHost ??\n this.closest(\"ef-preview\")?.apiHost;\n\n // Return undefined instead of defaulting to external URL\n // This allows components to use current origin when apiHost is not set\n return apiHost;\n }\n\n @property({ type: String })\n src = \"\";\n\n productionSrc() {\n if (!this.md5SumLoader.value) {\n throw new Error(\n `MD5 sum not available for ${this}. Cannot generate production URL`,\n );\n }\n\n if (!this.apiHost) {\n throw new Error(\n `apiHost not available for ${this}. Cannot generate production URL`,\n );\n }\n\n return `${this.apiHost}/api/v1/${options.assetType}/${this.md5SumLoader.value}`;\n }\n\n md5SumLoader = new Task(this, {\n autoRun: false,\n args: () => [this.src] as const,\n task: async ([src], { signal }) => {\n // Normalize the path: remove leading slash and any double slashes\n let normalizedSrc = src.startsWith(\"/\")\n ? src.slice(1)\n : src;\n normalizedSrc = normalizedSrc.replace(/^\\/+/, \"\");\n // Use production API format for local files\n const md5Path = `/api/v1/isobmff_files/local/md5?src=${encodeURIComponent(normalizedSrc)}`;\n const response = await fetch(md5Path, { signal });\n if (!response.ok) {\n return undefined;\n }\n const data = await response.json();\n return data.md5 ?? undefined;\n },\n });\n }\n\n return EFSourceElement as Constructor<EFSourceMixinInterface> & T;\n}\n"],"mappings":";;;;;AAcA,SAAgB,cACd,YACA,SACA;CACA,MAAM,wBAAwB,WAAW;;;cAajC;uBAkBS,IAAI,KAAK,MAAM;IAC5B,SAAS;IACT,YAAY,CAAC,KAAK,IAAI;IACtB,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa;KAEjC,IAAI,gBAAgB,IAAI,WAAW,IAAI,GACnC,IAAI,MAAM,EAAE,GACZ;AACJ,qBAAgB,cAAc,QAAQ,QAAQ,GAAG;KAEjD,MAAM,UAAU,uCAAuC,mBAAmB,cAAc;KACxF,MAAM,WAAW,MAAM,MAAM,SAAS,EAAE,QAAQ,CAAC;AACjD,SAAI,CAAC,SAAS,GACZ;AAGF,aADa,MAAM,SAAS,MAAM,EACtB,OAAO;;IAEtB,CAAC;;EAhDF,IAAI,UAAU;AAQZ,UANE,KAAK,QAAQ,mBAAmB,EAAE,WAClC,KAAK,QAAQ,eAAe,EAAE,WAC9B,KAAK,QAAQ,aAAa,EAAE;;EAUhC,gBAAgB;AACd,OAAI,CAAC,KAAK,aAAa,MACrB,OAAM,IAAI,MACR,6BAA6B,KAAK,kCACnC;AAGH,OAAI,CAAC,KAAK,QACR,OAAM,IAAI,MACR,6BAA6B,KAAK,kCACnC;AAGH,UAAO,GAAG,KAAK,QAAQ,UAAU,QAAQ,UAAU,GAAG,KAAK,aAAa;;;aAhBzE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAwC7B,QAAO"}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { ContextMixinInterface } from "../gui/ContextMixin.js";
|
|
2
2
|
import { Task } from "@lit/task";
|
|
3
|
-
import * as
|
|
3
|
+
import * as lit30 from "lit";
|
|
4
4
|
import { LitElement } from "lit";
|
|
5
|
-
import * as
|
|
6
|
-
import * as
|
|
5
|
+
import * as lit_html29 from "lit-html";
|
|
6
|
+
import * as lit_html_directives_ref3 from "lit-html/directives/ref";
|
|
7
7
|
|
|
8
8
|
//#region src/elements/EFSurface.d.ts
|
|
9
9
|
declare class EFSurface extends LitElement {
|
|
10
10
|
#private;
|
|
11
|
-
static styles:
|
|
12
|
-
canvasRef:
|
|
11
|
+
static styles: lit30.CSSResult[];
|
|
12
|
+
canvasRef: lit_html_directives_ref3.Ref<HTMLCanvasElement>;
|
|
13
13
|
targetElement: ContextMixinInterface | null;
|
|
14
14
|
target: string;
|
|
15
|
-
render():
|
|
15
|
+
render(): lit_html29.TemplateResult<1>;
|
|
16
16
|
get rootTimegroup(): any;
|
|
17
17
|
get currentTimeMs(): number;
|
|
18
18
|
get durationMs(): number;
|
|
@@ -15,15 +15,20 @@ let EFSurface = class EFSurface$1 extends LitElement {
|
|
|
15
15
|
this.frameTask = new Task(this, {
|
|
16
16
|
autoRun: false,
|
|
17
17
|
args: () => [this.targetElement],
|
|
18
|
-
task: async ([target]) => {
|
|
18
|
+
task: async ([target], { signal }) => {
|
|
19
|
+
signal?.throwIfAborted();
|
|
19
20
|
if (!target) return;
|
|
20
21
|
try {
|
|
21
22
|
const maybeTask = target.frameTask;
|
|
22
23
|
if (maybeTask && typeof maybeTask.run === "function") {
|
|
23
24
|
maybeTask.run();
|
|
24
25
|
await maybeTask.taskComplete;
|
|
26
|
+
signal?.throwIfAborted();
|
|
25
27
|
}
|
|
26
|
-
} catch (
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (error instanceof DOMException && error.name === "AbortError") throw error;
|
|
30
|
+
}
|
|
31
|
+
signal?.throwIfAborted();
|
|
27
32
|
this.copyFromTarget(target);
|
|
28
33
|
}
|
|
29
34
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EFSurface.js","names":["EFSurface","target: any","root: any"],"sources":["../../src/elements/EFSurface.ts"],"sourcesContent":["import { Task } from \"@lit/task\";\nimport { css, html, LitElement } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { createRef, ref } from \"lit/directives/ref.js\";\nimport type { ContextMixinInterface } from \"../gui/ContextMixin.ts\";\nimport { TargetController } from \"./TargetController.ts\";\n\n@customElement(\"ef-surface\")\nexport class EFSurface extends LitElement {\n static styles = [\n css`\n :host {\n display: block;\n position: relative;\n }\n canvas {\n all: inherit;\n width: 100%;\n height: 100%;\n display: block;\n }\n `,\n ];\n\n canvasRef = createRef<HTMLCanvasElement>();\n\n // @ts-expect-error controller is intentionally not referenced directly\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: Used for side effects\n #targetController: TargetController = new TargetController(this);\n\n @state()\n targetElement: ContextMixinInterface | null = null;\n\n @property({ type: String })\n target = \"\";\n\n render() {\n return html`<canvas ${ref(this.canvasRef)}></canvas>`;\n }\n\n // Provide minimal temporal-like properties so EFTimegroup can schedule us\n get rootTimegroup(): any {\n // Prefer the target element's root timegroup if available\n const target: any = this.targetElement;\n if (target && \"rootTimegroup\" in target) {\n return target.rootTimegroup;\n }\n // Fallback: nearest containing timegroup if any\n let root: any = this.closest(\"ef-timegroup\");\n while (root?.parentTimegroup) {\n root = root.parentTimegroup;\n }\n return root;\n }\n\n get currentTimeMs(): number {\n return this.rootTimegroup?.currentTimeMs ?? 0;\n }\n\n get durationMs(): number {\n return this.rootTimegroup?.durationMs ?? 0;\n }\n\n get startTimeMs(): number {\n return this.rootTimegroup?.startTimeMs ?? 0;\n }\n\n get endTimeMs(): number {\n return this.startTimeMs + this.durationMs;\n }\n\n /**\n * Minimal integration with EFTimegroup's frame scheduling:\n * - Waits for the target video element's frameTask to complete (ensuring it painted)\n * - Copies the target's canvas into this element's canvas\n */\n frameTask = new Task(this, {\n autoRun: false,\n args: () => [this.targetElement] as const,\n task: async ([target]) => {\n if (!target) return;\n\n // Ensure the target has painted its frame for this tick\n try {\n const maybeTask = (target as any).frameTask;\n if (maybeTask && typeof maybeTask.run === \"function\") {\n // Run (idempotent) and then wait for completion\n maybeTask.run();\n await maybeTask.taskComplete;\n }\n } catch (
|
|
1
|
+
{"version":3,"file":"EFSurface.js","names":["EFSurface","target: any","root: any"],"sources":["../../src/elements/EFSurface.ts"],"sourcesContent":["import { Task } from \"@lit/task\";\nimport { css, html, LitElement } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { createRef, ref } from \"lit/directives/ref.js\";\nimport type { ContextMixinInterface } from \"../gui/ContextMixin.ts\";\nimport { TargetController } from \"./TargetController.ts\";\n\n@customElement(\"ef-surface\")\nexport class EFSurface extends LitElement {\n static styles = [\n css`\n :host {\n display: block;\n position: relative;\n }\n canvas {\n all: inherit;\n width: 100%;\n height: 100%;\n display: block;\n }\n `,\n ];\n\n canvasRef = createRef<HTMLCanvasElement>();\n\n // @ts-expect-error controller is intentionally not referenced directly\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: Used for side effects\n #targetController: TargetController = new TargetController(this);\n\n @state()\n targetElement: ContextMixinInterface | null = null;\n\n @property({ type: String })\n target = \"\";\n\n render() {\n return html`<canvas ${ref(this.canvasRef)}></canvas>`;\n }\n\n // Provide minimal temporal-like properties so EFTimegroup can schedule us\n get rootTimegroup(): any {\n // Prefer the target element's root timegroup if available\n const target: any = this.targetElement;\n if (target && \"rootTimegroup\" in target) {\n return target.rootTimegroup;\n }\n // Fallback: nearest containing timegroup if any\n let root: any = this.closest(\"ef-timegroup\");\n while (root?.parentTimegroup) {\n root = root.parentTimegroup;\n }\n return root;\n }\n\n get currentTimeMs(): number {\n return this.rootTimegroup?.currentTimeMs ?? 0;\n }\n\n get durationMs(): number {\n return this.rootTimegroup?.durationMs ?? 0;\n }\n\n get startTimeMs(): number {\n return this.rootTimegroup?.startTimeMs ?? 0;\n }\n\n get endTimeMs(): number {\n return this.startTimeMs + this.durationMs;\n }\n\n /**\n * Minimal integration with EFTimegroup's frame scheduling:\n * - Waits for the target video element's frameTask to complete (ensuring it painted)\n * - Copies the target's canvas into this element's canvas\n */\n frameTask = new Task(this, {\n autoRun: false,\n args: () => [this.targetElement] as const,\n task: async ([target], { signal }) => {\n // Check abort before starting\n signal?.throwIfAborted();\n \n if (!target) return;\n\n // Ensure the target has painted its frame for this tick\n try {\n const maybeTask = (target as any).frameTask;\n if (maybeTask && typeof maybeTask.run === \"function\") {\n // Run (idempotent) and then wait for completion\n maybeTask.run();\n await maybeTask.taskComplete;\n // Check abort after async operation\n signal?.throwIfAborted();\n }\n } catch (error) {\n // Re-throw AbortError to propagate cancellation\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw error;\n }\n // Best-effort; continue to attempt copy for other errors\n }\n\n // Check abort before copy operation\n signal?.throwIfAborted();\n \n this.copyFromTarget(target);\n },\n });\n\n protected updated(): void {\n if (this.targetElement) {\n this.copyFromTarget(this.targetElement);\n }\n }\n\n // Target resolution is handled by TargetController. No implicit discovery.\n\n private getSourceCanvas(from: Element): HTMLCanvasElement | null {\n const anyEl = from as any;\n if (\"canvasElement\" in anyEl) {\n return anyEl.canvasElement ?? null;\n }\n const sr = (from as HTMLElement).shadowRoot;\n if (sr) {\n const c = sr.querySelector(\"canvas\");\n return (c as HTMLCanvasElement) ?? null;\n }\n return null;\n }\n\n private copyFromTarget(target: Element) {\n const dst = this.canvasRef.value;\n const src = this.getSourceCanvas(target);\n if (!dst || !src) return;\n if (!src.width || !src.height) return;\n\n // Match source pixel size for a faithful mirror; layout scaling is handled by CSS\n if (dst.width !== src.width || dst.height !== src.height) {\n dst.width = src.width;\n dst.height = src.height;\n }\n\n const ctx = dst.getContext(\"2d\");\n if (!ctx) return;\n ctx.drawImage(src, 0, 0, dst.width, dst.height);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-surface\": EFSurface;\n }\n}\n"],"mappings":";;;;;;;;AAQO,sBAAMA,oBAAkB,WAAW;;;mBAgB5B,WAA8B;uBAOI;gBAGrC;mBA0CG,IAAI,KAAK,MAAM;GACzB,SAAS;GACT,YAAY,CAAC,KAAK,cAAc;GAChC,MAAM,OAAO,CAAC,SAAS,EAAE,aAAa;AAEpC,YAAQ,gBAAgB;AAExB,QAAI,CAAC,OAAQ;AAGb,QAAI;KACF,MAAM,YAAa,OAAe;AAClC,SAAI,aAAa,OAAO,UAAU,QAAQ,YAAY;AAEpD,gBAAU,KAAK;AACf,YAAM,UAAU;AAEhB,cAAQ,gBAAgB;;aAEnB,OAAO;AAEd,SAAI,iBAAiB,gBAAgB,MAAM,SAAS,aAClD,OAAM;;AAMV,YAAQ,gBAAgB;AAExB,SAAK,eAAe,OAAO;;GAE9B,CAAC;;;gBAnGc,CACd,GAAG;;;;;;;;;;;MAYJ;;CAMD,oBAAsC,IAAI,iBAAiB,KAAK;CAQhE,SAAS;AACP,SAAO,IAAI,WAAW,IAAI,KAAK,UAAU,CAAC;;CAI5C,IAAI,gBAAqB;EAEvB,MAAMC,SAAc,KAAK;AACzB,MAAI,UAAU,mBAAmB,OAC/B,QAAO,OAAO;EAGhB,IAAIC,OAAY,KAAK,QAAQ,eAAe;AAC5C,SAAO,MAAM,gBACX,QAAO,KAAK;AAEd,SAAO;;CAGT,IAAI,gBAAwB;AAC1B,SAAO,KAAK,eAAe,iBAAiB;;CAG9C,IAAI,aAAqB;AACvB,SAAO,KAAK,eAAe,cAAc;;CAG3C,IAAI,cAAsB;AACxB,SAAO,KAAK,eAAe,eAAe;;CAG5C,IAAI,YAAoB;AACtB,SAAO,KAAK,cAAc,KAAK;;CA0CjC,AAAU,UAAgB;AACxB,MAAI,KAAK,cACP,MAAK,eAAe,KAAK,cAAc;;CAM3C,AAAQ,gBAAgB,MAAyC;EAC/D,MAAM,QAAQ;AACd,MAAI,mBAAmB,MACrB,QAAO,MAAM,iBAAiB;EAEhC,MAAM,KAAM,KAAqB;AACjC,MAAI,GAEF,QADU,GAAG,cAAc,SAAS,IACD;AAErC,SAAO;;CAGT,AAAQ,eAAe,QAAiB;EACtC,MAAM,MAAM,KAAK,UAAU;EAC3B,MAAM,MAAM,KAAK,gBAAgB,OAAO;AACxC,MAAI,CAAC,OAAO,CAAC,IAAK;AAClB,MAAI,CAAC,IAAI,SAAS,CAAC,IAAI,OAAQ;AAG/B,MAAI,IAAI,UAAU,IAAI,SAAS,IAAI,WAAW,IAAI,QAAQ;AACxD,OAAI,QAAQ,IAAI;AAChB,OAAI,SAAS,IAAI;;EAGnB,MAAM,MAAM,IAAI,WAAW,KAAK;AAChC,MAAI,CAAC,IAAK;AACV,MAAI,UAAU,KAAK,GAAG,GAAG,IAAI,OAAO,IAAI,OAAO;;;YAnHhD,OAAO;YAGP,SAAS,EAAE,MAAM,QAAQ,CAAC;wBA1B5B,cAAc,aAAa"}
|
|
@@ -196,6 +196,7 @@ declare class TemporalMixinInterface {
|
|
|
196
196
|
didBecomeChild(): void;
|
|
197
197
|
updateComplete: Promise<boolean>;
|
|
198
198
|
}
|
|
199
|
+
declare const isEFTemporal: (obj: any) => obj is TemporalMixinInterface;
|
|
199
200
|
//#endregion
|
|
200
|
-
export { TemporalMixinInterface };
|
|
201
|
+
export { TemporalMixinInterface, isEFTemporal };
|
|
201
202
|
//# sourceMappingURL=EFTemporal.d.ts.map
|