@editframe/elements 0.33.0-beta → 0.34.5-beta
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.js +5 -3
- package/dist/EF_FRAMEGEN.js.map +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.94.0 → _@oxc-project_runtime@0.95.0}/helpers/decorate.js +1 -1
- package/dist/canvas/EFCanvas.d.ts +7 -4
- package/dist/canvas/EFCanvas.js +1 -1
- package/dist/canvas/EFCanvasItem.d.ts +4 -4
- package/dist/canvas/EFCanvasItem.js +1 -1
- package/dist/canvas/overlays/SelectionOverlay.d.ts +95 -0
- package/dist/canvas/overlays/SelectionOverlay.js +1 -1
- package/dist/canvas/selection/SelectionController.js +7 -11
- package/dist/canvas/selection/SelectionController.js.map +1 -1
- package/dist/elements/EFAudio.d.ts +25 -7
- package/dist/elements/EFAudio.js +31 -61
- package/dist/elements/EFAudio.js.map +1 -1
- package/dist/elements/EFCaptions.d.ts +65 -52
- package/dist/elements/EFCaptions.js +186 -400
- package/dist/elements/EFCaptions.js.map +1 -1
- package/dist/elements/EFImage.d.ts +34 -6
- package/dist/elements/EFImage.js +114 -79
- package/dist/elements/EFImage.js.map +1 -1
- package/dist/elements/EFMedia/AssetIdMediaEngine.js +17 -17
- package/dist/elements/EFMedia/AssetIdMediaEngine.js.map +1 -1
- package/dist/elements/EFMedia/AssetMediaEngine.js +41 -25
- package/dist/elements/EFMedia/AssetMediaEngine.js.map +1 -1
- package/dist/elements/EFMedia/BaseMediaEngine.js +4 -4
- package/dist/elements/EFMedia/BaseMediaEngine.js.map +1 -1
- package/dist/elements/EFMedia/BufferedSeekingInput.js +1 -1
- package/dist/elements/EFMedia/BufferedSeekingInput.js.map +1 -1
- package/dist/elements/EFMedia/JitMediaEngine.js +31 -17
- package/dist/elements/EFMedia/JitMediaEngine.js.map +1 -1
- package/dist/elements/EFMedia/shared/AudioSpanUtils.js +3 -3
- package/dist/elements/EFMedia/shared/AudioSpanUtils.js.map +1 -1
- package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js +17 -9
- package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js.map +1 -1
- package/dist/elements/EFMedia.d.ts +66 -20
- package/dist/elements/EFMedia.js +412 -30
- package/dist/elements/EFMedia.js.map +1 -1
- package/dist/elements/EFPanZoom.d.ts +4 -4
- package/dist/elements/EFPanZoom.js +1 -1
- package/dist/elements/EFSourceMixin.js +43 -15
- package/dist/elements/EFSourceMixin.js.map +1 -1
- package/dist/elements/EFSurface.d.ts +23 -10
- package/dist/elements/EFSurface.js +64 -22
- package/dist/elements/EFSurface.js.map +1 -1
- package/dist/elements/EFTemporal.d.ts +8 -2
- package/dist/elements/EFTemporal.js +42 -31
- package/dist/elements/EFTemporal.js.map +1 -1
- package/dist/elements/EFText.d.ts +5 -4
- package/dist/elements/EFText.js +11 -2
- package/dist/elements/EFText.js.map +1 -1
- package/dist/elements/EFTextSegment.d.ts +4 -4
- package/dist/elements/EFTextSegment.js +1 -1
- package/dist/elements/EFThumbnailStrip.d.ts +4 -4
- package/dist/elements/EFThumbnailStrip.js +1 -1
- package/dist/elements/EFTimegroup.d.ts +22 -8
- package/dist/elements/EFTimegroup.js +203 -115
- package/dist/elements/EFTimegroup.js.map +1 -1
- package/dist/elements/EFVideo.d.ts +57 -20
- package/dist/elements/EFVideo.js +324 -72
- package/dist/elements/EFVideo.js.map +1 -1
- package/dist/elements/EFWaveform.d.ts +33 -7
- package/dist/elements/EFWaveform.js +103 -59
- package/dist/elements/EFWaveform.js.map +1 -1
- package/dist/elements/renderTemporalAudio.js +14 -3
- package/dist/elements/renderTemporalAudio.js.map +1 -1
- package/dist/getRenderInfo.d.ts +2 -2
- package/dist/gui/ContextMixin.js +1 -1
- package/dist/gui/Controllable.d.ts +2 -0
- package/dist/gui/EFActiveRootTemporal.d.ts +4 -4
- package/dist/gui/EFActiveRootTemporal.js +1 -1
- package/dist/gui/EFConfiguration.d.ts +4 -4
- package/dist/gui/EFConfiguration.js +1 -1
- package/dist/gui/EFControls.d.ts +2 -2
- package/dist/gui/EFControls.js +1 -1
- package/dist/gui/EFDial.d.ts +4 -4
- package/dist/gui/EFDial.js +1 -1
- package/dist/gui/EFFilmstrip.d.ts +3 -2
- package/dist/gui/EFFilmstrip.js +1 -1
- package/dist/gui/EFFitScale.js +1 -1
- package/dist/gui/EFFocusOverlay.d.ts +4 -4
- package/dist/gui/EFFocusOverlay.js +1 -1
- package/dist/gui/EFOverlayItem.d.ts +4 -4
- package/dist/gui/EFOverlayItem.js +1 -1
- package/dist/gui/EFOverlayLayer.d.ts +4 -4
- package/dist/gui/EFOverlayLayer.js +1 -1
- package/dist/gui/EFPause.d.ts +4 -4
- package/dist/gui/EFPause.js +1 -1
- package/dist/gui/EFPlay.d.ts +4 -4
- package/dist/gui/EFPlay.js +1 -1
- package/dist/gui/EFPreview.d.ts +4 -4
- package/dist/gui/EFPreview.js +1 -1
- package/dist/gui/EFResizableBox.d.ts +4 -4
- package/dist/gui/EFResizableBox.js +1 -1
- package/dist/gui/EFScrubber.d.ts +4 -4
- package/dist/gui/EFScrubber.js +1 -1
- package/dist/gui/EFTimeDisplay.d.ts +4 -4
- package/dist/gui/EFTimeDisplay.js +1 -1
- package/dist/gui/EFTimelineRuler.d.ts +4 -4
- package/dist/gui/EFTimelineRuler.js +1 -1
- package/dist/gui/EFToggleLoop.d.ts +4 -4
- package/dist/gui/EFToggleLoop.js +1 -1
- package/dist/gui/EFTogglePlay.d.ts +4 -4
- package/dist/gui/EFTogglePlay.js +1 -1
- package/dist/gui/EFTransformHandles.d.ts +4 -4
- package/dist/gui/EFTransformHandles.js +1 -1
- package/dist/gui/EFWorkbench.d.ts +5 -4
- package/dist/gui/EFWorkbench.js +1 -1
- package/dist/gui/PlaybackController.d.ts +10 -2
- package/dist/gui/PlaybackController.js +52 -30
- 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/TargetOrContextMixin.js +1 -1
- package/dist/gui/hierarchy/EFHierarchy.d.ts +4 -4
- package/dist/gui/hierarchy/EFHierarchy.js +1 -1
- package/dist/gui/hierarchy/EFHierarchyItem.d.ts +3 -3
- package/dist/gui/hierarchy/EFHierarchyItem.js +1 -1
- package/dist/gui/timeline/EFTimeline.d.ts +6 -2
- package/dist/gui/timeline/EFTimeline.js +1 -1
- package/dist/gui/timeline/EFTimelineRow.d.ts +57 -0
- package/dist/gui/timeline/EFTimelineRow.js +1 -1
- package/dist/gui/timeline/TrimHandles.d.ts +4 -4
- package/dist/gui/timeline/TrimHandles.js +1 -1
- package/dist/gui/timeline/tracks/AudioTrack.d.ts +2 -0
- package/dist/gui/timeline/tracks/AudioTrack.js +1 -1
- package/dist/gui/timeline/tracks/CaptionsTrack.d.ts +58 -0
- package/dist/gui/timeline/tracks/CaptionsTrack.js +1 -1
- package/dist/gui/timeline/tracks/HTMLTrack.d.ts +13 -0
- package/dist/gui/timeline/tracks/HTMLTrack.js +1 -1
- package/dist/gui/timeline/tracks/ImageTrack.d.ts +14 -0
- package/dist/gui/timeline/tracks/ImageTrack.js +1 -1
- package/dist/gui/timeline/tracks/TextTrack.d.ts +26 -0
- package/dist/gui/timeline/tracks/TextTrack.js +1 -1
- package/dist/gui/timeline/tracks/TimegroupTrack.d.ts +47 -0
- package/dist/gui/timeline/tracks/TimegroupTrack.js +4 -12
- package/dist/gui/timeline/tracks/TimegroupTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/TrackItem.d.ts +81 -0
- package/dist/gui/timeline/tracks/TrackItem.js +1 -1
- package/dist/gui/timeline/tracks/VideoTrack.d.ts +25 -0
- package/dist/gui/timeline/tracks/VideoTrack.js +1 -1
- package/dist/gui/timeline/tracks/WaveformTrack.d.ts +14 -0
- package/dist/gui/timeline/tracks/WaveformTrack.js +1 -1
- package/dist/gui/timeline/tracks/ensureTrackItemInit.d.ts +1 -0
- package/dist/gui/timeline/tracks/preloadTracks.d.ts +9 -0
- package/dist/gui/tree/EFTree.d.ts +5 -4
- package/dist/gui/tree/EFTree.js +1 -1
- package/dist/gui/tree/EFTreeItem.d.ts +4 -4
- package/dist/gui/tree/EFTreeItem.js +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/preview/AdaptiveResolutionTracker.js +6 -14
- package/dist/preview/AdaptiveResolutionTracker.js.map +1 -1
- package/dist/preview/FrameController.d.ts +123 -0
- package/dist/preview/FrameController.js +216 -0
- package/dist/preview/FrameController.js.map +1 -0
- package/dist/preview/RenderContext.d.ts +1 -0
- package/dist/preview/RenderContext.js +193 -0
- package/dist/preview/RenderContext.js.map +1 -0
- package/dist/preview/encoding/canvasEncoder.js +166 -0
- package/dist/preview/encoding/canvasEncoder.js.map +1 -0
- package/dist/preview/encoding/mainThreadEncoder.js +39 -0
- package/dist/preview/encoding/mainThreadEncoder.js.map +1 -0
- package/dist/preview/encoding/types.d.ts +1 -0
- package/dist/preview/encoding/workerEncoder.js +58 -0
- package/dist/preview/encoding/workerEncoder.js.map +1 -0
- package/dist/preview/logger.js +41 -0
- package/dist/preview/logger.js.map +1 -0
- package/dist/preview/previewTypes.js +11 -10
- package/dist/preview/previewTypes.js.map +1 -1
- package/dist/preview/renderTimegroupPreview.js +259 -236
- package/dist/preview/renderTimegroupPreview.js.map +1 -1
- package/dist/preview/renderTimegroupToCanvas.d.ts +5 -0
- package/dist/preview/renderTimegroupToCanvas.js +99 -489
- package/dist/preview/renderTimegroupToCanvas.js.map +1 -1
- package/dist/preview/renderTimegroupToVideo.d.ts +1 -0
- package/dist/preview/renderTimegroupToVideo.js +80 -22
- package/dist/preview/renderTimegroupToVideo.js.map +1 -1
- package/dist/preview/renderers.js.map +1 -1
- package/dist/preview/rendering/inlineImages.js +56 -0
- package/dist/preview/rendering/inlineImages.js.map +1 -0
- package/dist/preview/rendering/renderToImage.d.ts +1 -0
- package/dist/preview/rendering/renderToImage.js +120 -0
- package/dist/preview/rendering/renderToImage.js.map +1 -0
- package/dist/preview/rendering/renderToImageForeignObject.js +135 -0
- package/dist/preview/rendering/renderToImageForeignObject.js.map +1 -0
- package/dist/preview/rendering/renderToImageNative.d.ts +1 -0
- package/dist/preview/rendering/renderToImageNative.js +129 -0
- package/dist/preview/rendering/renderToImageNative.js.map +1 -0
- package/dist/preview/rendering/svgSerializer.js +43 -0
- package/dist/preview/rendering/svgSerializer.js.map +1 -0
- package/dist/preview/rendering/types.d.ts +2 -0
- package/dist/preview/statsTrackingStrategy.js +3 -1
- package/dist/preview/statsTrackingStrategy.js.map +1 -1
- package/dist/preview/workers/WorkerPool.js +8 -57
- package/dist/preview/workers/WorkerPool.js.map +1 -1
- package/dist/render/EFRenderAPI.d.ts +35 -0
- package/dist/render/EFRenderAPI.js +1 -0
- package/dist/render/EFRenderAPI.js.map +1 -1
- package/dist/sandbox/PlaybackControls.d.ts +1 -0
- package/dist/sandbox/ScenarioRunner.d.ts +1 -0
- package/dist/sandbox/defineSandbox.d.ts +1 -0
- package/dist/sandbox/index.d.ts +3 -0
- package/dist/style.css +3 -0
- package/dist/transcoding/types/index.d.ts +6 -3
- package/package.json +2 -3
- package/test/EFVideo.framegen.browsertest.ts +8 -1
- package/test/profilingPlugin.ts +1 -3
- package/test/setup.ts +23 -1
- package/dist/EF_INTERACTIVE.js +0 -7
- package/dist/EF_INTERACTIVE.js.map +0 -1
- package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +0 -50
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.d.ts +0 -12
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +0 -104
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js.map +0 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +0 -168
- package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js.map +0 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js +0 -46
- package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js.map +0 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +0 -49
- package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js.map +0 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +0 -30
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js.map +0 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +0 -49
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js.map +0 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +0 -47
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js.map +0 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +0 -140
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js.map +0 -1
- package/dist/elements/EFMedia/shared/BufferUtils.d.ts +0 -13
- package/dist/elements/EFMedia/shared/BufferUtils.js +0 -86
- package/dist/elements/EFMedia/shared/BufferUtils.js.map +0 -1
- package/dist/elements/EFMedia/shared/MediaTaskUtils.d.ts +0 -17
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js +0 -90
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js.map +0 -1
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js +0 -80
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js.map +0 -1
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.js +0 -49
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.js.map +0 -1
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js +0 -58
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js.map +0 -1
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js +0 -71
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js.map +0 -1
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.js +0 -52
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.js.map +0 -1
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js +0 -50
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js.map +0 -1
- package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js +0 -109
- package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js.map +0 -1
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.d.ts +0 -12
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +0 -97
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js.map +0 -1
- package/dist/elements/SampleBuffer.d.ts +0 -19
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderTimegroupPreview.js","names":["SYNC_PROPERTIES_SET: Set<string>","_baselineSnapshot: Map<Element, Map<string, string>> | null","CSS_SAFE_DEFAULT_VALUES: Record<string, string | string[]>","legacyPairs: ElementPair[]","node: CloneNode","node","clone","syncState: SyncState","srcMap: StylePropertyMapReadOnly","cs: CSSStyleDeclaration","cloneTextNode: Text | null","cloneTextNode","violations: string[]","rules: string[]"],"sources":["../../src/preview/renderTimegroupPreview.ts"],"sourcesContent":["/**\n * Elements to skip entirely when building the preview.\n */\nconst SKIP_TAGS = new Set([\n \"EF-AUDIO\",\n \"EF-THUMBNAIL-STRIP\",\n \"EF-FILMSTRIP\",\n \"EF-TIMELINE\",\n \"EF-WORKBENCH\",\n \"SCRIPT\",\n \"STYLE\",\n]);\n\n/**\n * All CSS properties to sync (camelCase for style[] access).\n */\nconst SYNC_PROPERTIES = [\n \"display\", \"visibility\", \"opacity\",\n \"position\", \"top\", \"right\", \"bottom\", \"left\", \"zIndex\",\n \"width\", \"height\", \"minWidth\", \"minHeight\", \"maxWidth\", \"maxHeight\",\n \"flex\", \"flexFlow\", \"justifyContent\", \"alignItems\", \"alignContent\", \"alignSelf\", \"gap\",\n \"gridTemplate\", \"gridColumn\", \"gridRow\", \"gridArea\",\n \"margin\", \"padding\", \"boxSizing\",\n \"border\", \"borderTop\", \"borderRight\", \"borderBottom\", \"borderLeft\", \"borderRadius\",\n \"background\", \"color\", \"boxShadow\", \"filter\", \"backdropFilter\", \"clipPath\",\n \"font\", \"textAlign\", \"textDecoration\", \"textTransform\",\n \"letterSpacing\", \"whiteSpace\", \"textOverflow\", \"lineHeight\",\n \"transform\", \"transformOrigin\", \"transformStyle\",\n \"perspective\", \"perspectiveOrigin\", \"backfaceVisibility\",\n \"cursor\", \"pointerEvents\", \"userSelect\", \"overflow\",\n] as const;\n\n/** Set version of SYNC_PROPERTIES for O(1) validation lookups */\nconst SYNC_PROPERTIES_SET: Set<string> = new Set(SYNC_PROPERTIES);\n\n/**\n * Validation state for property change detection.\n * Reset via resetPropertyValidation() at start of export.\n */\nlet _propertyValidationEnabled = false;\nlet _validationFrameCount = 0;\nlet _baselineSnapshot: Map<Element, Map<string, string>> | null = null;\n\nexport function enablePropertyValidation(): void {\n _propertyValidationEnabled = true;\n _validationFrameCount = 0;\n _baselineSnapshot = null;\n}\n\nexport function disablePropertyValidation(): void {\n _propertyValidationEnabled = false;\n _validationFrameCount = 0;\n _baselineSnapshot = null;\n}\n\nexport function resetPropertyValidation(): void {\n _validationFrameCount = 0;\n _baselineSnapshot = null;\n}\n\n/**\n * Kebab-case versions for computedStyleMap.get() - pre-computed for speed.\n */\nconst SYNC_PROPERTIES_KEBAB = SYNC_PROPERTIES.map(prop =>\n prop.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`)\n);\n\n/**\n * Feature detection: computedStyleMap is ~15% faster for style syncing.\n */\nconst HAS_COMPUTED_STYLE_MAP = typeof Element !== \"undefined\" && typeof Element.prototype.computedStyleMap === \"function\";\n\n/**\n * CSS initial/default values for SAFE-TO-SKIP properties.\n * Only includes NON-INHERITED properties where skipping the default\n * won't affect visual output.\n * \n * EXCLUDED (must always serialize):\n * - Inherited properties (color, font, text-*, visibility, cursor)\n * - Display (affects layout significantly)\n * - Properties where \"auto\" computes to a specific value\n * \n * INCLUDED (safe to skip):\n * - Transform/filter effects (none = no effect)\n * - Box shadows (none = no shadow)\n * - Borders when none/0 (no visual impact)\n * - backdrop-filter (none = no effect)\n */\nconst CSS_SAFE_DEFAULT_VALUES: Record<string, string | string[]> = {\n // Transforms & effects - safe to skip \"none\" (no visual impact)\n transform: \"none\",\n filter: \"none\",\n backdropFilter: \"none\",\n boxShadow: \"none\",\n \n // Borders - safe to skip when none/0\n border: [\"none\", \"0px none\", \"0px\", \"0px none rgb(0, 0, 0)\"],\n borderTop: [\"none\", \"0px none\", \"0px\", \"0px none rgb(0, 0, 0)\"],\n borderRight: [\"none\", \"0px none\", \"0px\", \"0px none rgb(0, 0, 0)\"],\n borderBottom: [\"none\", \"0px none\", \"0px\", \"0px none rgb(0, 0, 0)\"],\n borderLeft: [\"none\", \"0px none\", \"0px\", \"0px none rgb(0, 0, 0)\"],\n borderRadius: [\"0px\", \"0\"],\n \n // Positioning - safe to skip \"static\"\n position: \"static\",\n \n // Z-index - \"auto\" is safe when position is static\n zIndex: \"auto\",\n \n // 3D transforms - safe to skip defaults\n transformStyle: \"flat\",\n perspective: \"none\",\n backfaceVisibility: \"visible\",\n};\n\n/**\n * Check if a value matches a safe-to-skip default.\n */\nfunction isDefaultValue(prop: string, value: string): boolean {\n const defaults = CSS_SAFE_DEFAULT_VALUES[prop];\n if (!defaults) return false;\n if (Array.isArray(defaults)) {\n return defaults.includes(value);\n }\n return defaults === value;\n}\n\n// Re-export temporal types from shared module\nexport {\n type TemporalElement,\n isTemporal,\n getTemporalBounds,\n isVisibleAtTime,\n} from \"./previewTypes.js\";\n\n// Import for internal use\nimport {\n type TemporalElement,\n getTemporalBounds,\n} from \"./previewTypes.js\";\n\n/**\n * Tree node representing a source/clone pair with children.\n * This replaces the flat array approach for cleaner recursive traversal.\n */\nexport interface CloneNode {\n source: Element;\n clone: HTMLElement;\n children: CloneNode[];\n isCanvasClone: boolean;\n styleCache: Map<string, string>; // Cache of previous style values for change detection\n}\n\n/** Tree-based sync state */\nexport interface CloneTree {\n root: CloneNode | null;\n}\n\n/** Legacy pair type (kept for backward compatibility) */\nexport type ElementPair = [source: Element, clone: HTMLElement];\n\n/** Sync state with tree structure */\nexport interface SyncState {\n tree: CloneTree;\n nodeCount: number; // Total number of nodes (for debugging/logging)\n}\n\n/**\n * Traverse all nodes in the clone tree, calling the callback for each.\n */\nexport function traverseCloneTree(state: SyncState, callback: (node: CloneNode) => void): void {\n function visit(node: CloneNode): void {\n callback(node);\n for (const child of node.children) {\n visit(child);\n }\n }\n if (state.tree.root) {\n visit(state.tree.root);\n }\n}\n\n/**\n * Build clone tree structure with minimal overhead.\n * Optionally syncs styles in the same pass if timeMs is provided.\n */\nexport function buildCloneStructure(source: Element, timeMs?: number): {\n container: HTMLDivElement;\n pairs: ElementPair[];\n syncState: SyncState;\n} {\n const container = document.createElement(\"div\");\n container.style.cssText = \"position:absolute;top:0;left:0;width:100%;height:100%\";\n \n // Collect pairs for legacy compatibility\n const legacyPairs: ElementPair[] = [];\n \n function cloneElement(srcEl: Element): CloneNode | null {\n if (SKIP_TAGS.has(srcEl.tagName)) return null;\n \n // SVG - clone entire subtree (no children tracking needed)\n if (srcEl instanceof SVGElement) {\n const svgClone = srcEl.cloneNode(true) as SVGElement;\n const node: CloneNode = {\n source: srcEl,\n clone: svgClone as unknown as HTMLElement,\n children: [],\n isCanvasClone: false,\n styleCache: new Map(),\n };\n legacyPairs.push([srcEl, node.clone]);\n return node;\n }\n \n // Canvas - copy pixels\n if (srcEl instanceof HTMLCanvasElement) {\n const canvas = document.createElement(\"canvas\");\n canvas.width = srcEl.width;\n canvas.height = srcEl.height;\n const ctx = canvas.getContext(\"2d\");\n if (ctx) {\n try { ctx.drawImage(srcEl, 0, 0); } catch {}\n }\n // Raw canvas elements don't need style syncing, just return clone\n // return null;\n }\n \n // Custom elements with shadow canvas (e.g., ef-video, ef-image)\n const isCustom = srcEl.tagName.includes(\"-\");\n if (isCustom && srcEl.shadowRoot) {\n const shadowCanvas = srcEl.shadowRoot.querySelector(\"canvas\");\n if (shadowCanvas) {\n const clone = document.createElement(\"canvas\");\n clone.width = shadowCanvas.width || srcEl.clientWidth;\n clone.height = shadowCanvas.height || srcEl.clientHeight;\n // Mark ef-image canvases to preserve transparency (use PNG instead of JPEG)\n // ef-video doesn't need this since videos don't have transparency\n if (srcEl.tagName === \"EF-IMAGE\" || srcEl.tagName === \"EF-WAVEFORM\") {\n clone.dataset.preserveAlpha = \"true\";\n }\n const ctx = clone.getContext(\"2d\");\n if (ctx) {\n try { ctx.drawImage(shadowCanvas, 0, 0); } catch {}\n }\n // Copy initial CSS styles\n try {\n const canvasCs = getComputedStyle(shadowCanvas);\n const hostCs = getComputedStyle(srcEl);\n clone.style.position = hostCs.position;\n clone.style.top = hostCs.top;\n clone.style.right = hostCs.right;\n clone.style.bottom = hostCs.bottom;\n clone.style.left = hostCs.left;\n clone.style.margin = hostCs.margin;\n clone.style.zIndex = hostCs.zIndex;\n clone.style.transform = hostCs.transform;\n clone.style.transformOrigin = hostCs.transformOrigin;\n clone.style.opacity = hostCs.opacity;\n clone.style.visibility = hostCs.visibility;\n clone.style.width = canvasCs.width;\n clone.style.height = canvasCs.height;\n clone.style.display = \"block\";\n clone.style.animation = \"none\";\n clone.style.transition = \"none\";\n } catch {}\n \n const node: CloneNode = {\n source: srcEl,\n clone,\n children: [],\n isCanvasClone: true,\n styleCache: new Map(),\n };\n legacyPairs.push([srcEl, clone]);\n return node;\n }\n \n const shadowImg = srcEl.shadowRoot.querySelector(\"img\");\n if (shadowImg?.complete && shadowImg.naturalWidth > 0) {\n const clone = document.createElement(\"canvas\");\n clone.width = shadowImg.naturalWidth;\n clone.height = shadowImg.naturalHeight;\n // Mark as image-sourced canvas to preserve transparency (use PNG instead of JPEG)\n clone.dataset.preserveAlpha = \"true\";\n const ctx = clone.getContext(\"2d\");\n if (ctx) {\n try { ctx.drawImage(shadowImg, 0, 0); } catch {}\n }\n try {\n const imgCs = getComputedStyle(shadowImg);\n const hostCs = getComputedStyle(srcEl);\n clone.style.position = hostCs.position;\n clone.style.top = hostCs.top;\n clone.style.right = hostCs.right;\n clone.style.bottom = hostCs.bottom;\n clone.style.left = hostCs.left;\n clone.style.margin = hostCs.margin;\n clone.style.zIndex = hostCs.zIndex;\n clone.style.transform = hostCs.transform;\n clone.style.transformOrigin = hostCs.transformOrigin;\n clone.style.opacity = hostCs.opacity;\n clone.style.visibility = hostCs.visibility;\n clone.style.width = imgCs.width;\n clone.style.height = imgCs.height;\n clone.style.display = \"block\";\n clone.style.animation = \"none\";\n clone.style.transition = \"none\";\n } catch {}\n \n const node: CloneNode = {\n source: srcEl,\n clone,\n children: [],\n isCanvasClone: true,\n styleCache: new Map(),\n };\n legacyPairs.push([srcEl, clone]);\n return node;\n }\n }\n \n // Standard element clone\n const clone = document.createElement(isCustom ? \"div\" : srcEl.tagName.toLowerCase()) as HTMLElement;\n \n // Copy attributes\n for (const attr of srcEl.attributes) {\n const name = attr.name.toLowerCase();\n if (name === \"id\" || name.startsWith(\"on\")) continue;\n if (isCustom && name !== \"class\" && !name.startsWith(\"data-\")) continue;\n try { clone.setAttribute(attr.name, attr.value); } catch {}\n }\n \n if (srcEl instanceof HTMLImageElement && srcEl.src) {\n (clone as HTMLImageElement).src = srcEl.src;\n }\n if (srcEl instanceof HTMLInputElement) {\n (clone as HTMLInputElement).value = srcEl.value;\n }\n \n const node: CloneNode = {\n source: srcEl,\n clone,\n children: [],\n isCanvasClone: false,\n styleCache: new Map(),\n };\n legacyPairs.push([srcEl, clone]);\n \n // Shadow DOM children\n if (srcEl.shadowRoot) {\n // For caption elements and text segments, ALWAYS create a text node placeholder even if empty.\n // This allows syncStyles to update the text later when captions change.\n const isCaptionElement = srcEl.tagName === 'EF-CAPTIONS-ACTIVE-WORD' ||\n srcEl.tagName === 'EF-CAPTIONS-BEFORE-ACTIVE-WORD' ||\n srcEl.tagName === 'EF-CAPTIONS-AFTER-ACTIVE-WORD' ||\n srcEl.tagName === 'EF-CAPTIONS-SEGMENT';\n const isTextSegment = srcEl.tagName === 'EF-TEXT-SEGMENT';\n let hasTextNode = false;\n \n for (const child of srcEl.shadowRoot.childNodes) {\n if (child.nodeType === Node.TEXT_NODE) {\n const text = child.textContent?.trim();\n // Always include text for text segments (even if whitespace-only, e.g., \" \")\n if (text || isCaptionElement || isTextSegment) {\n clone.appendChild(document.createTextNode(child.textContent || \"\"));\n hasTextNode = true;\n }\n } else if (child.nodeType === Node.ELEMENT_NODE) {\n const el = child as Element;\n if (el.tagName === \"STYLE\" || el.tagName === \"SLOT\") continue;\n const childNode = cloneElement(el);\n if (childNode) {\n node.children.push(childNode);\n clone.appendChild(childNode.clone);\n }\n }\n }\n \n // For caption elements, ensure there's always a text node for syncStyles to update\n if (isCaptionElement && !hasTextNode) {\n clone.appendChild(document.createTextNode(\"\"));\n }\n }\n \n // Light DOM children\n for (const child of srcEl.childNodes) {\n if (child.nodeType === Node.TEXT_NODE) {\n const text = child.textContent?.trim();\n if (text) clone.appendChild(document.createTextNode(text));\n } else if (child.nodeType === Node.ELEMENT_NODE) {\n const childNode = cloneElement(child as Element);\n if (childNode) {\n node.children.push(childNode);\n clone.appendChild(childNode.clone);\n }\n }\n }\n \n return node;\n }\n \n const root = cloneElement(source);\n if (root) container.appendChild(root.clone);\n \n const syncState: SyncState = {\n tree: { root },\n nodeCount: legacyPairs.length,\n };\n \n // Sync styles in the same pass if timeMs is provided\n if (timeMs !== undefined && root) {\n syncNodeRecursive(root, timeMs);\n }\n \n return {\n container,\n pairs: legacyPairs,\n syncState,\n };\n}\n\n/**\n * Sync a single node's styles (extracted for reuse).\n */\nfunction syncNodeStyles(node: CloneNode): void {\n const { source, clone, isCanvasClone } = node;\n \n // Canvas clone - refresh pixels AND sync CSS styles\n if (isCanvasClone) {\n const canvas = clone as HTMLCanvasElement;\n const shadowCanvas = source.shadowRoot?.querySelector(\"canvas\");\n const shadowImg = source.shadowRoot?.querySelector(\"img\");\n \n if (shadowCanvas) {\n if (canvas.width !== shadowCanvas.width) canvas.width = shadowCanvas.width;\n if (canvas.height !== shadowCanvas.height) canvas.height = shadowCanvas.height;\n \n const ctx = canvas.getContext(\"2d\");\n if (ctx && shadowCanvas.width > 0 && shadowCanvas.height > 0) {\n try {\n // Clear canvas before drawing to ensure clean refresh\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.drawImage(shadowCanvas, 0, 0);\n } catch (e) {\n // Canvas draw can fail if source is in invalid state - log and continue\n console.warn(\"[syncNodeStyles] Canvas draw failed:\", e);\n }\n }\n \n try {\n const canvasCs = getComputedStyle(shadowCanvas);\n const hostCs = getComputedStyle(source);\n const s = canvas.style;\n const srcWidth = canvasCs.width;\n const srcHeight = canvasCs.height;\n const srcPosition = hostCs.position;\n const srcTop = hostCs.top;\n const srcLeft = hostCs.left;\n const srcRight = hostCs.right;\n const srcBottom = hostCs.bottom;\n const srcMargin = hostCs.margin;\n const srcTransform = hostCs.transform;\n const srcTransformOrigin = hostCs.transformOrigin;\n const srcOpacity = hostCs.opacity;\n const srcVisibility = hostCs.visibility;\n const srcZIndex = hostCs.zIndex;\n const srcBackfaceVisibility = hostCs.backfaceVisibility;\n const srcTransformStyle = hostCs.transformStyle;\n if (s.position !== srcPosition) s.position = srcPosition;\n if (s.top !== srcTop) s.top = srcTop;\n if (s.left !== srcLeft) s.left = srcLeft;\n if (s.right !== srcRight) s.right = srcRight;\n if (s.bottom !== srcBottom) s.bottom = srcBottom;\n if (s.margin !== srcMargin) s.margin = srcMargin;\n if (s.transform !== srcTransform) s.transform = srcTransform;\n if (s.transformOrigin !== srcTransformOrigin) s.transformOrigin = srcTransformOrigin;\n if (s.opacity !== srcOpacity) s.opacity = srcOpacity;\n if (s.visibility !== srcVisibility) s.visibility = srcVisibility;\n if (s.zIndex !== srcZIndex) s.zIndex = srcZIndex;\n if (s.width !== srcWidth) s.width = srcWidth;\n if (s.height !== srcHeight) s.height = srcHeight;\n if (s.backfaceVisibility !== srcBackfaceVisibility) s.backfaceVisibility = srcBackfaceVisibility;\n if (s.transformStyle !== srcTransformStyle) s.transformStyle = srcTransformStyle;\n } catch {}\n } else if (shadowImg?.complete && shadowImg.naturalWidth > 0) {\n if (canvas.width !== shadowImg.naturalWidth) canvas.width = shadowImg.naturalWidth;\n if (canvas.height !== shadowImg.naturalHeight) canvas.height = shadowImg.naturalHeight;\n \n const ctx = canvas.getContext(\"2d\");\n if (ctx) {\n // Clear canvas before drawing to ensure clean refresh\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n try { ctx.drawImage(shadowImg, 0, 0); } catch {}\n }\n \n try {\n const imgCs = getComputedStyle(shadowImg);\n const hostCs = getComputedStyle(source);\n const s = canvas.style;\n const srcWidth = imgCs.width;\n const srcHeight = imgCs.height;\n const srcPosition = hostCs.position;\n const srcTop = hostCs.top;\n const srcLeft = hostCs.left;\n const srcRight = hostCs.right;\n const srcBottom = hostCs.bottom;\n const srcMargin = hostCs.margin;\n const srcTransform = hostCs.transform;\n const srcTransformOrigin = hostCs.transformOrigin;\n const srcOpacity = hostCs.opacity;\n const srcVisibility = hostCs.visibility;\n const srcZIndex = hostCs.zIndex;\n const srcBackfaceVisibility = hostCs.backfaceVisibility;\n const srcTransformStyle = hostCs.transformStyle;\n if (s.position !== srcPosition) s.position = srcPosition;\n if (s.top !== srcTop) s.top = srcTop;\n if (s.left !== srcLeft) s.left = srcLeft;\n if (s.right !== srcRight) s.right = srcRight;\n if (s.bottom !== srcBottom) s.bottom = srcBottom;\n if (s.margin !== srcMargin) s.margin = srcMargin;\n if (s.transform !== srcTransform) s.transform = srcTransform;\n if (s.transformOrigin !== srcTransformOrigin) s.transformOrigin = srcTransformOrigin;\n if (s.opacity !== srcOpacity) s.opacity = srcOpacity;\n if (s.visibility !== srcVisibility) s.visibility = srcVisibility;\n if (s.zIndex !== srcZIndex) s.zIndex = srcZIndex;\n if (s.width !== srcWidth) s.width = srcWidth;\n if (s.height !== srcHeight) s.height = srcHeight;\n if (s.backfaceVisibility !== srcBackfaceVisibility) s.backfaceVisibility = srcBackfaceVisibility;\n if (s.transformStyle !== srcTransformStyle) s.transformStyle = srcTransformStyle;\n } catch {}\n }\n // return;\n }\n \n // Regular element - sync CSS properties with cache-based change detection\n const cloneStyle = clone.style as any;\n const { styleCache } = node;\n const propLen = SYNC_PROPERTIES.length;\n \n if (HAS_COMPUTED_STYLE_MAP) {\n let srcMap: StylePropertyMapReadOnly;\n try {\n srcMap = source.computedStyleMap();\n } catch { return; }\n \n for (let j = 0; j < propLen; j++) {\n const kebab = SYNC_PROPERTIES_KEBAB[j]!;\n const camel = SYNC_PROPERTIES[j]!;\n const srcVal = srcMap.get(kebab);\n if (!srcVal) continue;\n \n const strVal = srcVal.toString();\n \n // Skip if value hasn't changed from cache\n if (styleCache.get(camel) === strVal) continue;\n styleCache.set(camel, strVal);\n \n if (camel === \"display\") {\n const targetDisplay = strVal === \"none\" ? \"block\" : strVal;\n cloneStyle.display = targetDisplay;\n continue;\n }\n \n // Skip clipPath - clones always have clipPath: none for rendering\n // (source may have clip-path: inset(100%) from proxy mode)\n if (camel === \"clipPath\") continue;\n \n // OPTIMIZATION: Skip default values to reduce serialized HTML size\n // If the computed value is the CSS default, don't set it as inline style\n if (isDefaultValue(camel, strVal)) {\n // Remove from inline style if it was previously set\n if (cloneStyle[camel]) cloneStyle[camel] = \"\";\n continue;\n }\n \n cloneStyle[camel] = strVal;\n }\n } else {\n let cs: CSSStyleDeclaration;\n try {\n cs = getComputedStyle(source);\n } catch { return; }\n \n const srcStyle = cs as any;\n for (const prop of SYNC_PROPERTIES) {\n const srcVal = srcStyle[prop];\n \n // Skip if value hasn't changed from cache\n if (styleCache.get(prop) === srcVal) continue;\n styleCache.set(prop, srcVal);\n \n if (prop === \"display\") {\n const targetDisplay = srcVal === \"none\" ? \"block\" : srcVal;\n cloneStyle.display = targetDisplay;\n continue;\n }\n \n // Skip clipPath - clones always have clipPath: none for rendering\n // (source may have clip-path: inset(100%) from proxy mode)\n if (prop === \"clipPath\") continue;\n \n // OPTIMIZATION: Skip default values to reduce serialized HTML size\n if (isDefaultValue(prop, srcVal)) {\n if (cloneStyle[prop]) cloneStyle[prop] = \"\";\n continue;\n }\n \n cloneStyle[prop] = srcVal;\n }\n }\n \n // Disable animations/transitions to prevent re-animation (animations already finished above)\n if (cloneStyle.animation !== \"none\") cloneStyle.animation = \"none\";\n if (cloneStyle.transition !== \"none\") cloneStyle.transition = \"none\";\n \n // Sync text content from light DOM\n const srcTextNode = source.childNodes[0];\n const cloneTextNode = clone.childNodes[0];\n if (srcTextNode?.nodeType === Node.TEXT_NODE && cloneTextNode?.nodeType === Node.TEXT_NODE) {\n const srcText = srcTextNode.textContent || \"\";\n if (cloneTextNode.textContent !== srcText) cloneTextNode.textContent = srcText;\n }\n \n // Sync text content from shadow DOM (for caption elements that render text in shadow DOM)\n // Only check specific caption elements - checking every element's shadowRoot is expensive\n const tagName = (source as HTMLElement).tagName;\n if (tagName && (\n tagName === 'EF-CAPTIONS-ACTIVE-WORD' ||\n tagName === 'EF-CAPTIONS-BEFORE-ACTIVE-WORD' ||\n tagName === 'EF-CAPTIONS-AFTER-ACTIVE-WORD' ||\n tagName === 'EF-CAPTIONS-SEGMENT'\n )) {\n const srcShadowRoot = (source as HTMLElement).shadowRoot;\n if (srcShadowRoot && !srcTextNode) {\n // Collect ALL text nodes from shadow root (may be multiple due to Lit rendering)\n // Concatenate them to get the complete text content\n let srcShadowText = \"\";\n for (const srcChild of srcShadowRoot.childNodes) {\n if (srcChild.nodeType === Node.TEXT_NODE) {\n srcShadowText += srcChild.textContent || \"\";\n }\n }\n \n // Find or create text node in clone\n // For caption elements, there should be exactly one text node (created in buildCloneStructure)\n let cloneTextNode: Text | null = null;\n for (const cloneChild of clone.childNodes) {\n if (cloneChild.nodeType === Node.TEXT_NODE) {\n cloneTextNode = cloneChild as Text;\n break;\n }\n }\n \n // Create text node if it doesn't exist (shouldn't happen with fixed buildCloneStructure)\n if (!cloneTextNode) {\n cloneTextNode = document.createTextNode(srcShadowText);\n clone.appendChild(cloneTextNode);\n } else if (cloneTextNode.textContent !== srcShadowText) {\n // Update text content if it has changed\n cloneTextNode.textContent = srcShadowText;\n }\n }\n }\n \n // Sync input value\n if (source instanceof HTMLInputElement) {\n const srcVal = source.value;\n const cloneInput = clone as HTMLInputElement;\n if (cloneInput.value !== srcVal) {\n cloneInput.value = srcVal;\n cloneInput.setAttribute(\"value\", srcVal);\n }\n }\n}\n\n/**\n * Recursively sync a node and its children.\n * Returns early if the node is temporally culled, skipping ALL descendants.\n */\nfunction syncNodeRecursive(node: CloneNode, timeMs: number): void {\n const { source, clone, children, isCanvasClone, styleCache } = node;\n \n // Temporal culling - check if this node is visible at current time\n // Canvas clones skip temporal check (ef-video may have [0,0] range before video loads)\n if (!isCanvasClone) {\n const { startMs, endMs } = getTemporalBounds(source);\n if (timeMs < startMs || timeMs > endMs) {\n // Hide this element and BAIL OUT - skip all descendants automatically!\n clone.style.display = \"none\";\n // Invalidate display cache so it gets restored when element comes back in range\n styleCache.delete(\"display\");\n return;\n }\n }\n \n // Sync this node's styles\n syncNodeStyles(node);\n \n // Recursively sync children\n for (const child of children) {\n syncNodeRecursive(child, timeMs);\n }\n}\n\n/**\n * Sync all CSS properties from source elements to their clones.\n * Uses recursive tree traversal with early bailout for temporal culling.\n */\nexport function syncStyles(state: SyncState, timeMs: number): void {\n if (state.tree.root) {\n syncNodeRecursive(state.tree.root, timeMs);\n }\n \n // Property validation: detect unexpected property changes\n if (_propertyValidationEnabled) {\n validatePropertyChanges(state);\n }\n}\n\n/**\n * Captures a snapshot of all CSS properties for all source elements.\n */\nfunction capturePropertySnapshot(state: SyncState): Map<Element, Map<string, string>> {\n const snapshot = new Map<Element, Map<string, string>>();\n \n function captureNode(node: CloneNode): void {\n const props = new Map<string, string>();\n try {\n const cs = getComputedStyle(node.source);\n for (const prop of SYNC_PROPERTIES) {\n props.set(prop, (cs as any)[prop] ?? \"\");\n }\n } catch {}\n snapshot.set(node.source, props);\n \n for (const child of node.children) {\n captureNode(child);\n }\n }\n \n if (state.tree.root) {\n captureNode(state.tree.root);\n }\n \n return snapshot;\n}\n\n/**\n * Validates that only expected properties have changed since baseline.\n * Throws if any unexpected property changed.\n */\nfunction validatePropertyChanges(state: SyncState): void {\n _validationFrameCount++;\n \n // Capture baseline on first frame\n if (_baselineSnapshot === null) {\n _baselineSnapshot = capturePropertySnapshot(state);\n return;\n }\n \n // Only validate every 30 frames (expensive operation)\n if (_validationFrameCount % 30 !== 0) {\n return;\n }\n \n const currentSnapshot = capturePropertySnapshot(state);\n const violations: string[] = [];\n \n for (const [element, baselineProps] of _baselineSnapshot) {\n const currentProps = currentSnapshot.get(element);\n if (!currentProps) continue;\n \n for (const [prop, baselineValue] of baselineProps) {\n const currentValue = currentProps.get(prop) ?? \"\";\n \n // Skip if value unchanged\n if (baselineValue === currentValue) continue;\n \n if (!SYNC_PROPERTIES_SET.has(prop)) {\n const elementId = element.id || element.tagName;\n violations.push(\n `[${elementId}] ${prop}: \"${baselineValue}\" → \"${currentValue}\"`\n );\n }\n }\n }\n \n if (violations.length > 0) {\n const message = [\n `\\n⚠️ UNEXPECTED PROPERTY CHANGES at frame ${_validationFrameCount}:`,\n `Properties not in SYNC_PROPERTIES changed during export.`,\n ``,\n `Violations (${violations.length}):`,\n ...violations.slice(0, 20).map(v => ` ${v}`),\n violations.length > 20 ? ` ... and ${violations.length - 20} more` : \"\",\n ].join(\"\\n\");\n \n throw new Error(message);\n }\n}\n\n/**\n * Legacy sync function for backwards compatibility.\n */\nexport function syncAllStyles(pairs: ElementPair[], syncState?: SyncState, timeMs?: number): void {\n if (syncState) {\n syncStyles(syncState, timeMs ?? 0);\n return;\n }\n \n // Fallback for legacy callers without syncState\n for (let i = 0; i < pairs.length; i++) {\n const [src, clone] = pairs[i]!;\n \n let cs: CSSStyleDeclaration;\n try {\n cs = getComputedStyle(src);\n } catch { continue; }\n \n const cloneStyle = clone.style as any;\n const srcStyle = cs as any;\n \n if (srcStyle.display === \"none\") {\n if (cloneStyle.display !== \"none\") cloneStyle.display = \"none\";\n continue;\n }\n \n for (const prop of SYNC_PROPERTIES) {\n if (prop === \"display\") continue;\n const srcVal = srcStyle[prop];\n if (cloneStyle[prop] !== srcVal) cloneStyle[prop] = srcVal;\n }\n if (cloneStyle.animation !== \"none\") cloneStyle.animation = \"none\";\n if (cloneStyle.transition !== \"none\") cloneStyle.transition = \"none\";\n \n const srcTextNode = src.childNodes[0];\n const cloneTextNode = clone.childNodes[0];\n if (srcTextNode?.nodeType === Node.TEXT_NODE && cloneTextNode?.nodeType === Node.TEXT_NODE) {\n const srcText = srcTextNode.textContent || \"\";\n if (cloneTextNode.textContent !== srcText) cloneTextNode.textContent = srcText;\n }\n if (src instanceof HTMLInputElement && clone instanceof HTMLInputElement) {\n const srcVal = src.value;\n if (clone.value !== srcVal) {\n clone.value = srcVal;\n clone.setAttribute(\"value\", srcVal);\n }\n }\n \n // Canvas refresh\n if (clone instanceof HTMLCanvasElement && src.shadowRoot) {\n const shadowCanvas = src.shadowRoot.querySelector(\"canvas\");\n if (shadowCanvas && shadowCanvas.width > 0 && shadowCanvas.height > 0) {\n const ctx = clone.getContext(\"2d\");\n if (ctx) {\n if (clone.width !== shadowCanvas.width) clone.width = shadowCanvas.width;\n if (clone.height !== shadowCanvas.height) clone.height = shadowCanvas.height;\n ctx.clearRect(0, 0, clone.width, clone.height);\n try { ctx.drawImage(shadowCanvas, 0, 0); } catch {}\n }\n }\n }\n }\n}\n\n/**\n * Collect document styles for shadow DOM injection.\n */\nexport function collectDocumentStyles(): string {\n const rules: string[] = [];\n try {\n for (const sheet of document.styleSheets) {\n try {\n if (sheet.cssRules) {\n for (const rule of sheet.cssRules) {\n rules.push(rule.cssText);\n }\n }\n } catch {}\n }\n } catch {}\n return rules.join(\"\\n\");\n}\n\n\n// Backward-compatible aliases\nexport const syncStaticStyles = syncStyles;\nexport const syncAnimatedStyles = syncStyles;\n\n/**\n * Override clip-path, opacity, and optionally transform on the root clone element.\n * The source may have these properties set for proxy mode or workbench scaling.\n * \n * @param syncState - The sync state containing the clone tree\n * @param fullReset - If true, also resets opacity and transform (for capture operations)\n */\nexport function overrideRootCloneStyles(syncState: SyncState, fullReset: boolean = false): void {\n const rootClone = syncState.tree.root?.clone;\n if (!rootClone) return;\n \n rootClone.style.clipPath = \"none\";\n if (fullReset) {\n rootClone.style.opacity = \"1\";\n rootClone.style.transform = \"none\";\n }\n}\n\n/**\n * Create a live preview of a timegroup with a refresh function.\n * Used by EFWorkbench for the \"computed\" preview mode.\n * \n * @param source - The source timegroup to preview\n * @returns Object with preview container and refresh function\n */\nexport function renderTimegroupPreview(source: Element): {\n container: HTMLDivElement;\n refresh: (timeMs?: number) => void;\n} {\n const { container, syncState } = buildCloneStructure(source);\n \n // Initial style sync\n syncStyles(syncState, 0);\n \n return {\n container,\n refresh: (timeMs?: number) => {\n syncStyles(syncState, timeMs ?? 0);\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"renderTimegroupPreview.js","names":["CSS_SAFE_DEFAULT_VALUES: Record<string, string | string[]>","removed: RemovedNodeInfo[]","node: CloneNode","node","clone","syncState: SyncState","srcMap: StylePropertyMapReadOnly","cs: CSSStyleDeclaration","syncStats: SyncStats","rules: string[]"],"sources":["../../src/preview/renderTimegroupPreview.ts"],"sourcesContent":["/**\n * Canvas refresh fix:\n * Canvas pixels must be explicitly cleared and redrawn in syncNodeStyles\n * to ensure video frames are captured correctly during foreignObject rendering.\n * Without clearRect, stale frames from previous seeks may be serialized.\n * \n * See FOREIGNOBJECT_BUG_FIX.md for detailed explanation.\n */\n\nimport { logger } from \"./logger.js\";\n\n/**\n * Elements to skip entirely when building the preview.\n */\nconst SKIP_TAGS = new Set([\n \"EF-AUDIO\",\n \"EF-THUMBNAIL-STRIP\",\n \"EF-FILMSTRIP\",\n \"EF-TIMELINE\",\n \"EF-WORKBENCH\",\n \"SCRIPT\",\n \"STYLE\",\n]);\n\n/**\n * All CSS properties to sync (camelCase for style[] access).\n */\nconst SYNC_PROPERTIES = [\n \"display\", \"visibility\", \"opacity\",\n \"position\", \"top\", \"right\", \"bottom\", \"left\", \"zIndex\",\n \"width\", \"height\", \"minWidth\", \"minHeight\", \"maxWidth\", \"maxHeight\",\n \"flex\", \"flexFlow\", \"justifyContent\", \"alignItems\", \"alignContent\", \"alignSelf\", \"gap\",\n \"gridTemplate\", \"gridColumn\", \"gridRow\", \"gridArea\",\n \"margin\", \"padding\", \"boxSizing\",\n \"border\", \"borderTop\", \"borderRight\", \"borderBottom\", \"borderLeft\", \"borderRadius\",\n \"background\", \"color\", \"boxShadow\", \"filter\", \"backdropFilter\", \"clipPath\",\n \"font\", \"textAlign\", \"textDecoration\", \"textTransform\",\n \"letterSpacing\", \"whiteSpace\", \"textOverflow\", \"lineHeight\",\n \"transform\", \"transformOrigin\", \"transformStyle\",\n \"perspective\", \"perspectiveOrigin\", \"backfaceVisibility\",\n \"cursor\", \"pointerEvents\", \"userSelect\", \"overflow\",\n] as const;\n\n/**\n * Kebab-case versions for computedStyleMap.get() - pre-computed for speed.\n */\nconst SYNC_PROPERTIES_KEBAB = SYNC_PROPERTIES.map(prop =>\n prop.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`)\n);\n\n/**\n * Feature detection: computedStyleMap is ~15% faster for style syncing.\n */\nconst HAS_COMPUTED_STYLE_MAP = typeof Element !== \"undefined\" && typeof Element.prototype.computedStyleMap === \"function\";\n\n/**\n * CSS initial/default values for SAFE-TO-SKIP properties.\n * Only includes NON-INHERITED properties where skipping the default\n * won't affect visual output.\n * \n * EXCLUDED (must always serialize):\n * - Inherited properties (color, font, text-*, visibility, cursor)\n * - Display (affects layout significantly)\n * - Properties where \"auto\" computes to a specific value\n * \n * INCLUDED (safe to skip):\n * - Transform/filter effects (none = no effect)\n * - Box shadows (none = no shadow)\n * - Borders when none/0 (no visual impact)\n * - backdrop-filter (none = no effect)\n */\nconst CSS_SAFE_DEFAULT_VALUES: Record<string, string | string[]> = {\n // Transforms & effects - safe to skip \"none\" (no visual impact)\n transform: \"none\",\n filter: \"none\",\n backdropFilter: \"none\",\n boxShadow: \"none\",\n \n // Borders - safe to skip when none/0\n border: [\"none\", \"0px none\", \"0px\", \"0px none rgb(0, 0, 0)\"],\n borderTop: [\"none\", \"0px none\", \"0px\", \"0px none rgb(0, 0, 0)\"],\n borderRight: [\"none\", \"0px none\", \"0px\", \"0px none rgb(0, 0, 0)\"],\n borderBottom: [\"none\", \"0px none\", \"0px\", \"0px none rgb(0, 0, 0)\"],\n borderLeft: [\"none\", \"0px none\", \"0px\", \"0px none rgb(0, 0, 0)\"],\n borderRadius: [\"0px\", \"0\"],\n \n // Positioning - safe to skip \"static\"\n position: \"static\",\n \n // Z-index - \"auto\" is safe when position is static\n zIndex: \"auto\",\n \n // 3D transforms - safe to skip defaults\n transformStyle: \"flat\",\n perspective: \"none\",\n backfaceVisibility: \"visible\",\n};\n\n/**\n * Check if a value matches a safe-to-skip default.\n */\nfunction isDefaultValue(prop: string, value: string): boolean {\n const defaults = CSS_SAFE_DEFAULT_VALUES[prop];\n if (!defaults) return false;\n if (Array.isArray(defaults)) {\n return defaults.includes(value);\n }\n return defaults === value;\n}\n\n// Re-export temporal types from shared module\nexport {\n type TemporalElement,\n isTemporal,\n getTemporalBounds,\n isVisibleAtTime,\n} from \"./previewTypes.js\";\n\n// Import for internal use\nimport {\n getTemporalBounds,\n} from \"./previewTypes.js\";\n\n/**\n * Tree node representing a source/clone pair with children.\n * This replaces the flat array approach for cleaner recursive traversal.\n */\nexport interface CloneNode {\n source: Element;\n clone: HTMLElement;\n children: CloneNode[];\n isCanvasClone: boolean;\n /** Cached temporal bounds for this node */\n bounds: { startMs: number; endMs: number };\n /** Parent node reference for ancestor visibility checks */\n parent: CloneNode | null;\n}\n\n/** Tree-based sync state */\nexport interface CloneTree {\n root: CloneNode | null;\n}\n\n/** Sync state with tree structure and delta tracking */\nexport interface SyncState {\n tree: CloneTree;\n nodeCount: number; // Total number of nodes (for debugging/logging)\n /** Maps clone canvases to their original source elements (ef-video, ef-image, etc.) */\n canvasSourceMap: WeakMap<HTMLCanvasElement, Element>;\n /** Previous frame's visible set for delta tracking */\n previousVisibleSet: Set<CloneNode>;\n /** Current frame's visible set (updated by syncStyles) */\n currentVisibleSet: Set<CloneNode>;\n}\n\n/** Info needed to restore a removed node */\ninterface RemovedNodeInfo {\n node: CloneNode;\n parent: Node;\n nextSibling: Node | null;\n}\n\n/**\n * Remove hidden nodes from the clone DOM for serialization.\n * Returns info needed to restore them afterward.\n * \n * This physically removes non-visible nodes so they won't be serialized,\n * avoiding the cost of serializing hidden elements and their resources.\n */\nexport function removeHiddenNodesForSerialization(state: SyncState): RemovedNodeInfo[] {\n const removed: RemovedNodeInfo[] = [];\n const visibleSet = state.currentVisibleSet;\n \n // Traverse all nodes and remove those not in visible set\n function visit(node: CloneNode): void {\n // First recurse to children (before potentially removing this node)\n for (const child of node.children) {\n visit(child);\n }\n \n // If this node isn't visible, remove it from DOM\n if (!visibleSet.has(node)) {\n const parent = node.clone.parentNode;\n if (parent) {\n const nextSibling = node.clone.nextSibling;\n parent.removeChild(node.clone);\n removed.push({ node, parent, nextSibling });\n }\n }\n }\n \n if (state.tree.root) {\n visit(state.tree.root);\n }\n \n return removed;\n}\n\n/**\n * Restore previously removed hidden nodes to the clone DOM.\n * Must be called after serialization to maintain tree integrity for next frame.\n */\nexport function restoreHiddenNodes(removed: RemovedNodeInfo[]): void {\n // Restore in reverse order to maintain correct DOM positions\n for (let i = removed.length - 1; i >= 0; i--) {\n const { node, parent, nextSibling } = removed[i]!;\n if (nextSibling) {\n parent.insertBefore(node.clone, nextSibling);\n } else {\n parent.appendChild(node.clone);\n }\n }\n}\n\n/**\n * Get visible canvases from the current visible set.\n * Use this to skip encoding hidden canvases during serialization.\n */\nexport function getVisibleCanvases(state: SyncState): Set<HTMLCanvasElement> {\n const visibleCanvases = new Set<HTMLCanvasElement>();\n for (const node of state.currentVisibleSet) {\n if (node.clone instanceof HTMLCanvasElement) {\n visibleCanvases.add(node.clone);\n }\n }\n return visibleCanvases;\n}\n\n/**\n * Traverse all nodes in the clone tree, calling the callback for each.\n */\nexport function traverseCloneTree(state: SyncState, callback: (node: CloneNode) => void): void {\n function visit(node: CloneNode): void {\n callback(node);\n for (const child of node.children) {\n visit(child);\n }\n }\n if (state.tree.root) {\n visit(state.tree.root);\n }\n}\n\n/**\n * Helper to copy styles from host and content elements to a canvas clone.\n * Reduces code duplication for shadow canvas and shadow img cases.\n */\nfunction copyCanvasCloneStyles(\n clone: HTMLCanvasElement,\n hostCs: CSSStyleDeclaration,\n contentCs: CSSStyleDeclaration\n): void {\n const s = clone.style;\n s.position = hostCs.position;\n s.top = hostCs.top;\n s.right = hostCs.right;\n s.bottom = hostCs.bottom;\n s.left = hostCs.left;\n s.margin = hostCs.margin;\n s.zIndex = hostCs.zIndex;\n s.transform = hostCs.transform;\n s.transformOrigin = hostCs.transformOrigin;\n s.opacity = hostCs.opacity;\n s.visibility = hostCs.visibility;\n s.width = contentCs.width;\n s.height = contentCs.height;\n s.display = \"block\";\n s.animation = \"none\";\n s.transition = \"none\";\n}\n\n/**\n * Build clone tree structure with minimal overhead.\n * Caches temporal bounds on each node for visibility checks.\n * Optionally syncs styles in the same pass if timeMs is provided.\n */\nexport function buildCloneStructure(source: Element, timeMs?: number): {\n container: HTMLDivElement;\n syncState: SyncState;\n} {\n const container = document.createElement(\"div\");\n container.style.cssText = \"position:absolute;top:0;left:0;width:100%;height:100%\";\n \n let nodeCount = 0;\n const canvasSourceMap = new WeakMap<HTMLCanvasElement, Element>();\n \n function cloneElement(srcEl: Element, parentNode: CloneNode | null): CloneNode | null {\n if (SKIP_TAGS.has(srcEl.tagName)) return null;\n \n // Get temporal bounds upfront for indexing\n const bounds = getTemporalBounds(srcEl);\n \n // SVG - clone entire subtree (no children tracking needed)\n if (srcEl instanceof SVGElement) {\n const svgClone = srcEl.cloneNode(true) as SVGElement;\n const node: CloneNode = {\n source: srcEl,\n clone: svgClone as unknown as HTMLElement,\n children: [],\n isCanvasClone: false,\n bounds,\n parent: parentNode,\n };\n nodeCount++;\n return node;\n }\n \n // Canvas - copy pixels\n if (srcEl instanceof HTMLCanvasElement) {\n const canvas = document.createElement(\"canvas\");\n canvas.width = srcEl.width;\n canvas.height = srcEl.height;\n const ctx = canvas.getContext(\"2d\");\n if (ctx) {\n try { ctx.drawImage(srcEl, 0, 0); } catch {}\n }\n // Raw canvas elements don't need style syncing, just return clone\n // return null;\n }\n \n // Custom elements with shadow canvas (e.g., ef-video, ef-image)\n const isCustom = srcEl.tagName.includes(\"-\");\n if (isCustom && srcEl.shadowRoot) {\n const shadowCanvas = srcEl.shadowRoot.querySelector(\"canvas\");\n if (shadowCanvas) {\n const clone = document.createElement(\"canvas\");\n clone.width = shadowCanvas.width || srcEl.clientWidth;\n clone.height = shadowCanvas.height || srcEl.clientHeight;\n // Mark ef-image canvases to preserve transparency (use PNG instead of JPEG)\n // ef-video doesn't need this since videos don't have transparency\n if (srcEl.tagName === \"EF-IMAGE\" || srcEl.tagName === \"EF-WAVEFORM\") {\n clone.dataset.preserveAlpha = \"true\";\n }\n \n const ctx = clone.getContext(\"2d\");\n if (ctx) {\n try { ctx.drawImage(shadowCanvas, 0, 0); } catch {}\n }\n \n // Copy initial CSS styles - OPTIMIZATION: Cache getComputedStyle results\n try {\n const hostCs = getComputedStyle(srcEl);\n const canvasCs = getComputedStyle(shadowCanvas);\n copyCanvasCloneStyles(clone, hostCs, canvasCs);\n } catch {}\n \n // Map clone canvas to source element for RenderContext caching\n canvasSourceMap.set(clone, srcEl);\n \n const node: CloneNode = {\n source: srcEl,\n clone,\n children: [],\n isCanvasClone: true,\n bounds,\n parent: parentNode,\n };\n nodeCount++;\n return node;\n }\n \n const shadowImg = srcEl.shadowRoot.querySelector(\"img\");\n if (shadowImg?.complete && shadowImg.naturalWidth > 0) {\n const clone = document.createElement(\"canvas\");\n clone.width = shadowImg.naturalWidth;\n clone.height = shadowImg.naturalHeight;\n // Mark as image-sourced canvas to preserve transparency (use PNG instead of JPEG)\n clone.dataset.preserveAlpha = \"true\";\n const ctx = clone.getContext(\"2d\");\n if (ctx) {\n try { ctx.drawImage(shadowImg, 0, 0); } catch {}\n }\n \n // Copy initial CSS styles - OPTIMIZATION: Cache getComputedStyle results\n try {\n const hostCs = getComputedStyle(srcEl);\n const imgCs = getComputedStyle(shadowImg);\n copyCanvasCloneStyles(clone, hostCs, imgCs);\n } catch {}\n \n // Map clone canvas to source element for RenderContext caching\n canvasSourceMap.set(clone, srcEl);\n \n const node: CloneNode = {\n source: srcEl,\n clone,\n children: [],\n isCanvasClone: true,\n bounds,\n parent: parentNode,\n };\n nodeCount++;\n return node;\n }\n }\n \n // Standard element clone\n const clone = document.createElement(isCustom ? \"div\" : srcEl.tagName.toLowerCase()) as HTMLElement;\n \n // Copy attributes - OPTIMIZATION: Early exit if no attributes\n const attrs = srcEl.attributes;\n const attrLen = attrs.length;\n if (attrLen > 0) {\n for (let i = 0; i < attrLen; i++) {\n const attr = attrs[i]!;\n const name = attr.name.toLowerCase();\n if (name === \"id\" || name.startsWith(\"on\")) continue;\n if (isCustom && name !== \"class\" && !name.startsWith(\"data-\")) continue;\n try { clone.setAttribute(attr.name, attr.value); } catch {}\n }\n }\n \n if (srcEl instanceof HTMLImageElement && srcEl.src) {\n (clone as HTMLImageElement).src = srcEl.src;\n }\n if (srcEl instanceof HTMLInputElement) {\n (clone as HTMLInputElement).value = srcEl.value;\n }\n \n const node: CloneNode = {\n source: srcEl,\n clone,\n children: [],\n isCanvasClone: false,\n bounds,\n parent: parentNode,\n };\n nodeCount++;\n \n // Shadow DOM children - OPTIMIZATION: Early exit if no childNodes\n if (srcEl.shadowRoot) {\n const shadowChildren = srcEl.shadowRoot.childNodes;\n const shadowLen = shadowChildren.length;\n if (shadowLen > 0) {\n // For text segments, ALWAYS create a text node placeholder even if empty.\n // Caption elements now use light DOM, so they don't need special handling here.\n const isTextSegment = srcEl.tagName === 'EF-TEXT-SEGMENT';\n let hasTextNode = false;\n \n for (let i = 0; i < shadowLen; i++) {\n const child = shadowChildren[i]!;\n if (child.nodeType === Node.TEXT_NODE) {\n const text = child.textContent?.trim();\n // Always include text for text segments (even if whitespace-only, e.g., \" \")\n if (text || isTextSegment) {\n clone.appendChild(document.createTextNode(child.textContent || \"\"));\n hasTextNode = true;\n }\n } else if (child.nodeType === Node.ELEMENT_NODE) {\n const el = child as Element;\n if (el.tagName === \"STYLE\" || el.tagName === \"SLOT\") continue;\n const childNode = cloneElement(el, node);\n if (childNode) {\n node.children.push(childNode);\n clone.appendChild(childNode.clone);\n }\n }\n }\n \n // For text segments, ensure there's always a text node for syncStyles to update\n if (isTextSegment && !hasTextNode) {\n clone.appendChild(document.createTextNode(\"\"));\n }\n }\n }\n \n // Light DOM children - OPTIMIZATION: Use indexed loop for performance\n const lightChildren = srcEl.childNodes;\n const lightLen = lightChildren.length;\n for (let i = 0; i < lightLen; i++) {\n const child = lightChildren[i]!;\n if (child.nodeType === Node.TEXT_NODE) {\n const text = child.textContent?.trim();\n if (text) clone.appendChild(document.createTextNode(text));\n } else if (child.nodeType === Node.ELEMENT_NODE) {\n const childNode = cloneElement(child as Element, node);\n if (childNode) {\n node.children.push(childNode);\n clone.appendChild(childNode.clone);\n }\n }\n }\n \n return node;\n }\n \n const root = cloneElement(source, null);\n if (root) container.appendChild(root.clone);\n \n const syncState: SyncState = {\n tree: { root },\n nodeCount,\n canvasSourceMap,\n previousVisibleSet: new Set(),\n currentVisibleSet: new Set(),\n };\n \n // Sync styles in the same pass if timeMs is provided\n if (timeMs !== undefined && root) {\n syncStylesWithIndex(syncState, timeMs);\n }\n \n return {\n container,\n syncState,\n };\n}\n\n/**\n * Sync a single node's styles (extracted for reuse).\n */\nfunction syncNodeStyles(node: CloneNode): void {\n const { source, clone, isCanvasClone } = node;\n \n // Canvas clone - refresh pixels AND sync CSS styles\n if (isCanvasClone) {\n const canvas = clone as HTMLCanvasElement;\n const shadowCanvas = source.shadowRoot?.querySelector(\"canvas\");\n const shadowImg = source.shadowRoot?.querySelector(\"img\");\n \n if (shadowCanvas) {\n if (canvas.width !== shadowCanvas.width) canvas.width = shadowCanvas.width;\n if (canvas.height !== shadowCanvas.height) canvas.height = shadowCanvas.height;\n \n const ctx = canvas.getContext(\"2d\");\n if (ctx && shadowCanvas.width > 0 && shadowCanvas.height > 0) {\n try {\n // Clear canvas before drawing to ensure clean refresh\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.drawImage(shadowCanvas, 0, 0);\n } catch (e) {\n // Canvas draw can fail if source is in invalid state - log and continue\n logger.warn(\"[syncNodeStyles] Canvas draw failed:\", e);\n }\n }\n \n try {\n const canvasCs = getComputedStyle(shadowCanvas);\n const hostCs = getComputedStyle(source);\n const s = canvas.style;\n \n // Browser optimizes redundant style writes internally\n s.position = hostCs.position;\n s.top = hostCs.top;\n s.left = hostCs.left;\n s.right = hostCs.right;\n s.bottom = hostCs.bottom;\n s.margin = hostCs.margin;\n s.transform = hostCs.transform;\n s.transformOrigin = hostCs.transformOrigin;\n s.opacity = hostCs.opacity;\n s.visibility = hostCs.visibility;\n s.zIndex = hostCs.zIndex;\n s.width = canvasCs.width;\n s.height = canvasCs.height;\n s.backfaceVisibility = hostCs.backfaceVisibility;\n s.transformStyle = hostCs.transformStyle;\n } catch {}\n } else if (shadowImg?.complete && shadowImg.naturalWidth > 0) {\n if (canvas.width !== shadowImg.naturalWidth) canvas.width = shadowImg.naturalWidth;\n if (canvas.height !== shadowImg.naturalHeight) canvas.height = shadowImg.naturalHeight;\n \n const ctx = canvas.getContext(\"2d\");\n if (ctx) {\n // Clear canvas before drawing to ensure clean refresh\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n try { ctx.drawImage(shadowImg, 0, 0); } catch {}\n }\n \n try {\n const imgCs = getComputedStyle(shadowImg);\n const hostCs = getComputedStyle(source);\n const s = canvas.style;\n \n // Browser optimizes redundant style writes internally\n s.position = hostCs.position;\n s.top = hostCs.top;\n s.left = hostCs.left;\n s.right = hostCs.right;\n s.bottom = hostCs.bottom;\n s.margin = hostCs.margin;\n s.transform = hostCs.transform;\n s.transformOrigin = hostCs.transformOrigin;\n s.opacity = hostCs.opacity;\n s.visibility = hostCs.visibility;\n s.zIndex = hostCs.zIndex;\n s.width = imgCs.width;\n s.height = imgCs.height;\n s.backfaceVisibility = hostCs.backfaceVisibility;\n s.transformStyle = hostCs.transformStyle;\n } catch {}\n }\n // return;\n }\n \n // Regular element - sync CSS properties directly (browser optimizes redundant writes)\n const cloneStyle = clone.style as any;\n const propLen = SYNC_PROPERTIES.length;\n const tagName = (source as HTMLElement).tagName;\n \n if (HAS_COMPUTED_STYLE_MAP) {\n let srcMap: StylePropertyMapReadOnly;\n try {\n srcMap = source.computedStyleMap();\n } catch { return; }\n \n for (let j = 0; j < propLen; j++) {\n const kebab = SYNC_PROPERTIES_KEBAB[j]!;\n const camel = SYNC_PROPERTIES[j]!;\n const srcVal = srcMap.get(kebab);\n if (!srcVal) continue;\n \n const strVal = srcVal.toString();\n \n if (camel === \"display\") {\n // For caption child elements, preserve display:none when explicitly set\n // (they use it to hide empty content, not for temporal visibility)\n const isCaptionChild = tagName && (\n tagName === 'EF-CAPTIONS-ACTIVE-WORD' ||\n tagName === 'EF-CAPTIONS-BEFORE-ACTIVE-WORD' ||\n tagName === 'EF-CAPTIONS-AFTER-ACTIVE-WORD' ||\n tagName === 'EF-CAPTIONS-SEGMENT'\n );\n const targetDisplay = (strVal === \"none\" && !isCaptionChild) ? \"block\" : strVal;\n cloneStyle.display = targetDisplay;\n continue;\n }\n \n // Skip clipPath - clones always have clipPath: none for rendering\n // (source may have clip-path: inset(100%) from proxy mode)\n if (camel === \"clipPath\") continue;\n \n // OPTIMIZATION: Skip default values to reduce serialized HTML size\n // If the computed value is the CSS default, don't set it as inline style\n if (isDefaultValue(camel, strVal)) {\n // Remove from inline style if it was previously set\n if (cloneStyle[camel]) cloneStyle[camel] = \"\";\n continue;\n }\n \n cloneStyle[camel] = strVal;\n }\n } else {\n let cs: CSSStyleDeclaration;\n try {\n cs = getComputedStyle(source);\n } catch { return; }\n \n const srcStyle = cs as any;\n for (const prop of SYNC_PROPERTIES) {\n const srcVal = srcStyle[prop];\n \n if (prop === \"display\") {\n // For caption child elements, preserve display:none when explicitly set\n // (they use it to hide empty content, not for temporal visibility)\n const isCaptionChild = tagName && (\n tagName === 'EF-CAPTIONS-ACTIVE-WORD' ||\n tagName === 'EF-CAPTIONS-BEFORE-ACTIVE-WORD' ||\n tagName === 'EF-CAPTIONS-AFTER-ACTIVE-WORD' ||\n tagName === 'EF-CAPTIONS-SEGMENT'\n );\n const targetDisplay = (srcVal === \"none\" && !isCaptionChild) ? \"block\" : srcVal;\n cloneStyle.display = targetDisplay;\n continue;\n }\n \n // Skip clipPath - clones always have clipPath: none for rendering\n // (source may have clip-path: inset(100%) from proxy mode)\n if (prop === \"clipPath\") continue;\n \n // OPTIMIZATION: Skip default values to reduce serialized HTML size\n if (isDefaultValue(prop, srcVal)) {\n if (cloneStyle[prop]) cloneStyle[prop] = \"\";\n continue;\n }\n \n cloneStyle[prop] = srcVal;\n }\n }\n \n // Disable animations/transitions to prevent re-animation (browser optimizes redundant writes)\n cloneStyle.animation = \"none\";\n cloneStyle.transition = \"none\";\n \n // Sync text content from light DOM\n // Caption child elements now use light DOM, so this handles them naturally\n const srcTextNode = source.childNodes[0];\n if (srcTextNode?.nodeType === Node.TEXT_NODE) {\n const srcText = srcTextNode.textContent || \"\";\n const cloneTextNode = clone.childNodes[0];\n \n if (cloneTextNode?.nodeType === Node.TEXT_NODE) {\n // Update existing text node\n if (cloneTextNode.textContent !== srcText) cloneTextNode.textContent = srcText;\n } else if (!clone.childNodes.length) {\n // Only create text node if clone has NO children (was empty when initially cloned)\n // Don't set textContent as it would delete element children!\n clone.appendChild(document.createTextNode(srcText));\n }\n }\n \n // Sync input value\n if (source instanceof HTMLInputElement) {\n const srcVal = source.value;\n const cloneInput = clone as HTMLInputElement;\n if (cloneInput.value !== srcVal) {\n cloneInput.value = srcVal;\n cloneInput.setAttribute(\"value\", srcVal);\n }\n }\n}\n\n// Performance instrumentation counters\ninterface SyncStats {\n nodesVisited: number;\n nodesCulledByParent: number;\n nodesCulledByTemporal: number;\n nodesProcessed: number;\n nodesFullSync: number; // Newly visible nodes (full sync)\n nodesIncrementalSync: number; // Still visible nodes (incremental sync)\n nodesHidden: number; // Newly hidden nodes\n indexQueryTimeMs: number;\n syncTimeMs: number;\n}\n\nlet syncStats: SyncStats = {\n nodesVisited: 0,\n nodesCulledByParent: 0,\n nodesCulledByTemporal: 0,\n nodesProcessed: 0,\n nodesFullSync: 0,\n nodesIncrementalSync: 0,\n nodesHidden: 0,\n indexQueryTimeMs: 0,\n syncTimeMs: 0,\n};\n\n/**\n * Visibility delta between frames.\n * Used for incremental updates - only sync what changed.\n */\ninterface VisibilityDelta {\n nowVisible: Set<CloneNode>; // Need full style sync + show\n stillVisible: Set<CloneNode>; // Only sync animated properties (or skip if same time)\n nowHidden: Set<CloneNode>; // Just set display:none\n}\n\n/**\n * Compute visibility delta between previous and current frame.\n */\nfunction computeVisibilityDelta(\n previousSet: Set<CloneNode>,\n currentSet: Set<CloneNode>,\n): VisibilityDelta {\n const nowVisible = new Set<CloneNode>();\n const stillVisible = new Set<CloneNode>();\n const nowHidden = new Set<CloneNode>();\n \n // Find nodes that became visible or stayed visible\n for (const node of currentSet) {\n if (previousSet.has(node)) {\n stillVisible.add(node);\n } else {\n nowVisible.add(node);\n }\n }\n \n // Find nodes that became hidden\n for (const node of previousSet) {\n if (!currentSet.has(node)) {\n nowHidden.add(node);\n }\n }\n \n return { nowVisible, stillVisible, nowHidden };\n}\n\n/**\n * Build visible set by recursive traversal with bounds checking.\n * Queries fresh bounds from source elements each time - bounds are computed\n * dynamically by timegroups based on composition mode.\n */\nfunction buildVisibleSetRecursive(\n node: CloneNode,\n timeMs: number,\n visibleSet: Set<CloneNode>,\n): void {\n const { children, source } = node;\n \n // Get fresh bounds from source element (not cached - timegroup bounds are dynamic)\n const bounds = getTemporalBounds(source);\n \n // Check if this node is visible at current time\n const isVisible = timeMs >= bounds.startMs && timeMs <= bounds.endMs;\n \n if (isVisible) {\n visibleSet.add(node);\n // Recurse to children\n for (const child of children) {\n buildVisibleSetRecursive(child, timeMs, visibleSet);\n }\n }\n // If not visible, skip entire subtree\n}\n\n/**\n * Sync styles with recursive visibility check and delta tracking.\n * \n * DELTA TRACKING: Tracks visibility changes between frames to minimize work:\n * - nowVisible nodes: Full style sync + show\n * - stillVisible nodes: Incremental sync (source DOM may have changed)\n * - nowHidden nodes: Just hide (display:none)\n */\nfunction syncStylesWithIndex(state: SyncState, timeMs: number): void {\n const queryStart = performance.now();\n \n // Build the set of visible nodes by recursive traversal\n const visibleSet = new Set<CloneNode>();\n if (state.tree.root) {\n buildVisibleSetRecursive(state.tree.root, timeMs, visibleSet);\n }\n \n // Compute delta from previous frame\n const delta = computeVisibilityDelta(state.previousVisibleSet, visibleSet);\n \n syncStats.indexQueryTimeMs = performance.now() - queryStart;\n \n // Now traverse the tree but use the delta for O(1) sync decisions\n const syncStart = performance.now();\n if (state.tree.root) {\n syncNodeWithDelta(state.tree.root, visibleSet, delta);\n }\n syncStats.syncTimeMs = performance.now() - syncStart;\n \n // Update state for next frame and expose current visible set\n state.previousVisibleSet = visibleSet;\n state.currentVisibleSet = visibleSet;\n}\n\n/**\n * Sync a node using visibility delta for incremental updates.\n * \n * DELTA TRACKING optimization:\n * - nowVisible: Full style sync (element just appeared)\n * - stillVisible: Incremental sync (source DOM may have changed)\n * - nowHidden: Just hide the element\n * - Not in any set: Skip entirely (was already hidden)\n */\nfunction syncNodeWithDelta(\n node: CloneNode,\n visibleSet: Set<CloneNode>,\n delta: VisibilityDelta,\n): void {\n syncStats.nodesVisited++;\n \n const isVisible = visibleSet.has(node);\n \n if (!isVisible) {\n // Node is not visible - ALWAYS set display:none\n // This handles both \"just became hidden\" and \"initial build with node outside time range\"\n node.clone.style.display = \"none\";\n if (delta.nowHidden.has(node)) {\n syncStats.nodesHidden++;\n }\n // Already hidden nodes: skip (don't even recurse to children)\n syncStats.nodesCulledByTemporal++;\n return;\n }\n \n // Node is visible - determine sync strategy\n if (delta.nowVisible.has(node)) {\n // Just became visible - need full style sync\n syncNodeStyles(node);\n syncStats.nodesFullSync++;\n } else if (delta.stillVisible.has(node)) {\n // Was visible, still visible - still need to sync\n // Source DOM properties can change independently of time (input values, text, etc.)\n // TODO: Phase 5 could track property changes for smarter incremental sync\n syncNodeStyles(node);\n syncStats.nodesIncrementalSync++;\n }\n \n syncStats.nodesProcessed++;\n \n // Recurse to children\n for (const child of node.children) {\n syncNodeWithDelta(child, visibleSet, delta);\n }\n}\n\n/**\n * Legacy recursive sync (kept for comparison/fallback).\n * Returns early if the node is temporally culled, skipping ALL descendants.\n * @deprecated Use syncStylesWithIndex for better performance\n */\nexport function syncNodeRecursiveLegacy(node: CloneNode, timeMs: number): void {\n const { clone, children, bounds } = node;\n syncStats.nodesVisited++;\n \n // Temporal culling - check if this node is visible at current time\n // NOTE: Canvas clones now participate in temporal culling (lazy canvas copying).\n // Invalid bounds [0,0] are treated as [-Infinity, Infinity] by getTemporalBounds.\n {\n // OPTIMIZATION: Check if parent is already hidden to skip bounds computation\n const parent = clone.parentElement;\n if (parent instanceof HTMLElement) {\n // If parent has display:none, this element is already hidden - skip bounds check\n if (parent.style.display === \"none\") {\n clone.style.display = \"none\";\n syncStats.nodesCulledByParent++;\n return;\n }\n }\n \n // Use cached bounds from node instead of calling getTemporalBounds\n const { startMs, endMs } = bounds;\n if (timeMs < startMs || timeMs > endMs) {\n // Hide this element and BAIL OUT - skip all descendants automatically!\n clone.style.display = \"none\";\n syncStats.nodesCulledByTemporal++;\n return;\n }\n }\n \n // Sync this node's styles\n syncNodeStyles(node);\n syncStats.nodesProcessed++;\n \n // Recursively sync children\n for (const child of children) {\n syncNodeRecursiveLegacy(child, timeMs);\n }\n}\n\n/**\n * Sync all CSS properties from source elements to their clones.\n * Uses interval index for O(log n + k) visibility queries instead of O(n) traversal.\n * Uses delta tracking for incremental updates between frames.\n */\nexport function syncStyles(state: SyncState, timeMs: number): void {\n // Reset stats\n syncStats = {\n nodesVisited: 0,\n nodesCulledByParent: 0,\n nodesCulledByTemporal: 0,\n nodesProcessed: 0,\n nodesFullSync: 0,\n nodesIncrementalSync: 0,\n nodesHidden: 0,\n indexQueryTimeMs: 0,\n syncTimeMs: 0,\n };\n \n // Use interval-index-based sync with delta tracking\n syncStylesWithIndex(state, timeMs);\n}\n\n/**\n * Collect document styles for shadow DOM injection.\n */\nexport function collectDocumentStyles(): string {\n const rules: string[] = [];\n try {\n for (const sheet of document.styleSheets) {\n try {\n if (sheet.cssRules) {\n for (const rule of sheet.cssRules) {\n rules.push(rule.cssText);\n }\n }\n } catch {}\n }\n } catch {}\n return rules.join(\"\\n\");\n}\n\n\n// Backward-compatible aliases\nexport const syncStaticStyles = syncStyles;\nexport const syncAnimatedStyles = syncStyles;\n\n/**\n * Override clip-path, opacity, and optionally transform on the root clone element.\n * The source may have these properties set for proxy mode or workbench scaling.\n * \n * @param syncState - The sync state containing the clone tree\n * @param fullReset - If true, also resets opacity and transform (for capture operations)\n */\nexport function overrideRootCloneStyles(syncState: SyncState, fullReset: boolean = false): void {\n const rootClone = syncState.tree.root?.clone;\n if (!rootClone) return;\n \n rootClone.style.clipPath = \"none\";\n if (fullReset) {\n rootClone.style.opacity = \"1\";\n rootClone.style.transform = \"none\";\n }\n}\n\n/**\n * Create a live preview of a timegroup with a refresh function.\n * Used by EFWorkbench for the \"computed\" preview mode.\n * \n * @param source - The source timegroup to preview\n * @returns Object with preview container and refresh function\n */\nexport function renderTimegroupPreview(source: Element): {\n container: HTMLDivElement;\n refresh: (timeMs?: number) => void;\n} {\n const { container, syncState } = buildCloneStructure(source);\n \n // Initial style sync\n syncStyles(syncState, 0);\n \n return {\n container,\n refresh: (timeMs?: number) => {\n syncStyles(syncState, timeMs ?? 0);\n },\n };\n}\n"],"mappings":"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"}
|