@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,135 @@
|
|
|
1
|
+
//#region src/preview/RenderProfiler.ts
|
|
2
|
+
/**
|
|
3
|
+
* Profiling utility for render operations.
|
|
4
|
+
* Centralizes timing accumulation and logging to keep business logic clean.
|
|
5
|
+
*/
|
|
6
|
+
/** Interval between profiling log outputs (ms) */
|
|
7
|
+
const DEFAULT_LOG_INTERVAL_MS = 2e3;
|
|
8
|
+
/** Interval for periodic frame logging (every N frames) */
|
|
9
|
+
const DEFAULT_FRAME_LOG_INTERVAL = 60;
|
|
10
|
+
/**
|
|
11
|
+
* Profiler for render operations.
|
|
12
|
+
* Accumulates timing data and provides structured logging.
|
|
13
|
+
*/
|
|
14
|
+
var RenderProfiler = class {
|
|
15
|
+
constructor() {
|
|
16
|
+
this._renderCount = 0;
|
|
17
|
+
this._lastLogTime = 0;
|
|
18
|
+
this._timingLoggedAt = 0;
|
|
19
|
+
this._timings = {
|
|
20
|
+
setup: 0,
|
|
21
|
+
draw: 0,
|
|
22
|
+
downsample: 0,
|
|
23
|
+
canvasEncode: 0,
|
|
24
|
+
inline: 0,
|
|
25
|
+
serialize: 0,
|
|
26
|
+
base64: 0,
|
|
27
|
+
imageLoad: 0,
|
|
28
|
+
restore: 0
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Reset all timing data.
|
|
33
|
+
*/
|
|
34
|
+
reset() {
|
|
35
|
+
this._renderCount = 0;
|
|
36
|
+
this._lastLogTime = 0;
|
|
37
|
+
this._timingLoggedAt = 0;
|
|
38
|
+
for (const key of Object.keys(this._timings)) this._timings[key] = 0;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get current render count.
|
|
42
|
+
*/
|
|
43
|
+
get renderCount() {
|
|
44
|
+
return this._renderCount;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Increment render count.
|
|
48
|
+
*/
|
|
49
|
+
incrementRenderCount() {
|
|
50
|
+
this._renderCount++;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Add time to a specific phase.
|
|
54
|
+
*/
|
|
55
|
+
addTime(phase, ms) {
|
|
56
|
+
this._timings[phase] += ms;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Time a synchronous operation and add to the specified phase.
|
|
60
|
+
*/
|
|
61
|
+
time(phase, fn) {
|
|
62
|
+
const start = performance.now();
|
|
63
|
+
const result = fn();
|
|
64
|
+
this._timings[phase] += performance.now() - start;
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Time an async operation and add to the specified phase.
|
|
69
|
+
*/
|
|
70
|
+
async timeAsync(phase, fn) {
|
|
71
|
+
const start = performance.now();
|
|
72
|
+
const result = await fn();
|
|
73
|
+
this._timings[phase] += performance.now() - start;
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Check if enough time has passed since last log (for time-based logging).
|
|
78
|
+
*/
|
|
79
|
+
shouldLogByTime(intervalMs = DEFAULT_LOG_INTERVAL_MS) {
|
|
80
|
+
const now = performance.now();
|
|
81
|
+
if (now - this._lastLogTime > intervalMs) {
|
|
82
|
+
this._lastLogTime = now;
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if enough frames have passed since last log (for frame-based logging).
|
|
89
|
+
*/
|
|
90
|
+
shouldLogByFrameCount(interval = DEFAULT_FRAME_LOG_INTERVAL) {
|
|
91
|
+
if (this._renderCount - this._timingLoggedAt >= interval) {
|
|
92
|
+
this._timingLoggedAt = this._renderCount;
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Check if this is an early render (for initial debug logging).
|
|
99
|
+
*/
|
|
100
|
+
isEarlyRender(threshold = 2) {
|
|
101
|
+
return this._renderCount < threshold;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Get timing summary string.
|
|
105
|
+
*/
|
|
106
|
+
summary() {
|
|
107
|
+
const t = this._timings;
|
|
108
|
+
const parts = [];
|
|
109
|
+
if (t.setup > 0) parts.push(`setup=${t.setup.toFixed(0)}ms`);
|
|
110
|
+
if (t.draw > 0) parts.push(`draw=${t.draw.toFixed(0)}ms`);
|
|
111
|
+
if (t.downsample > 0) parts.push(`downsample=${t.downsample.toFixed(0)}ms`);
|
|
112
|
+
if (t.canvasEncode > 0) parts.push(`canvasEncode=${t.canvasEncode.toFixed(0)}ms`);
|
|
113
|
+
if (t.inline > 0) parts.push(`inline=${t.inline.toFixed(0)}ms`);
|
|
114
|
+
if (t.serialize > 0) parts.push(`serialize=${t.serialize.toFixed(0)}ms`);
|
|
115
|
+
if (t.base64 > 0) parts.push(`base64=${t.base64.toFixed(0)}ms`);
|
|
116
|
+
if (t.imageLoad > 0) parts.push(`imageLoad=${t.imageLoad.toFixed(0)}ms`);
|
|
117
|
+
if (t.restore > 0) parts.push(`restore=${t.restore.toFixed(0)}ms`);
|
|
118
|
+
return parts.join(", ");
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get raw timings object.
|
|
122
|
+
*/
|
|
123
|
+
getTimings() {
|
|
124
|
+
return { ...this._timings };
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Default shared profiler instance.
|
|
129
|
+
* Can be replaced with a custom instance for testing.
|
|
130
|
+
*/
|
|
131
|
+
const defaultProfiler = new RenderProfiler();
|
|
132
|
+
|
|
133
|
+
//#endregion
|
|
134
|
+
export { defaultProfiler };
|
|
135
|
+
//# sourceMappingURL=RenderProfiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RenderProfiler.js","names":["parts: string[]"],"sources":["../../src/preview/RenderProfiler.ts"],"sourcesContent":["/**\n * Profiling utility for render operations.\n * Centralizes timing accumulation and logging to keep business logic clean.\n */\n\n/** Interval between profiling log outputs (ms) */\nconst DEFAULT_LOG_INTERVAL_MS = 2000;\n\n/** Interval for periodic frame logging (every N frames) */\nconst DEFAULT_FRAME_LOG_INTERVAL = 60;\n\n/**\n * Phases tracked during rendering.\n */\nexport interface RenderTimings {\n setup: number;\n draw: number;\n downsample: number;\n canvasEncode: number;\n inline: number;\n serialize: number;\n base64: number;\n imageLoad: number;\n restore: number;\n}\n\n/**\n * Profiler for render operations.\n * Accumulates timing data and provides structured logging.\n */\nexport class RenderProfiler {\n private _renderCount = 0;\n private _lastLogTime = 0;\n private _timingLoggedAt = 0;\n \n private _timings: RenderTimings = {\n setup: 0,\n draw: 0,\n downsample: 0,\n canvasEncode: 0,\n inline: 0,\n serialize: 0,\n base64: 0,\n imageLoad: 0,\n restore: 0,\n };\n\n /**\n * Reset all timing data.\n */\n reset(): void {\n this._renderCount = 0;\n this._lastLogTime = 0;\n this._timingLoggedAt = 0;\n \n for (const key of Object.keys(this._timings) as (keyof RenderTimings)[]) {\n this._timings[key] = 0;\n }\n }\n\n /**\n * Get current render count.\n */\n get renderCount(): number {\n return this._renderCount;\n }\n\n /**\n * Increment render count.\n */\n incrementRenderCount(): void {\n this._renderCount++;\n }\n\n /**\n * Add time to a specific phase.\n */\n addTime(phase: keyof RenderTimings, ms: number): void {\n this._timings[phase] += ms;\n }\n\n /**\n * Time a synchronous operation and add to the specified phase.\n */\n time<T>(phase: keyof RenderTimings, fn: () => T): T {\n const start = performance.now();\n const result = fn();\n this._timings[phase] += performance.now() - start;\n return result;\n }\n\n /**\n * Time an async operation and add to the specified phase.\n */\n async timeAsync<T>(phase: keyof RenderTimings, fn: () => Promise<T>): Promise<T> {\n const start = performance.now();\n const result = await fn();\n this._timings[phase] += performance.now() - start;\n return result;\n }\n\n /**\n * Check if enough time has passed since last log (for time-based logging).\n */\n shouldLogByTime(intervalMs: number = DEFAULT_LOG_INTERVAL_MS): boolean {\n const now = performance.now();\n if (now - this._lastLogTime > intervalMs) {\n this._lastLogTime = now;\n return true;\n }\n return false;\n }\n\n /**\n * Check if enough frames have passed since last log (for frame-based logging).\n */\n shouldLogByFrameCount(interval: number = DEFAULT_FRAME_LOG_INTERVAL): boolean {\n if (this._renderCount - this._timingLoggedAt >= interval) {\n this._timingLoggedAt = this._renderCount;\n return true;\n }\n return false;\n }\n\n /**\n * Check if this is an early render (for initial debug logging).\n */\n isEarlyRender(threshold: number = 2): boolean {\n return this._renderCount < threshold;\n }\n\n /**\n * Get timing summary string.\n */\n summary(): string {\n const t = this._timings;\n const parts: string[] = [];\n \n if (t.setup > 0) parts.push(`setup=${t.setup.toFixed(0)}ms`);\n if (t.draw > 0) parts.push(`draw=${t.draw.toFixed(0)}ms`);\n if (t.downsample > 0) parts.push(`downsample=${t.downsample.toFixed(0)}ms`);\n if (t.canvasEncode > 0) parts.push(`canvasEncode=${t.canvasEncode.toFixed(0)}ms`);\n if (t.inline > 0) parts.push(`inline=${t.inline.toFixed(0)}ms`);\n if (t.serialize > 0) parts.push(`serialize=${t.serialize.toFixed(0)}ms`);\n if (t.base64 > 0) parts.push(`base64=${t.base64.toFixed(0)}ms`);\n if (t.imageLoad > 0) parts.push(`imageLoad=${t.imageLoad.toFixed(0)}ms`);\n if (t.restore > 0) parts.push(`restore=${t.restore.toFixed(0)}ms`);\n \n return parts.join(', ');\n }\n\n /**\n * Get raw timings object.\n */\n getTimings(): Readonly<RenderTimings> {\n return { ...this._timings };\n }\n}\n\n/**\n * Default shared profiler instance.\n * Can be replaced with a custom instance for testing.\n */\nexport const defaultProfiler = new RenderProfiler();\n"],"mappings":";;;;;;AAMA,MAAM,0BAA0B;;AAGhC,MAAM,6BAA6B;;;;;AAqBnC,IAAa,iBAAb,MAA4B;;sBACH;sBACA;yBACG;kBAEQ;GAChC,OAAO;GACP,MAAM;GACN,YAAY;GACZ,cAAc;GACd,QAAQ;GACR,WAAW;GACX,QAAQ;GACR,WAAW;GACX,SAAS;GACV;;;;;CAKD,QAAc;AACZ,OAAK,eAAe;AACpB,OAAK,eAAe;AACpB,OAAK,kBAAkB;AAEvB,OAAK,MAAM,OAAO,OAAO,KAAK,KAAK,SAAS,CAC1C,MAAK,SAAS,OAAO;;;;;CAOzB,IAAI,cAAsB;AACxB,SAAO,KAAK;;;;;CAMd,uBAA6B;AAC3B,OAAK;;;;;CAMP,QAAQ,OAA4B,IAAkB;AACpD,OAAK,SAAS,UAAU;;;;;CAM1B,KAAQ,OAA4B,IAAgB;EAClD,MAAM,QAAQ,YAAY,KAAK;EAC/B,MAAM,SAAS,IAAI;AACnB,OAAK,SAAS,UAAU,YAAY,KAAK,GAAG;AAC5C,SAAO;;;;;CAMT,MAAM,UAAa,OAA4B,IAAkC;EAC/E,MAAM,QAAQ,YAAY,KAAK;EAC/B,MAAM,SAAS,MAAM,IAAI;AACzB,OAAK,SAAS,UAAU,YAAY,KAAK,GAAG;AAC5C,SAAO;;;;;CAMT,gBAAgB,aAAqB,yBAAkC;EACrE,MAAM,MAAM,YAAY,KAAK;AAC7B,MAAI,MAAM,KAAK,eAAe,YAAY;AACxC,QAAK,eAAe;AACpB,UAAO;;AAET,SAAO;;;;;CAMT,sBAAsB,WAAmB,4BAAqC;AAC5E,MAAI,KAAK,eAAe,KAAK,mBAAmB,UAAU;AACxD,QAAK,kBAAkB,KAAK;AAC5B,UAAO;;AAET,SAAO;;;;;CAMT,cAAc,YAAoB,GAAY;AAC5C,SAAO,KAAK,eAAe;;;;;CAM7B,UAAkB;EAChB,MAAM,IAAI,KAAK;EACf,MAAMA,QAAkB,EAAE;AAE1B,MAAI,EAAE,QAAQ,EAAG,OAAM,KAAK,SAAS,EAAE,MAAM,QAAQ,EAAE,CAAC,IAAI;AAC5D,MAAI,EAAE,OAAO,EAAG,OAAM,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,CAAC,IAAI;AACzD,MAAI,EAAE,aAAa,EAAG,OAAM,KAAK,cAAc,EAAE,WAAW,QAAQ,EAAE,CAAC,IAAI;AAC3E,MAAI,EAAE,eAAe,EAAG,OAAM,KAAK,gBAAgB,EAAE,aAAa,QAAQ,EAAE,CAAC,IAAI;AACjF,MAAI,EAAE,SAAS,EAAG,OAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,EAAE,CAAC,IAAI;AAC/D,MAAI,EAAE,YAAY,EAAG,OAAM,KAAK,aAAa,EAAE,UAAU,QAAQ,EAAE,CAAC,IAAI;AACxE,MAAI,EAAE,SAAS,EAAG,OAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,EAAE,CAAC,IAAI;AAC/D,MAAI,EAAE,YAAY,EAAG,OAAM,KAAK,aAAa,EAAE,UAAU,QAAQ,EAAE,CAAC,IAAI;AACxE,MAAI,EAAE,UAAU,EAAG,OAAM,KAAK,WAAW,EAAE,QAAQ,QAAQ,EAAE,CAAC,IAAI;AAElE,SAAO,MAAM,KAAK,KAAK;;;;;CAMzB,aAAsC;AACpC,SAAO,EAAE,GAAG,KAAK,UAAU;;;;;;;AAQ/B,MAAa,kBAAkB,IAAI,gBAAgB"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
//#region src/preview/previewSettings.ts
|
|
2
|
+
const STORAGE_KEY_PRESENTATION_MODE = "ef-preview-presentation-mode";
|
|
3
|
+
const STORAGE_KEY_RENDER_MODE = "ef-preview-render-mode";
|
|
4
|
+
const STORAGE_KEY_RESOLUTION_SCALE = "ef-preview-resolution-scale";
|
|
5
|
+
const STORAGE_KEY_SHOW_STATS = "ef-preview-show-stats";
|
|
6
|
+
/**
|
|
7
|
+
* Cached detection result for native HTML-in-Canvas API availability.
|
|
8
|
+
* This is separate from the user preference - it detects browser capability.
|
|
9
|
+
*/
|
|
10
|
+
let _nativeApiAvailable = null;
|
|
11
|
+
/**
|
|
12
|
+
* Detect if the native HTML-in-Canvas API (drawElementImage) is available in this browser.
|
|
13
|
+
* This checks browser capability, not user preference.
|
|
14
|
+
*
|
|
15
|
+
* The API is available in Chrome Canary with chrome://flags/#canvas-draw-element
|
|
16
|
+
* @see https://github.com/WICG/html-in-canvas
|
|
17
|
+
*/
|
|
18
|
+
function isNativeCanvasApiAvailable() {
|
|
19
|
+
if (_nativeApiAvailable === null) {
|
|
20
|
+
const ctx = document.createElement("canvas").getContext("2d");
|
|
21
|
+
_nativeApiAvailable = ctx !== null && "drawElementImage" in ctx;
|
|
22
|
+
}
|
|
23
|
+
return _nativeApiAvailable;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get the current preview presentation mode.
|
|
27
|
+
* Defaults to "original" if not set.
|
|
28
|
+
*/
|
|
29
|
+
function getPreviewPresentationMode() {
|
|
30
|
+
try {
|
|
31
|
+
const stored = localStorage.getItem(STORAGE_KEY_PRESENTATION_MODE);
|
|
32
|
+
if (stored === "original" || stored === "computed" || stored === "canvas") return stored;
|
|
33
|
+
return "original";
|
|
34
|
+
} catch {
|
|
35
|
+
return "original";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Set the preview presentation mode.
|
|
40
|
+
* Persists to localStorage and dispatches a change event.
|
|
41
|
+
*/
|
|
42
|
+
function setPreviewPresentationMode(mode) {
|
|
43
|
+
try {
|
|
44
|
+
localStorage.setItem(STORAGE_KEY_PRESENTATION_MODE, mode);
|
|
45
|
+
} catch {}
|
|
46
|
+
window.dispatchEvent(new CustomEvent("ef-preview-settings-changed", { detail: { presentationMode: mode } }));
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get the current render mode for HTML-to-canvas capture.
|
|
50
|
+
* Defaults to "native" if available, otherwise "foreignObject".
|
|
51
|
+
*/
|
|
52
|
+
function getRenderMode() {
|
|
53
|
+
try {
|
|
54
|
+
const stored = localStorage.getItem(STORAGE_KEY_RENDER_MODE);
|
|
55
|
+
if (stored === "foreignObject" || stored === "native") return stored;
|
|
56
|
+
return isNativeCanvasApiAvailable() ? "native" : "foreignObject";
|
|
57
|
+
} catch {
|
|
58
|
+
return isNativeCanvasApiAvailable() ? "native" : "foreignObject";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Set the render mode for HTML-to-canvas capture.
|
|
63
|
+
* Persists to localStorage and dispatches a change event.
|
|
64
|
+
*/
|
|
65
|
+
function setRenderMode(mode) {
|
|
66
|
+
try {
|
|
67
|
+
localStorage.setItem(STORAGE_KEY_RENDER_MODE, mode);
|
|
68
|
+
} catch {}
|
|
69
|
+
window.dispatchEvent(new CustomEvent("ef-preview-settings-changed", { detail: { renderMode: mode } }));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Valid numeric resolution scale values.
|
|
73
|
+
*/
|
|
74
|
+
const VALID_NUMERIC_SCALES = [
|
|
75
|
+
1,
|
|
76
|
+
.75,
|
|
77
|
+
.5,
|
|
78
|
+
.25
|
|
79
|
+
];
|
|
80
|
+
/**
|
|
81
|
+
* Get the current preview resolution scale.
|
|
82
|
+
* Defaults to 1 (full resolution) if not set.
|
|
83
|
+
*/
|
|
84
|
+
function getPreviewResolutionScale() {
|
|
85
|
+
try {
|
|
86
|
+
const stored = localStorage.getItem(STORAGE_KEY_RESOLUTION_SCALE);
|
|
87
|
+
if (stored !== null) {
|
|
88
|
+
if (stored === "auto") return "auto";
|
|
89
|
+
const parsed = parseFloat(stored);
|
|
90
|
+
if (VALID_NUMERIC_SCALES.includes(parsed)) return parsed;
|
|
91
|
+
}
|
|
92
|
+
return 1;
|
|
93
|
+
} catch {
|
|
94
|
+
return 1;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Set the preview resolution scale.
|
|
99
|
+
* Persists to localStorage and dispatches a change event.
|
|
100
|
+
*/
|
|
101
|
+
function setPreviewResolutionScale(scale) {
|
|
102
|
+
try {
|
|
103
|
+
localStorage.setItem(STORAGE_KEY_RESOLUTION_SCALE, String(scale));
|
|
104
|
+
} catch {}
|
|
105
|
+
window.dispatchEvent(new CustomEvent("ef-preview-settings-changed", { detail: { resolutionScale: scale } }));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get whether performance stats should be shown.
|
|
109
|
+
* Defaults to false (stats hidden by default).
|
|
110
|
+
*/
|
|
111
|
+
function getShowStats() {
|
|
112
|
+
try {
|
|
113
|
+
return localStorage.getItem(STORAGE_KEY_SHOW_STATS) === "true";
|
|
114
|
+
} catch {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Set whether performance stats should be shown.
|
|
120
|
+
* Persists to localStorage and dispatches a change event.
|
|
121
|
+
*/
|
|
122
|
+
function setShowStats(enabled) {
|
|
123
|
+
try {
|
|
124
|
+
localStorage.setItem(STORAGE_KEY_SHOW_STATS, String(enabled));
|
|
125
|
+
} catch {}
|
|
126
|
+
window.dispatchEvent(new CustomEvent("ef-preview-settings-changed", { detail: { showStats: enabled } }));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
//#endregion
|
|
130
|
+
export { getPreviewPresentationMode, getPreviewResolutionScale, getRenderMode, getShowStats, isNativeCanvasApiAvailable, setPreviewPresentationMode, setPreviewResolutionScale, setRenderMode, setShowStats };
|
|
131
|
+
//# sourceMappingURL=previewSettings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"previewSettings.js","names":["_nativeApiAvailable: boolean | null","VALID_NUMERIC_SCALES: number[]"],"sources":["../../src/preview/previewSettings.ts"],"sourcesContent":["/**\n * Preview settings module with localStorage persistence.\n * Manages configuration for the preview rendering system.\n */\n\nconst STORAGE_KEY_NATIVE_CANVAS_API = \"ef-preview-native-canvas-api-enabled\";\nconst STORAGE_KEY_PRESENTATION_MODE = \"ef-preview-presentation-mode\";\nconst STORAGE_KEY_RENDER_MODE = \"ef-preview-render-mode\";\nconst STORAGE_KEY_RESOLUTION_SCALE = \"ef-preview-resolution-scale\";\nconst STORAGE_KEY_SHOW_STATS = \"ef-preview-show-stats\";\n\n/**\n * Render mode for HTML-to-canvas capture operations.\n * - \"foreignObject\": SVG foreignObject serialization (fallback, works everywhere)\n * - \"native\": Chrome's experimental drawElementImage API (fastest when available)\n */\nexport type RenderMode = \"foreignObject\" | \"native\";\n\n/**\n * Preview resolution scale factor.\n * Controls how much to reduce the preview render resolution for better performance.\n * - 1: Full resolution (default)\n * - 0.75: 3/4 resolution\n * - 0.5: Half resolution\n * - 0.25: Quarter resolution\n * - \"auto\": Adaptive resolution that scales down during motion to prevent dropped frames,\n * and renders at full resolution when at rest\n */\nexport type PreviewResolutionScale = 1 | 0.75 | 0.5 | 0.25 | \"auto\";\n\n/**\n * Preview presentation mode determines how content is rendered in the workbench.\n * - \"clone\": Show a clone with computed styles applied (alias for \"computed\")\n * - \"dom\": Show the original DOM content directly (alias for \"original\")\n * - \"original\": Show the original DOM content directly\n * - \"computed\": Show a clone with computed styles applied\n * - \"canvas\": Render to canvas using the active rendering path\n */\nexport type PreviewPresentationMode = \"original\" | \"computed\" | \"canvas\" | \"clone\" | \"dom\";\n\n/**\n * Cached detection result for native HTML-in-Canvas API availability.\n * This is separate from the user preference - it detects browser capability.\n */\nlet _nativeApiAvailable: boolean | null = null;\n\n/**\n * Detect if the native HTML-in-Canvas API (drawElementImage) is available in this browser.\n * This checks browser capability, not user preference.\n * \n * The API is available in Chrome Canary with chrome://flags/#canvas-draw-element\n * @see https://github.com/WICG/html-in-canvas\n */\nexport function isNativeCanvasApiAvailable(): boolean {\n if (_nativeApiAvailable === null) {\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n _nativeApiAvailable = ctx !== null && \"drawElementImage\" in ctx;\n }\n return _nativeApiAvailable;\n}\n\n/**\n * Check if the native Canvas API is enabled by the user.\n * Returns true only if:\n * 1. The API is available in the browser\n * 2. The user has not explicitly disabled it\n * \n * Default is enabled when available (opt-out model).\n */\nexport function isNativeCanvasApiEnabled(): boolean {\n if (!isNativeCanvasApiAvailable()) {\n return false;\n }\n \n try {\n const stored = localStorage.getItem(STORAGE_KEY_NATIVE_CANVAS_API);\n // Default to true (enabled) when available, unless explicitly disabled\n if (stored === null) {\n return true;\n }\n return stored === \"true\";\n } catch {\n // localStorage not available (e.g., private browsing)\n return true;\n }\n}\n\n/**\n * Set whether the native Canvas API should be used (when available).\n * Persists to localStorage and dispatches a change event.\n */\nexport function setNativeCanvasApiEnabled(enabled: boolean): void {\n try {\n localStorage.setItem(STORAGE_KEY_NATIVE_CANVAS_API, String(enabled));\n } catch {\n // localStorage not available\n }\n \n // Dispatch event so components can react to the change\n window.dispatchEvent(new CustomEvent(\"ef-preview-settings-changed\", {\n detail: { nativeCanvasApiEnabled: enabled }\n }));\n}\n\n/**\n * Get the current raw user preference (ignoring availability).\n * Returns null if no preference is set.\n */\nexport function getNativeCanvasApiPreference(): boolean | null {\n try {\n const stored = localStorage.getItem(STORAGE_KEY_NATIVE_CANVAS_API);\n if (stored === null) {\n return null;\n }\n return stored === \"true\";\n } catch {\n return null;\n }\n}\n\n/**\n * Subscribe to preview settings changes.\n * @returns Unsubscribe function\n */\nexport function onPreviewSettingsChanged(\n callback: (detail: PreviewSettingsChangedDetail) => void\n): () => void {\n const handler = (event: Event) => {\n callback((event as CustomEvent).detail);\n };\n window.addEventListener(\"ef-preview-settings-changed\", handler);\n return () => window.removeEventListener(\"ef-preview-settings-changed\", handler);\n}\n\n/**\n * Detail object for preview settings change events.\n */\nexport interface PreviewSettingsChangedDetail {\n nativeCanvasApiEnabled?: boolean;\n presentationMode?: PreviewPresentationMode;\n renderMode?: RenderMode;\n resolutionScale?: PreviewResolutionScale;\n showStats?: boolean;\n}\n\n/**\n * Get the current preview presentation mode.\n * Defaults to \"original\" if not set.\n */\nexport function getPreviewPresentationMode(): PreviewPresentationMode {\n try {\n const stored = localStorage.getItem(STORAGE_KEY_PRESENTATION_MODE);\n if (stored === \"original\" || stored === \"computed\" || stored === \"canvas\") {\n return stored;\n }\n return \"original\";\n } catch {\n return \"original\";\n }\n}\n\n/**\n * Set the preview presentation mode.\n * Persists to localStorage and dispatches a change event.\n */\nexport function setPreviewPresentationMode(mode: PreviewPresentationMode): void {\n try {\n localStorage.setItem(STORAGE_KEY_PRESENTATION_MODE, mode);\n } catch {\n // localStorage not available\n }\n \n // Dispatch event so components can react to the change\n window.dispatchEvent(new CustomEvent(\"ef-preview-settings-changed\", {\n detail: { presentationMode: mode }\n }));\n}\n\n/**\n * Get the current render mode for HTML-to-canvas capture.\n * Defaults to \"native\" if available, otherwise \"foreignObject\".\n */\nexport function getRenderMode(): RenderMode {\n try {\n const stored = localStorage.getItem(STORAGE_KEY_RENDER_MODE);\n if (stored === \"foreignObject\" || stored === \"native\") {\n return stored;\n }\n // Default: prefer native if available, otherwise foreignObject\n return isNativeCanvasApiAvailable() ? \"native\" : \"foreignObject\";\n } catch {\n return isNativeCanvasApiAvailable() ? \"native\" : \"foreignObject\";\n }\n}\n\n/**\n * Set the render mode for HTML-to-canvas capture.\n * Persists to localStorage and dispatches a change event.\n */\nexport function setRenderMode(mode: RenderMode): void {\n try {\n localStorage.setItem(STORAGE_KEY_RENDER_MODE, mode);\n } catch {\n // localStorage not available\n }\n \n // Dispatch event so components can react to the change\n window.dispatchEvent(new CustomEvent(\"ef-preview-settings-changed\", {\n detail: { renderMode: mode }\n }));\n}\n\n/**\n * Valid numeric resolution scale values.\n */\nconst VALID_NUMERIC_SCALES: number[] = [1, 0.75, 0.5, 0.25];\n\n/**\n * Get the current preview resolution scale.\n * Defaults to 1 (full resolution) if not set.\n */\nexport function getPreviewResolutionScale(): PreviewResolutionScale {\n try {\n const stored = localStorage.getItem(STORAGE_KEY_RESOLUTION_SCALE);\n if (stored !== null) {\n // Check for \"auto\" string first\n if (stored === \"auto\") {\n return \"auto\";\n }\n // Then check numeric values\n const parsed = parseFloat(stored);\n if (VALID_NUMERIC_SCALES.includes(parsed)) {\n return parsed as PreviewResolutionScale;\n }\n }\n return 1;\n } catch {\n return 1;\n }\n}\n\n/**\n * Set the preview resolution scale.\n * Persists to localStorage and dispatches a change event.\n */\nexport function setPreviewResolutionScale(scale: PreviewResolutionScale): void {\n try {\n localStorage.setItem(STORAGE_KEY_RESOLUTION_SCALE, String(scale));\n } catch {\n // localStorage not available\n }\n \n // Dispatch event so components can react to the change\n window.dispatchEvent(new CustomEvent(\"ef-preview-settings-changed\", {\n detail: { resolutionScale: scale }\n }));\n}\n\n/**\n * Get whether performance stats should be shown.\n * Defaults to false (stats hidden by default).\n */\nexport function getShowStats(): boolean {\n try {\n const stored = localStorage.getItem(STORAGE_KEY_SHOW_STATS);\n return stored === \"true\";\n } catch {\n return false;\n }\n}\n\n/**\n * Set whether performance stats should be shown.\n * Persists to localStorage and dispatches a change event.\n */\nexport function setShowStats(enabled: boolean): void {\n try {\n localStorage.setItem(STORAGE_KEY_SHOW_STATS, String(enabled));\n } catch {\n // localStorage not available\n }\n \n // Dispatch event so components can react to the change\n window.dispatchEvent(new CustomEvent(\"ef-preview-settings-changed\", {\n detail: { showStats: enabled }\n }));\n}\n\n"],"mappings":";AAMA,MAAM,gCAAgC;AACtC,MAAM,0BAA0B;AAChC,MAAM,+BAA+B;AACrC,MAAM,yBAAyB;;;;;AAmC/B,IAAIA,sBAAsC;;;;;;;;AAS1C,SAAgB,6BAAsC;AACpD,KAAI,wBAAwB,MAAM;EAEhC,MAAM,MADS,SAAS,cAAc,SAAS,CAC5B,WAAW,KAAK;AACnC,wBAAsB,QAAQ,QAAQ,sBAAsB;;AAE9D,QAAO;;;;;;AA2FT,SAAgB,6BAAsD;AACpE,KAAI;EACF,MAAM,SAAS,aAAa,QAAQ,8BAA8B;AAClE,MAAI,WAAW,cAAc,WAAW,cAAc,WAAW,SAC/D,QAAO;AAET,SAAO;SACD;AACN,SAAO;;;;;;;AAQX,SAAgB,2BAA2B,MAAqC;AAC9E,KAAI;AACF,eAAa,QAAQ,+BAA+B,KAAK;SACnD;AAKR,QAAO,cAAc,IAAI,YAAY,+BAA+B,EAClE,QAAQ,EAAE,kBAAkB,MAAM,EACnC,CAAC,CAAC;;;;;;AAOL,SAAgB,gBAA4B;AAC1C,KAAI;EACF,MAAM,SAAS,aAAa,QAAQ,wBAAwB;AAC5D,MAAI,WAAW,mBAAmB,WAAW,SAC3C,QAAO;AAGT,SAAO,4BAA4B,GAAG,WAAW;SAC3C;AACN,SAAO,4BAA4B,GAAG,WAAW;;;;;;;AAQrD,SAAgB,cAAc,MAAwB;AACpD,KAAI;AACF,eAAa,QAAQ,yBAAyB,KAAK;SAC7C;AAKR,QAAO,cAAc,IAAI,YAAY,+BAA+B,EAClE,QAAQ,EAAE,YAAY,MAAM,EAC7B,CAAC,CAAC;;;;;AAML,MAAMC,uBAAiC;CAAC;CAAG;CAAM;CAAK;CAAK;;;;;AAM3D,SAAgB,4BAAoD;AAClE,KAAI;EACF,MAAM,SAAS,aAAa,QAAQ,6BAA6B;AACjE,MAAI,WAAW,MAAM;AAEnB,OAAI,WAAW,OACb,QAAO;GAGT,MAAM,SAAS,WAAW,OAAO;AACjC,OAAI,qBAAqB,SAAS,OAAO,CACvC,QAAO;;AAGX,SAAO;SACD;AACN,SAAO;;;;;;;AAQX,SAAgB,0BAA0B,OAAqC;AAC7E,KAAI;AACF,eAAa,QAAQ,8BAA8B,OAAO,MAAM,CAAC;SAC3D;AAKR,QAAO,cAAc,IAAI,YAAY,+BAA+B,EAClE,QAAQ,EAAE,iBAAiB,OAAO,EACnC,CAAC,CAAC;;;;;;AAOL,SAAgB,eAAwB;AACtC,KAAI;AAEF,SADe,aAAa,QAAQ,uBAAuB,KACzC;SACZ;AACN,SAAO;;;;;;;AAQX,SAAgB,aAAa,SAAwB;AACnD,KAAI;AACF,eAAa,QAAQ,wBAAwB,OAAO,QAAQ,CAAC;SACvD;AAKR,QAAO,cAAc,IAAI,YAAY,+BAA+B,EAClE,QAAQ,EAAE,WAAW,SAAS,EAC/B,CAAC,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
//#region src/preview/previewTypes.ts
|
|
2
|
+
/**
|
|
3
|
+
* Type guard to check if an element has temporal properties.
|
|
4
|
+
*/
|
|
5
|
+
function isTemporal(el) {
|
|
6
|
+
return "startTimeMs" in el && "endTimeMs" in el;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Get temporal bounds for an element, treating invalid ranges as unbounded.
|
|
10
|
+
* Invalid range (end <= start) means element hasn't computed its duration yet.
|
|
11
|
+
*/
|
|
12
|
+
function getTemporalBounds(el) {
|
|
13
|
+
if (!isTemporal(el)) return {
|
|
14
|
+
startMs: -Infinity,
|
|
15
|
+
endMs: Infinity
|
|
16
|
+
};
|
|
17
|
+
const startMs = el.startTimeMs ?? -Infinity;
|
|
18
|
+
const endMs = el.endTimeMs ?? Infinity;
|
|
19
|
+
if (endMs <= startMs) return {
|
|
20
|
+
startMs: -Infinity,
|
|
21
|
+
endMs: Infinity
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
startMs,
|
|
25
|
+
endMs
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Check if an element is temporally visible at the given time.
|
|
30
|
+
*/
|
|
31
|
+
function isVisibleAtTime(element, timeMs) {
|
|
32
|
+
const { startMs, endMs } = getTemporalBounds(element);
|
|
33
|
+
return timeMs >= startMs && timeMs <= endMs;
|
|
34
|
+
}
|
|
35
|
+
/** Default timegroup dimensions when not measurable */
|
|
36
|
+
const DEFAULT_WIDTH = 1920;
|
|
37
|
+
const DEFAULT_HEIGHT = 1080;
|
|
38
|
+
/** Default scale for thumbnail captures */
|
|
39
|
+
const DEFAULT_THUMBNAIL_SCALE = .25;
|
|
40
|
+
/** Default timeout for blocking content readiness mode (ms) */
|
|
41
|
+
const DEFAULT_BLOCKING_TIMEOUT_MS = 5e3;
|
|
42
|
+
/** JPEG quality settings for different canvas scales */
|
|
43
|
+
const JPEG_QUALITY_HIGH = .95;
|
|
44
|
+
const JPEG_QUALITY_MEDIUM = .85;
|
|
45
|
+
/**
|
|
46
|
+
* Create a preview container with standard styling.
|
|
47
|
+
* Consolidates the repeated container creation pattern across preview functions.
|
|
48
|
+
*/
|
|
49
|
+
function createPreviewContainer(options) {
|
|
50
|
+
const { width, height, background = "#000", position = "relative" } = options;
|
|
51
|
+
const container = document.createElement("div");
|
|
52
|
+
container.style.cssText = `
|
|
53
|
+
width: ${width}px;
|
|
54
|
+
height: ${height}px;
|
|
55
|
+
position: ${position};
|
|
56
|
+
overflow: hidden;
|
|
57
|
+
background: ${background};
|
|
58
|
+
`;
|
|
59
|
+
return container;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
export { DEFAULT_BLOCKING_TIMEOUT_MS, DEFAULT_HEIGHT, DEFAULT_THUMBNAIL_SCALE, DEFAULT_WIDTH, JPEG_QUALITY_HIGH, JPEG_QUALITY_MEDIUM, createPreviewContainer, getTemporalBounds, isTemporal, isVisibleAtTime };
|
|
64
|
+
//# sourceMappingURL=previewTypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"previewTypes.js","names":[],"sources":["../../src/preview/previewTypes.ts"],"sourcesContent":["/**\n * Shared types and constants for preview rendering.\n * \n * Consolidates duplicate definitions from renderTimegroupToCanvas.ts and\n * renderTimegroupPreview.ts into a single source of truth.\n */\n\n// ============================================================================\n// Temporal Types\n// ============================================================================\n\n/**\n * Element with temporal properties (startTimeMs, endTimeMs).\n * Used for temporal visibility checks during preview rendering.\n */\nexport interface TemporalElement extends Element {\n startTimeMs?: number;\n endTimeMs?: number;\n src?: string;\n}\n\n/**\n * Type guard to check if an element has temporal properties.\n */\nexport function isTemporal(el: Element): el is TemporalElement {\n return \"startTimeMs\" in el && \"endTimeMs\" in el;\n}\n\n/**\n * Get temporal bounds for an element, treating invalid ranges as unbounded.\n * Invalid range (end <= start) means element hasn't computed its duration yet.\n */\nexport function getTemporalBounds(el: Element): { startMs: number; endMs: number } {\n if (!isTemporal(el)) return { startMs: -Infinity, endMs: Infinity };\n\n const startMs = el.startTimeMs ?? -Infinity;\n const endMs = el.endTimeMs ?? Infinity;\n\n // Invalid range (end <= start) means element hasn't computed its duration yet\n if (endMs <= startMs) return { startMs: -Infinity, endMs: Infinity };\n\n return { startMs, endMs };\n}\n\n/**\n * Check if an element is temporally visible at the given time.\n */\nexport function isVisibleAtTime(element: Element, timeMs: number): boolean {\n const { startMs, endMs } = getTemporalBounds(element);\n return timeMs >= startMs && timeMs <= endMs;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** Default timegroup dimensions when not measurable */\nexport const DEFAULT_WIDTH = 1920;\nexport const DEFAULT_HEIGHT = 1080;\n\n/** Default scale for thumbnail captures */\nexport const DEFAULT_THUMBNAIL_SCALE = 0.25;\n\n/** Default timeout for blocking content readiness mode (ms) */\nexport const DEFAULT_BLOCKING_TIMEOUT_MS = 5000;\n\n/** JPEG quality settings for different canvas scales */\nexport const JPEG_QUALITY_HIGH = 0.95;\nexport const JPEG_QUALITY_MEDIUM = 0.85;\n\n// ============================================================================\n// Container Creation\n// ============================================================================\n\n/**\n * Options for creating a preview container.\n */\nexport interface PreviewContainerOptions {\n width: number;\n height: number;\n background?: string;\n position?: \"relative\" | \"absolute\" | \"fixed\";\n}\n\n/**\n * Create a preview container with standard styling.\n * Consolidates the repeated container creation pattern across preview functions.\n */\nexport function createPreviewContainer(options: PreviewContainerOptions): HTMLDivElement {\n const { width, height, background = \"#000\", position = \"relative\" } = options;\n\n const container = document.createElement(\"div\");\n container.style.cssText = `\n width: ${width}px;\n height: ${height}px;\n position: ${position};\n overflow: hidden;\n background: ${background};\n `;\n return container;\n}\n\n// ============================================================================\n// Style Injection\n// ============================================================================\n\n/**\n * Inject document styles into a container for foreignObject rendering.\n * SVG foreignObject needs all CSS rules inlined since it can't access\n * the document's stylesheets.\n */\nexport function injectDocumentStyles(\n container: HTMLElement,\n collectStyles: () => string,\n): HTMLStyleElement {\n const styleEl = document.createElement(\"style\");\n styleEl.textContent = collectStyles();\n container.appendChild(styleEl);\n return styleEl;\n}\n"],"mappings":";;;;AAwBA,SAAgB,WAAW,IAAoC;AAC7D,QAAO,iBAAiB,MAAM,eAAe;;;;;;AAO/C,SAAgB,kBAAkB,IAAiD;AACjF,KAAI,CAAC,WAAW,GAAG,CAAE,QAAO;EAAE,SAAS;EAAW,OAAO;EAAU;CAEnE,MAAM,UAAU,GAAG,eAAe;CAClC,MAAM,QAAQ,GAAG,aAAa;AAG9B,KAAI,SAAS,QAAS,QAAO;EAAE,SAAS;EAAW,OAAO;EAAU;AAEpE,QAAO;EAAE;EAAS;EAAO;;;;;AAM3B,SAAgB,gBAAgB,SAAkB,QAAyB;CACzE,MAAM,EAAE,SAAS,UAAU,kBAAkB,QAAQ;AACrD,QAAO,UAAU,WAAW,UAAU;;;AAQxC,MAAa,gBAAgB;AAC7B,MAAa,iBAAiB;;AAG9B,MAAa,0BAA0B;;AAGvC,MAAa,8BAA8B;;AAG3C,MAAa,oBAAoB;AACjC,MAAa,sBAAsB;;;;;AAoBnC,SAAgB,uBAAuB,SAAkD;CACvF,MAAM,EAAE,OAAO,QAAQ,aAAa,QAAQ,WAAW,eAAe;CAEtE,MAAM,YAAY,SAAS,cAAc,MAAM;AAC/C,WAAU,MAAM,UAAU;aACf,MAAM;cACL,OAAO;gBACL,SAAS;;kBAEP,WAAW;;AAE3B,QAAO"}
|