@editframe/elements 0.37.3-beta → 0.38.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EF_FRAMEGEN.js +17 -14
- package/dist/EF_FRAMEGEN.js.map +1 -1
- package/dist/EF_RENDERING.js.map +1 -1
- package/dist/canvas/EFCanvas.d.ts +9 -2
- package/dist/canvas/EFCanvas.js +14 -4
- package/dist/canvas/EFCanvas.js.map +1 -1
- package/dist/canvas/EFCanvasItem.d.ts +2 -2
- package/dist/canvas/overlays/SelectionOverlay.d.ts +10 -2
- package/dist/canvas/overlays/SelectionOverlay.js +5 -12
- package/dist/canvas/overlays/SelectionOverlay.js.map +1 -1
- package/dist/canvas/overlays/overlayState.js.map +1 -1
- package/dist/canvas/selection/SelectionController.js.map +1 -1
- package/dist/elements/EFAudio.d.ts +1 -11
- package/dist/elements/EFAudio.js +2 -10
- package/dist/elements/EFAudio.js.map +1 -1
- package/dist/elements/EFCaptions.d.ts +5 -9
- package/dist/elements/EFCaptions.js +34 -11
- package/dist/elements/EFCaptions.js.map +1 -1
- package/dist/elements/EFImage.d.ts +10 -8
- package/dist/elements/EFImage.js +117 -32
- package/dist/elements/EFImage.js.map +1 -1
- package/dist/elements/EFMedia/AssetMediaEngine.js +2 -2
- package/dist/elements/EFMedia/AssetMediaEngine.js.map +1 -1
- package/dist/elements/EFMedia/BaseMediaEngine.js +15 -92
- package/dist/elements/EFMedia/BaseMediaEngine.js.map +1 -1
- package/dist/elements/EFMedia/BufferedSeekingInput.js +10 -11
- package/dist/elements/EFMedia/BufferedSeekingInput.js.map +1 -1
- package/dist/elements/EFMedia/{AssetIdMediaEngine.js → FileMediaEngine.js} +44 -24
- package/dist/elements/EFMedia/FileMediaEngine.js.map +1 -0
- package/dist/elements/EFMedia/JitMediaEngine.js +14 -13
- 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/shared/ThumbnailExtractor.js +12 -7
- package/dist/elements/EFMedia/shared/ThumbnailExtractor.js.map +1 -1
- package/dist/elements/EFMedia/shared/timeoutUtils.js +44 -0
- package/dist/elements/EFMedia/shared/timeoutUtils.js.map +1 -0
- package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js +1 -1
- package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js.map +1 -1
- package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js +4 -4
- package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js.map +1 -1
- package/dist/elements/EFMedia.d.ts +14 -8
- package/dist/elements/EFMedia.js +52 -19
- package/dist/elements/EFMedia.js.map +1 -1
- package/dist/elements/EFPanZoom.d.ts +2 -2
- package/dist/elements/EFPanZoom.js +1 -1
- package/dist/elements/EFPanZoom.js.map +1 -1
- package/dist/elements/EFSourceMixin.js +16 -8
- package/dist/elements/EFSourceMixin.js.map +1 -1
- package/dist/elements/EFSurface.d.ts +5 -8
- package/dist/elements/EFSurface.js +4 -43
- package/dist/elements/EFSurface.js.map +1 -1
- package/dist/elements/EFTemporal.d.ts +33 -8
- package/dist/elements/EFTemporal.js +92 -40
- package/dist/elements/EFTemporal.js.map +1 -1
- package/dist/elements/EFText.d.ts +3 -0
- package/dist/elements/EFText.js +54 -21
- package/dist/elements/EFText.js.map +1 -1
- package/dist/elements/EFTextSegment.js +8 -4
- package/dist/elements/EFTextSegment.js.map +1 -1
- package/dist/elements/EFTimegroup.d.ts +26 -43
- package/dist/elements/EFTimegroup.js +295 -314
- package/dist/elements/EFTimegroup.js.map +1 -1
- package/dist/elements/EFVideo.d.ts +44 -42
- package/dist/elements/EFVideo.js +259 -172
- package/dist/elements/EFVideo.js.map +1 -1
- package/dist/elements/EFWaveform.d.ts +3 -8
- package/dist/elements/EFWaveform.js +18 -13
- package/dist/elements/EFWaveform.js.map +1 -1
- package/dist/elements/ElementPositionInfo.js.map +1 -1
- package/dist/elements/FetchMixin.js.map +1 -1
- package/dist/elements/TargetController.d.ts +0 -3
- package/dist/elements/TargetController.js +12 -35
- package/dist/elements/TargetController.js.map +1 -1
- package/dist/elements/TimegroupController.js.map +1 -1
- package/dist/elements/cloneFactoryRegistry.d.ts +14 -0
- package/dist/elements/cloneFactoryRegistry.js +15 -0
- package/dist/elements/cloneFactoryRegistry.js.map +1 -0
- package/dist/elements/renderTemporalAudio.js +8 -6
- package/dist/elements/renderTemporalAudio.js.map +1 -1
- package/dist/elements/setupTemporalHierarchy.js +62 -0
- package/dist/elements/setupTemporalHierarchy.js.map +1 -0
- package/dist/elements/updateAnimations.js +62 -87
- package/dist/elements/updateAnimations.js.map +1 -1
- package/dist/getRenderInfo.d.ts +3 -2
- package/dist/getRenderInfo.js +20 -4
- package/dist/getRenderInfo.js.map +1 -1
- package/dist/gui/ContextMixin.js +68 -12
- package/dist/gui/ContextMixin.js.map +1 -1
- package/dist/gui/Controllable.js +1 -1
- package/dist/gui/Controllable.js.map +1 -1
- package/dist/gui/EFActiveRootTemporal.d.ts +2 -2
- package/dist/gui/EFActiveRootTemporal.js.map +1 -1
- package/dist/gui/EFControls.d.ts +2 -2
- package/dist/gui/EFControls.js +2 -2
- package/dist/gui/EFControls.js.map +1 -1
- package/dist/gui/EFDial.d.ts +2 -2
- package/dist/gui/EFDial.js +12 -9
- package/dist/gui/EFDial.js.map +1 -1
- package/dist/gui/EFFilmstrip.d.ts +2 -0
- package/dist/gui/EFFilmstrip.js +18 -10
- package/dist/gui/EFFilmstrip.js.map +1 -1
- package/dist/gui/EFFitScale.d.ts +28 -4
- package/dist/gui/EFFitScale.js +88 -26
- package/dist/gui/EFFitScale.js.map +1 -1
- package/dist/gui/EFFocusOverlay.d.ts +2 -2
- package/dist/gui/EFFocusOverlay.js +3 -3
- package/dist/gui/EFFocusOverlay.js.map +1 -1
- package/dist/gui/EFOverlayItem.d.ts +2 -2
- package/dist/gui/EFOverlayLayer.d.ts +2 -2
- package/dist/gui/EFPause.d.ts +2 -2
- package/dist/gui/EFPause.js +1 -1
- package/dist/gui/EFPlay.d.ts +2 -2
- package/dist/gui/EFPlay.js +1 -1
- package/dist/gui/EFPreview.js +1 -1
- package/dist/gui/EFResizableBox.d.ts +2 -2
- package/dist/gui/EFResizableBox.js +5 -5
- package/dist/gui/EFResizableBox.js.map +1 -1
- package/dist/gui/EFScrubber.d.ts +2 -2
- package/dist/gui/EFScrubber.js +8 -13
- package/dist/gui/EFScrubber.js.map +1 -1
- package/dist/gui/EFTimeDisplay.d.ts +6 -2
- package/dist/gui/EFTimeDisplay.js +25 -7
- package/dist/gui/EFTimeDisplay.js.map +1 -1
- package/dist/gui/EFTimelineRuler.d.ts +2 -2
- package/dist/gui/EFTimelineRuler.js +3 -3
- package/dist/gui/EFTimelineRuler.js.map +1 -1
- package/dist/gui/EFToggleLoop.d.ts +2 -2
- package/dist/gui/EFToggleLoop.js +1 -1
- package/dist/gui/EFTogglePlay.d.ts +2 -2
- package/dist/gui/EFTogglePlay.js +1 -1
- package/dist/gui/EFTransformHandles.d.ts +2 -2
- package/dist/gui/EFTransformHandles.js +6 -6
- package/dist/gui/EFTransformHandles.js.map +1 -1
- package/dist/gui/EFWorkbench.d.ts +40 -36
- package/dist/gui/EFWorkbench.js +436 -822
- package/dist/gui/EFWorkbench.js.map +1 -1
- package/dist/gui/FitScaleHelpers.js.map +1 -1
- package/dist/gui/PlaybackController.d.ts +3 -8
- package/dist/gui/PlaybackController.js +59 -56
- 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 +43 -6
- package/dist/gui/TargetOrContextMixin.js.map +1 -1
- package/dist/gui/ef-theme.css +136 -0
- package/dist/gui/hierarchy/EFHierarchy.d.ts +2 -2
- package/dist/gui/hierarchy/EFHierarchy.js +14 -24
- package/dist/gui/hierarchy/EFHierarchy.js.map +1 -1
- package/dist/gui/hierarchy/EFHierarchyItem.d.ts +3 -3
- package/dist/gui/hierarchy/EFHierarchyItem.js +22 -10
- package/dist/gui/hierarchy/EFHierarchyItem.js.map +1 -1
- package/dist/gui/icons.js.map +1 -1
- package/dist/gui/previewSettingsContext.d.ts +18 -0
- package/dist/gui/previewSettingsContext.js.map +1 -1
- package/dist/gui/theme.js +34 -0
- package/dist/gui/theme.js.map +1 -0
- package/dist/gui/timeline/EFTimeline.d.ts +2 -2
- package/dist/gui/timeline/EFTimeline.js +70 -52
- package/dist/gui/timeline/EFTimeline.js.map +1 -1
- package/dist/gui/timeline/EFTimelineRow.d.ts +5 -3
- package/dist/gui/timeline/EFTimelineRow.js +55 -32
- package/dist/gui/timeline/EFTimelineRow.js.map +1 -1
- package/dist/gui/timeline/TrimHandles.d.ts +23 -9
- package/dist/gui/timeline/TrimHandles.js +224 -51
- package/dist/gui/timeline/TrimHandles.js.map +1 -1
- package/dist/gui/timeline/flattenHierarchy.js.map +1 -1
- package/dist/gui/timeline/timelineEditingContext.d.ts +34 -0
- package/dist/gui/timeline/timelineEditingContext.js +24 -0
- package/dist/gui/timeline/timelineEditingContext.js.map +1 -0
- package/dist/gui/timeline/timelineStateContext.js.map +1 -1
- package/dist/gui/timeline/tracks/AudioTrack.js +1 -1
- package/dist/gui/timeline/tracks/AudioTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/CaptionsTrack.d.ts +2 -3
- package/dist/gui/timeline/tracks/CaptionsTrack.js +17 -75
- package/dist/gui/timeline/tracks/CaptionsTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/EFThumbnailStrip.d.ts +52 -0
- package/dist/gui/timeline/tracks/EFThumbnailStrip.js +596 -0
- package/dist/gui/timeline/tracks/EFThumbnailStrip.js.map +1 -0
- package/dist/gui/timeline/tracks/HTMLTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/ImageTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/TextTrack.d.ts +3 -2
- package/dist/gui/timeline/tracks/TextTrack.js +17 -43
- package/dist/gui/timeline/tracks/TextTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/TimegroupTrack.d.ts +3 -4
- package/dist/gui/timeline/tracks/TimegroupTrack.js +33 -23
- package/dist/gui/timeline/tracks/TimegroupTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/TrackItem.d.ts +7 -9
- package/dist/gui/timeline/tracks/TrackItem.js +18 -17
- package/dist/gui/timeline/tracks/TrackItem.js.map +1 -1
- package/dist/gui/timeline/tracks/VideoTrack.d.ts +3 -3
- package/dist/gui/timeline/tracks/VideoTrack.js +11 -14
- package/dist/gui/timeline/tracks/VideoTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/WaveformTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/renderTrackChildren.js.map +1 -1
- package/dist/gui/timeline/tracks/waveformUtils.js +1 -1
- package/dist/gui/timeline/tracks/waveformUtils.js.map +1 -1
- package/dist/gui/tree/EFTree.d.ts +2 -2
- package/dist/gui/tree/EFTree.js +8 -14
- package/dist/gui/tree/EFTree.js.map +1 -1
- package/dist/gui/tree/EFTreeItem.d.ts +2 -2
- package/dist/gui/tree/EFTreeItem.js +3 -3
- package/dist/gui/tree/EFTreeItem.js.map +1 -1
- package/dist/gui/tree/treeContext.js.map +1 -1
- package/dist/index.d.ts +10 -8
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +2 -2
- package/dist/node.js +2 -2
- package/dist/preview/AdaptiveResolutionTracker.js +3 -3
- package/dist/preview/AdaptiveResolutionTracker.js.map +1 -1
- package/dist/preview/FrameController.d.ts +2 -17
- package/dist/preview/FrameController.js +40 -63
- package/dist/preview/FrameController.js.map +1 -1
- package/dist/preview/QualityUpgradeScheduler.d.ts +76 -0
- package/dist/preview/QualityUpgradeScheduler.js +158 -0
- package/dist/preview/QualityUpgradeScheduler.js.map +1 -0
- package/dist/preview/RenderContext.d.ts +119 -1
- package/dist/preview/RenderContext.js +21 -3
- package/dist/preview/RenderContext.js.map +1 -1
- package/dist/preview/RenderProfiler.js.map +1 -1
- package/dist/preview/RenderStats.js +85 -0
- package/dist/preview/RenderStats.js.map +1 -0
- package/dist/preview/encoding/canvasEncoder.js +2 -52
- package/dist/preview/encoding/canvasEncoder.js.map +1 -1
- package/dist/preview/encoding/mainThreadEncoder.js.map +1 -1
- package/dist/preview/encoding/workerEncoder.js.map +1 -1
- package/dist/preview/logger.js.map +1 -1
- package/dist/preview/previewSettings.d.ts +34 -0
- package/dist/preview/previewSettings.js +29 -17
- package/dist/preview/previewSettings.js.map +1 -1
- package/dist/preview/previewTypes.js +4 -4
- package/dist/preview/previewTypes.js.map +1 -1
- package/dist/preview/renderElementToCanvas.d.ts +44 -0
- package/dist/preview/renderElementToCanvas.js +72 -0
- package/dist/preview/renderElementToCanvas.js.map +1 -0
- package/dist/preview/renderTimegroupToCanvas.d.ts +134 -32
- package/dist/preview/renderTimegroupToCanvas.js +321 -146
- package/dist/preview/renderTimegroupToCanvas.js.map +1 -1
- package/dist/preview/renderTimegroupToCanvas.types.d.ts +51 -0
- package/dist/preview/renderTimegroupToVideo.d.ts +20 -35
- package/dist/preview/renderTimegroupToVideo.js +94 -106
- package/dist/preview/renderTimegroupToVideo.js.map +1 -1
- package/dist/preview/renderTimegroupToVideo.types.d.ts +42 -0
- package/dist/preview/renderVideoToVideo.js +286 -0
- package/dist/preview/renderVideoToVideo.js.map +1 -0
- package/dist/preview/renderers.d.ts +56 -0
- package/dist/preview/renderers.js +13 -1
- package/dist/preview/renderers.js.map +1 -1
- package/dist/preview/rendering/ScaleConfig.js +74 -0
- package/dist/preview/rendering/ScaleConfig.js.map +1 -0
- package/dist/preview/rendering/inlineImages.d.ts +13 -0
- package/dist/preview/rendering/inlineImages.js +7 -44
- package/dist/preview/rendering/inlineImages.js.map +1 -1
- package/dist/preview/rendering/loadImage.d.ts +8 -0
- package/dist/preview/rendering/loadImage.js +22 -0
- package/dist/preview/rendering/loadImage.js.map +1 -0
- package/dist/preview/rendering/renderToImageNative.js +3 -3
- package/dist/preview/rendering/renderToImageNative.js.map +1 -1
- package/dist/preview/rendering/serializeTimelineDirect.js +224 -68
- package/dist/preview/rendering/serializeTimelineDirect.js.map +1 -1
- package/dist/preview/statsTrackingStrategy.js +1 -101
- package/dist/preview/statsTrackingStrategy.js.map +1 -1
- package/dist/preview/workers/WorkerPool.js +0 -1
- package/dist/preview/workers/WorkerPool.js.map +1 -1
- package/dist/preview/workers/encoderWorkerInline.js +21 -54
- package/dist/preview/workers/encoderWorkerInline.js.map +1 -1
- package/dist/render/EFRenderAPI.d.ts +2 -1
- package/dist/render/EFRenderAPI.js +12 -36
- package/dist/render/EFRenderAPI.js.map +1 -1
- package/dist/render/getRenderData.js +4 -4
- package/dist/render/getRenderData.js.map +1 -1
- package/dist/style.css +114 -163
- package/dist/transcoding/cache/RequestDeduplicator.js +1 -0
- package/dist/transcoding/cache/RequestDeduplicator.js.map +1 -1
- package/dist/transcoding/types/index.d.ts +1 -1
- package/dist/transcoding/utils/UrlGenerator.js +10 -3
- package/dist/transcoding/utils/UrlGenerator.js.map +1 -1
- package/dist/utils/LRUCache.js +1 -0
- package/dist/utils/LRUCache.js.map +1 -1
- package/dist/utils/frameTime.js +23 -1
- package/dist/utils/frameTime.js.map +1 -1
- package/package.json +45 -8
- package/scripts/build-css.js +8 -1
- package/test/setup.ts +0 -1
- package/test/useAssetMSW.ts +50 -0
- package/test/visualRegressionUtils.ts +23 -9
- package/tsdown.config.ts +6 -1
- package/dist/_virtual/rolldown_runtime.js +0 -27
- package/dist/elements/EFMedia/AssetIdMediaEngine.js.map +0 -1
- package/dist/elements/EFThumbnailStrip.d.ts +0 -167
- package/dist/elements/EFThumbnailStrip.js +0 -731
- package/dist/elements/EFThumbnailStrip.js.map +0 -1
- package/dist/elements/SessionThumbnailCache.js +0 -154
- package/dist/elements/SessionThumbnailCache.js.map +0 -1
- package/dist/node_modules/react/cjs/react-jsx-runtime.development.js +0 -688
- package/dist/node_modules/react/cjs/react-jsx-runtime.development.js.map +0 -1
- package/dist/node_modules/react/cjs/react.development.js +0 -1521
- package/dist/node_modules/react/cjs/react.development.js.map +0 -1
- package/dist/node_modules/react/index.js +0 -13
- package/dist/node_modules/react/index.js.map +0 -1
- package/dist/node_modules/react/jsx-runtime.js +0 -13
- package/dist/node_modules/react/jsx-runtime.js.map +0 -1
- package/dist/preview/encoding/types.d.ts +0 -1
- package/dist/preview/renderTimegroupPreview.js +0 -686
- package/dist/preview/renderTimegroupPreview.js.map +0 -1
- package/dist/preview/rendering/renderToImage.d.ts +0 -2
- package/dist/preview/rendering/renderToImage.js +0 -95
- package/dist/preview/rendering/renderToImage.js.map +0 -1
- package/dist/preview/rendering/renderToImageForeignObject.js +0 -163
- package/dist/preview/rendering/renderToImageForeignObject.js.map +0 -1
- package/dist/preview/rendering/renderToImageNative.d.ts +0 -1
- package/dist/preview/rendering/svgSerializer.js +0 -43
- package/dist/preview/rendering/svgSerializer.js.map +0 -1
- package/dist/preview/rendering/types.d.ts +0 -2
- package/dist/preview/thumbnailCacheSettings.js +0 -52
- package/dist/preview/thumbnailCacheSettings.js.map +0 -1
- package/dist/sandbox/PlaybackControls.d.ts +0 -1
- package/dist/sandbox/PlaybackControls.js +0 -10
- package/dist/sandbox/PlaybackControls.js.map +0 -1
- package/dist/sandbox/ScenarioRunner.d.ts +0 -1
- package/dist/sandbox/ScenarioRunner.js +0 -1
- package/dist/sandbox/defineSandbox.d.ts +0 -1
- package/dist/sandbox/index.d.ts +0 -3
- package/dist/sandbox/index.js +0 -2
- package/test/EFVideo.framegen.browsertest.ts +0 -80
- package/test/thumbnail-performance-test.html +0 -116
|
@@ -4,7 +4,7 @@ import { loopContext, playingContext } from "./playingContext.js";
|
|
|
4
4
|
import { __decorate } from "../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
|
|
5
5
|
import { isEFTemporal } from "../elements/EFTemporal.js";
|
|
6
6
|
import { TargetController } from "../elements/TargetController.js";
|
|
7
|
-
import { isControllable } from "./Controllable.js";
|
|
7
|
+
import { createDirectTemporalSubscription, determineTargetType, isControllable } from "./Controllable.js";
|
|
8
8
|
import { consume } from "@lit/context";
|
|
9
9
|
import { property, state } from "lit/decorators.js";
|
|
10
10
|
|
|
@@ -33,6 +33,7 @@ function TargetOrContextMixin(superClass, contextToProxy) {
|
|
|
33
33
|
#contextUnsubscribe;
|
|
34
34
|
#contextRequestHandler;
|
|
35
35
|
#additionalContextUnsubscribes = /* @__PURE__ */ new Map();
|
|
36
|
+
#directTemporalSubscription;
|
|
36
37
|
get effectiveContext() {
|
|
37
38
|
return this.targetElement ?? this.contextFromParent;
|
|
38
39
|
}
|
|
@@ -47,11 +48,49 @@ function TargetOrContextMixin(superClass, contextToProxy) {
|
|
|
47
48
|
};
|
|
48
49
|
this.addEventListener("context-request", this.#contextRequestHandler, true);
|
|
49
50
|
}
|
|
50
|
-
#
|
|
51
|
-
if (!this.targetElement) return;
|
|
51
|
+
#unsubscribeAll() {
|
|
52
52
|
this.#contextUnsubscribe?.();
|
|
53
|
+
this.#contextUnsubscribe = void 0;
|
|
53
54
|
for (const unsubscribe of this.#additionalContextUnsubscribes.values()) unsubscribe();
|
|
54
55
|
this.#additionalContextUnsubscribes.clear();
|
|
56
|
+
this.#directTemporalSubscription?.unsubscribe();
|
|
57
|
+
this.#directTemporalSubscription = void 0;
|
|
58
|
+
}
|
|
59
|
+
#tryDirectTemporalSubscription() {
|
|
60
|
+
if (!this.targetElement) return false;
|
|
61
|
+
if (determineTargetType(this.targetElement) !== "direct-temporal") return false;
|
|
62
|
+
this.#directTemporalSubscription = createDirectTemporalSubscription(this.targetElement, {
|
|
63
|
+
onPlayingChange: (value) => {
|
|
64
|
+
this.playing = value;
|
|
65
|
+
},
|
|
66
|
+
onLoopChange: (value) => {
|
|
67
|
+
if ("loop" in this) this.loop = value;
|
|
68
|
+
},
|
|
69
|
+
onCurrentTimeMsChange: (value) => {
|
|
70
|
+
if ("currentTimeMs" in this) this.currentTimeMs = value;
|
|
71
|
+
},
|
|
72
|
+
onDurationMsChange: (value) => {
|
|
73
|
+
if ("durationMs" in this) this.durationMs = value;
|
|
74
|
+
},
|
|
75
|
+
onTargetTemporalChange: () => {}
|
|
76
|
+
});
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
#subscribeToTargetContext() {
|
|
80
|
+
if (!this.targetElement) return;
|
|
81
|
+
this.#unsubscribeAll();
|
|
82
|
+
if (this.#tryDirectTemporalSubscription()) return;
|
|
83
|
+
if (isEFTemporal(this.targetElement)) {
|
|
84
|
+
const target = this.targetElement;
|
|
85
|
+
target.updateComplete.then(() => {
|
|
86
|
+
if (this.targetElement !== target) return;
|
|
87
|
+
if (!this.#tryDirectTemporalSubscription()) target.updateComplete.then(() => {
|
|
88
|
+
if (this.targetElement !== target) return;
|
|
89
|
+
this.#tryDirectTemporalSubscription();
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
55
94
|
const event = new ContextRequestEvent(contextToProxy, this, (value, unsubscribe) => {
|
|
56
95
|
this.contextFromParent = value;
|
|
57
96
|
this.#contextUnsubscribe = unsubscribe;
|
|
@@ -83,9 +122,7 @@ function TargetOrContextMixin(superClass, contextToProxy) {
|
|
|
83
122
|
}
|
|
84
123
|
disconnectedCallback() {
|
|
85
124
|
super.disconnectedCallback();
|
|
86
|
-
this.#
|
|
87
|
-
for (const unsubscribe of this.#additionalContextUnsubscribes.values()) unsubscribe();
|
|
88
|
-
this.#additionalContextUnsubscribes.clear();
|
|
125
|
+
this.#unsubscribeAll();
|
|
89
126
|
if (this.#contextRequestHandler) this.removeEventListener("context-request", this.#contextRequestHandler, true);
|
|
90
127
|
}
|
|
91
128
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TargetOrContextMixin.js","names":["#targetController","#contextRequestHandler","#contextUnsubscribe","#additionalContextUnsubscribes","additionalContexts: Array<[Context<any, any>, string]>","#subscribeToTargetContext"],"sources":["../../src/gui/TargetOrContextMixin.ts"],"sourcesContent":["import { type Context, consume } from \"@lit/context\";\nimport type { LitElement } from \"lit\";\nimport { property, state } from \"lit/decorators.js\";\nimport { isEFTemporal } from \"../elements/EFTemporal.js\";\nimport { TargetController } from \"../elements/TargetController.js\";\nimport { type ControllableInterface, isControllable } from \"./Controllable.js\";\nimport { currentTimeContext } from \"./currentTimeContext.js\";\nimport { durationContext } from \"./durationContext.js\";\nimport { loopContext, playingContext } from \"./playingContext.js\";\n\ntype Constructor<T = {}> = new (...args: any[]) => T;\n\nclass ContextRequestEvent extends Event {\n context: Context<any, any>;\n contextTarget: Element;\n callback: (value: any, unsubscribe: () => void) => void;\n subscribe: boolean;\n\n constructor(\n context: Context<any, any>,\n contextTarget: Element,\n callback: (value: any, unsubscribe: () => void) => void,\n subscribe: boolean,\n ) {\n super(\"context-request\", { bubbles: true, composed: true });\n this.context = context;\n this.contextTarget = contextTarget;\n this.callback = callback;\n this.subscribe = subscribe ?? false;\n }\n}\n\nexport function TargetOrContextMixin<T extends Constructor<LitElement>>(\n superClass: T,\n contextToProxy: Context<any, any>,\n) {\n class TargetOrContextClass extends superClass {\n @property({ type: String })\n target = \"\";\n\n @state()\n targetElement: ControllableInterface | null = null;\n\n // @ts-expect-error contextToProxy is generic but provides ControllableInterface at runtime\n @consume({ context: contextToProxy, subscribe: true })\n contextFromParent: ControllableInterface | null = null;\n\n #targetController?: TargetController;\n #contextUnsubscribe?: () => void;\n #contextRequestHandler?: (event: Event) => void;\n #additionalContextUnsubscribes = new Map<Context<any, any>, () => void>();\n\n get effectiveContext(): ControllableInterface | null {\n return this.targetElement ?? this.contextFromParent;\n }\n\n connectedCallback() {\n super.connectedCallback();\n if (this.target) {\n this.#targetController = new TargetController(\n this as any as LitElement & {\n targetElement: Element | null;\n target: string;\n },\n );\n }\n\n // Intercept context-request events and redirect them to targetElement\n this.#contextRequestHandler = (event: Event) => {\n if (this.targetElement && event.type === \"context-request\") {\n event.stopPropagation();\n this.targetElement.dispatchEvent(\n new (event.constructor as any)(event.type, event),\n );\n }\n };\n this.addEventListener(\n \"context-request\",\n this.#contextRequestHandler,\n true,\n );\n }\n\n #subscribeToTargetContext() {\n if (!this.targetElement) return;\n\n this.#contextUnsubscribe?.();\n\n // Unsubscribe from all additional contexts\n for (const unsubscribe of this.#additionalContextUnsubscribes.values()) {\n unsubscribe();\n }\n this.#additionalContextUnsubscribes.clear();\n\n // Subscribe to efContext\n const event = new ContextRequestEvent(\n contextToProxy,\n this,\n (value, unsubscribe) => {\n (this as any).contextFromParent = value;\n this.#contextUnsubscribe = unsubscribe;\n },\n true,\n );\n this.targetElement.dispatchEvent(event);\n\n // Subscribe to additional contexts that controls commonly need\n const additionalContexts: Array<[Context<any, any>, string]> = [\n [playingContext, \"playing\"],\n [loopContext, \"loop\"],\n [currentTimeContext, \"currentTimeMs\"],\n [durationContext, \"durationMs\"],\n ];\n\n for (const [context, propertyName] of additionalContexts) {\n const contextEvent = new ContextRequestEvent(\n context,\n this,\n (value, unsubscribe) => {\n // Update the control's property if it exists\n if (propertyName in this) {\n (this as any)[propertyName] = value;\n }\n this.#additionalContextUnsubscribes.set(context, unsubscribe);\n },\n true,\n );\n this.targetElement.dispatchEvent(contextEvent);\n }\n }\n\n updated(changedProperties: Map<string | number | symbol, unknown>): void {\n super.updated?.(changedProperties);\n\n if (changedProperties.has(\"targetElement\") && this.targetElement) {\n if (\n isEFTemporal(this.targetElement) &&\n !isControllable(this.targetElement)\n ) {\n console.warn(\n \"Control element is targeting a non-root temporal element without playbackController. \" +\n \"Controls can only target root temporal elements (not nested within a timegroup). \" +\n \"Target element:\",\n this.targetElement,\n );\n }\n this.#subscribeToTargetContext();\n }\n\n if (changedProperties.has(\"target\")) {\n if (this.target && !this.#targetController) {\n this.#targetController = new TargetController(\n this as any as LitElement & {\n targetElement: Element | null;\n target: string;\n },\n );\n }\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.#contextUnsubscribe?.();\n for (const unsubscribe of this.#additionalContextUnsubscribes.values()) {\n unsubscribe();\n }\n this.#additionalContextUnsubscribes.clear();\n if (this.#contextRequestHandler) {\n this.removeEventListener(\n \"context-request\",\n this.#contextRequestHandler,\n true,\n );\n }\n }\n }\n\n return TargetOrContextClass as Constructor<{\n target: string;\n targetElement: ControllableInterface | null;\n effectiveContext: ControllableInterface | null;\n }> &\n T;\n}\n"],"mappings":";;;;;;;;;;;AAYA,IAAM,sBAAN,cAAkC,MAAM;CAMtC,YACE,SACA,eACA,UACA,WACA;AACA,QAAM,mBAAmB;GAAE,SAAS;GAAM,UAAU;GAAM,CAAC;AAC3D,OAAK,UAAU;AACf,OAAK,gBAAgB;AACrB,OAAK,WAAW;AAChB,OAAK,YAAY,aAAa;;;AAIlC,SAAgB,qBACd,YACA,gBACA;CACA,MAAM,6BAA6B,WAAW;;;iBAEnC;wBAGqC;4BAII;;EAElD;EACA;EACA;EACA,iDAAiC,IAAI,KAAoC;EAEzE,IAAI,mBAAiD;AACnD,UAAO,KAAK,iBAAiB,KAAK;;EAGpC,oBAAoB;AAClB,SAAM,mBAAmB;AACzB,OAAI,KAAK,OACP,OAAKA,mBAAoB,IAAI,iBAC3B,KAID;AAIH,SAAKC,yBAA0B,UAAiB;AAC9C,QAAI,KAAK,iBAAiB,MAAM,SAAS,mBAAmB;AAC1D,WAAM,iBAAiB;AACvB,UAAK,cAAc,cACjB,IAAK,MAAM,YAAoB,MAAM,MAAM,MAAM,CAClD;;;AAGL,QAAK,iBACH,mBACA,MAAKA,uBACL,KACD;;EAGH,4BAA4B;AAC1B,OAAI,CAAC,KAAK,cAAe;AAEzB,SAAKC,sBAAuB;AAG5B,QAAK,MAAM,eAAe,MAAKC,8BAA+B,QAAQ,CACpE,cAAa;AAEf,SAAKA,8BAA+B,OAAO;GAG3C,MAAM,QAAQ,IAAI,oBAChB,gBACA,OACC,OAAO,gBAAgB;AACtB,IAAC,KAAa,oBAAoB;AAClC,UAAKD,qBAAsB;MAE7B,KACD;AACD,QAAK,cAAc,cAAc,MAAM;GAGvC,MAAME,qBAAyD;IAC7D,CAAC,gBAAgB,UAAU;IAC3B,CAAC,aAAa,OAAO;IACrB,CAAC,oBAAoB,gBAAgB;IACrC,CAAC,iBAAiB,aAAa;IAChC;AAED,QAAK,MAAM,CAAC,SAAS,iBAAiB,oBAAoB;IACxD,MAAM,eAAe,IAAI,oBACvB,SACA,OACC,OAAO,gBAAgB;AAEtB,SAAI,gBAAgB,KAClB,CAAC,KAAa,gBAAgB;AAEhC,WAAKD,8BAA+B,IAAI,SAAS,YAAY;OAE/D,KACD;AACD,SAAK,cAAc,cAAc,aAAa;;;EAIlD,QAAQ,mBAAiE;AACvE,SAAM,UAAU,kBAAkB;AAElC,OAAI,kBAAkB,IAAI,gBAAgB,IAAI,KAAK,eAAe;AAChE,QACE,aAAa,KAAK,cAAc,IAChC,CAAC,eAAe,KAAK,cAAc,CAEnC,SAAQ,KACN,yLAGA,KAAK,cACN;AAEH,UAAKE,0BAA2B;;AAGlC,OAAI,kBAAkB,IAAI,SAAS,EACjC;QAAI,KAAK,UAAU,CAAC,MAAKL,iBACvB,OAAKA,mBAAoB,IAAI,iBAC3B,KAID;;;EAKP,uBAAuB;AACrB,SAAM,sBAAsB;AAC5B,SAAKE,sBAAuB;AAC5B,QAAK,MAAM,eAAe,MAAKC,8BAA+B,QAAQ,CACpE,cAAa;AAEf,SAAKA,8BAA+B,OAAO;AAC3C,OAAI,MAAKF,sBACP,MAAK,oBACH,mBACA,MAAKA,uBACL,KACD;;;aAxIJ,SAAS,EAAE,MAAM,QAAQ,CAAC;aAG1B,OAAO;aAIP,QAAQ;EAAE,SAAS;EAAgB,WAAW;EAAM,CAAC;AAsIxD,QAAO"}
|
|
1
|
+
{"version":3,"file":"TargetOrContextMixin.js","names":["#targetController","#contextRequestHandler","#contextUnsubscribe","#additionalContextUnsubscribes","#directTemporalSubscription","#unsubscribeAll","#tryDirectTemporalSubscription","additionalContexts: Array<[Context<any, any>, string]>","#subscribeToTargetContext"],"sources":["../../src/gui/TargetOrContextMixin.ts"],"sourcesContent":["import { type Context, consume } from \"@lit/context\";\nimport type { LitElement } from \"lit\";\nimport { property, state } from \"lit/decorators.js\";\nimport {\n isEFTemporal,\n type TemporalMixinInterface,\n} from \"../elements/EFTemporal.js\";\nimport { TargetController } from \"../elements/TargetController.js\";\nimport {\n type ControllableInterface,\n type ControllableSubscription,\n isControllable,\n determineTargetType,\n createDirectTemporalSubscription,\n} from \"./Controllable.js\";\nimport { currentTimeContext } from \"./currentTimeContext.js\";\nimport { durationContext } from \"./durationContext.js\";\nimport { loopContext, playingContext } from \"./playingContext.js\";\n\ntype Constructor<T = {}> = new (...args: any[]) => T;\n\nclass ContextRequestEvent extends Event {\n context: Context<any, any>;\n contextTarget: Element;\n callback: (value: any, unsubscribe: () => void) => void;\n subscribe: boolean;\n\n constructor(\n context: Context<any, any>,\n contextTarget: Element,\n callback: (value: any, unsubscribe: () => void) => void,\n subscribe: boolean,\n ) {\n super(\"context-request\", { bubbles: true, composed: true });\n this.context = context;\n this.contextTarget = contextTarget;\n this.callback = callback;\n this.subscribe = subscribe ?? false;\n }\n}\n\nexport function TargetOrContextMixin<T extends Constructor<LitElement>>(\n superClass: T,\n contextToProxy: Context<any, any>,\n) {\n class TargetOrContextClass extends superClass {\n @property({ type: String })\n target = \"\";\n\n @state()\n targetElement: ControllableInterface | null = null;\n\n // @ts-expect-error contextToProxy is generic but provides ControllableInterface at runtime\n @consume({ context: contextToProxy, subscribe: true })\n contextFromParent: ControllableInterface | null = null;\n\n #targetController?: TargetController;\n #contextUnsubscribe?: () => void;\n #contextRequestHandler?: (event: Event) => void;\n #additionalContextUnsubscribes = new Map<Context<any, any>, () => void>();\n #directTemporalSubscription?: ControllableSubscription;\n\n get effectiveContext(): ControllableInterface | null {\n return this.targetElement ?? this.contextFromParent;\n }\n\n connectedCallback() {\n super.connectedCallback();\n if (this.target) {\n this.#targetController = new TargetController(\n this as any as LitElement & {\n targetElement: Element | null;\n target: string;\n },\n );\n }\n\n // Intercept context-request events and redirect them to targetElement\n this.#contextRequestHandler = (event: Event) => {\n if (this.targetElement && event.type === \"context-request\") {\n event.stopPropagation();\n this.targetElement.dispatchEvent(\n new (event.constructor as any)(event.type, event),\n );\n }\n };\n this.addEventListener(\n \"context-request\",\n this.#contextRequestHandler,\n true,\n );\n }\n\n #unsubscribeAll() {\n this.#contextUnsubscribe?.();\n this.#contextUnsubscribe = undefined;\n for (const unsubscribe of this.#additionalContextUnsubscribes.values()) {\n unsubscribe();\n }\n this.#additionalContextUnsubscribes.clear();\n this.#directTemporalSubscription?.unsubscribe();\n this.#directTemporalSubscription = undefined;\n }\n\n #tryDirectTemporalSubscription(): boolean {\n if (!this.targetElement) return false;\n\n const targetType = determineTargetType(this.targetElement);\n if (targetType !== \"direct-temporal\") return false;\n\n this.#directTemporalSubscription = createDirectTemporalSubscription(\n this.targetElement as unknown as TemporalMixinInterface & HTMLElement,\n {\n onPlayingChange: (value) => {\n (this as any).playing = value;\n },\n onLoopChange: (value) => {\n if (\"loop\" in this) (this as any).loop = value;\n },\n onCurrentTimeMsChange: (value) => {\n if (\"currentTimeMs\" in this) (this as any).currentTimeMs = value;\n },\n onDurationMsChange: (value) => {\n if (\"durationMs\" in this) (this as any).durationMs = value;\n },\n onTargetTemporalChange: () => {},\n },\n );\n return true;\n }\n\n #subscribeToTargetContext() {\n if (!this.targetElement) return;\n\n this.#unsubscribeAll();\n\n if (this.#tryDirectTemporalSubscription()) return;\n\n // Temporal target without PlaybackController yet — wait for initialization\n if (isEFTemporal(this.targetElement)) {\n const target = this.targetElement as unknown as TemporalMixinInterface &\n HTMLElement;\n target.updateComplete.then(() => {\n if ((this.targetElement as unknown) !== target) return;\n if (!this.#tryDirectTemporalSubscription()) {\n // Still not ready — one more cycle (PlaybackController created in updateComplete.then)\n target.updateComplete.then(() => {\n if ((this.targetElement as unknown) !== target) return;\n this.#tryDirectTemporalSubscription();\n });\n }\n });\n return;\n }\n\n // Context-provider path (EFPreview, etc.)\n const event = new ContextRequestEvent(\n contextToProxy,\n this,\n (value, unsubscribe) => {\n (this as any).contextFromParent = value;\n this.#contextUnsubscribe = unsubscribe;\n },\n true,\n );\n this.targetElement.dispatchEvent(event);\n\n const additionalContexts: Array<[Context<any, any>, string]> = [\n [playingContext, \"playing\"],\n [loopContext, \"loop\"],\n [currentTimeContext, \"currentTimeMs\"],\n [durationContext, \"durationMs\"],\n ];\n\n for (const [context, propertyName] of additionalContexts) {\n const contextEvent = new ContextRequestEvent(\n context,\n this,\n (value, unsubscribe) => {\n if (propertyName in this) {\n (this as any)[propertyName] = value;\n }\n this.#additionalContextUnsubscribes.set(context, unsubscribe);\n },\n true,\n );\n this.targetElement.dispatchEvent(contextEvent);\n }\n }\n\n updated(changedProperties: Map<string | number | symbol, unknown>): void {\n super.updated?.(changedProperties);\n\n if (changedProperties.has(\"targetElement\") && this.targetElement) {\n if (\n isEFTemporal(this.targetElement) &&\n !isControllable(this.targetElement)\n ) {\n console.warn(\n \"Control element is targeting a non-root temporal element without playbackController. \" +\n \"Controls can only target root temporal elements (not nested within a timegroup). \" +\n \"Target element:\",\n this.targetElement,\n );\n }\n this.#subscribeToTargetContext();\n }\n\n if (changedProperties.has(\"target\")) {\n if (this.target && !this.#targetController) {\n this.#targetController = new TargetController(\n this as any as LitElement & {\n targetElement: Element | null;\n target: string;\n },\n );\n }\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.#unsubscribeAll();\n if (this.#contextRequestHandler) {\n this.removeEventListener(\n \"context-request\",\n this.#contextRequestHandler,\n true,\n );\n }\n }\n }\n\n return TargetOrContextClass as Constructor<{\n target: string;\n targetElement: ControllableInterface | null;\n effectiveContext: ControllableInterface | null;\n }> &\n T;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Editframe GUI Theme System
|
|
3
|
+
*
|
|
4
|
+
* Global design tokens for all ef-* components.
|
|
5
|
+
* CSS custom properties inherit through shadow DOM boundaries.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* - Dark theme is default
|
|
9
|
+
* - Add .light class to any ancestor to activate light mode
|
|
10
|
+
* - Override tokens on any ancestor to customize theme
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
:root,
|
|
14
|
+
:host {
|
|
15
|
+
/* Backgrounds — Strong hierarchy with deep blacks */
|
|
16
|
+
--ef-color-bg: #0a0a0a; /* Deep black workspace */
|
|
17
|
+
--ef-color-bg-panel: #111111; /* Elevated panels (hierarchy, timeline header) */
|
|
18
|
+
--ef-color-bg-elevated: #1a1a1a; /* Dropdowns, popovers */
|
|
19
|
+
--ef-color-bg-inset: #050505; /* Track wells (darker than workspace) */
|
|
20
|
+
|
|
21
|
+
/* Borders — Visible but refined */
|
|
22
|
+
--ef-color-border: rgba(255, 255, 255, 0.15); /* More visible borders */
|
|
23
|
+
--ef-color-border-subtle: rgba(255, 255, 255, 0.08); /* Subtle dividers */
|
|
24
|
+
|
|
25
|
+
/* Text — High contrast */
|
|
26
|
+
--ef-color-text: #FAFAFA; /* Primary text */
|
|
27
|
+
--ef-color-text-muted: #9CA3AF; /* Labels, timestamps, hints */
|
|
28
|
+
--ef-color-text-subtle: #6B7280; /* Empty states, placeholders */
|
|
29
|
+
|
|
30
|
+
/* Interactive states — Neutral hover, accent for selection */
|
|
31
|
+
--ef-color-primary: #3B82F6; /* Blue-500 — primary actions (not red) */
|
|
32
|
+
--ef-color-primary-hover: #60A5FA; /* Blue-400 — primary hover */
|
|
33
|
+
--ef-color-primary-subtle: rgba(59, 130, 246, 0.15); /* Low-opacity accent */
|
|
34
|
+
--ef-color-hover: rgba(255, 255, 255, 0.06); /* Neutral gray hover */
|
|
35
|
+
--ef-color-selected: rgba(59, 130, 246, 0.2); /* Selected state (blue) */
|
|
36
|
+
--ef-color-selected-subtle: rgba(59, 130, 246, 0.1); /* Ancestor/related selection */
|
|
37
|
+
--ef-color-focused: rgba(59, 130, 246, 0.25); /* Keyboard focus (blue) */
|
|
38
|
+
|
|
39
|
+
/* Semantic colors — Desaturated for professional GUI */
|
|
40
|
+
--ef-color-danger: #DC2626; /* Red-600 (less bright) */
|
|
41
|
+
--ef-color-success: #059669; /* Emerald-600 (more muted) */
|
|
42
|
+
--ef-color-warning: #D97706; /* Amber-600 (less bright) */
|
|
43
|
+
--ef-color-playhead: #DC2626; /* Red-600 for playhead */
|
|
44
|
+
--ef-color-error: #DC2626; /* Error state */
|
|
45
|
+
|
|
46
|
+
/* Element type colors — Desaturated, professional */
|
|
47
|
+
--ef-color-type-video: #3B82F6; /* Blue-500 (less bright) */
|
|
48
|
+
--ef-color-type-audio: #10B981; /* Emerald-500 (more muted) */
|
|
49
|
+
--ef-color-type-image: #8B5CF6; /* Violet-500 (less bright) */
|
|
50
|
+
--ef-color-type-text: #F59E0B; /* Amber-500 (less bright) */
|
|
51
|
+
--ef-color-type-captions: #14B8A6; /* Teal-500 (distinct from audio) */
|
|
52
|
+
--ef-color-type-timegroup: #64748B; /* Slate-500 (more muted) */
|
|
53
|
+
|
|
54
|
+
/* Typography */
|
|
55
|
+
--ef-font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
56
|
+
--ef-font-size-xs: 0.75rem; /* 12px */
|
|
57
|
+
--ef-font-size-sm: 0.875rem; /* 14px */
|
|
58
|
+
--ef-font-size-base: 1rem; /* 16px */
|
|
59
|
+
|
|
60
|
+
/* Layout */
|
|
61
|
+
--ef-row-height: 24px; /* timeline row height */
|
|
62
|
+
--ef-track-height: 24px; /* track item height */
|
|
63
|
+
--ef-hierarchy-width: 200px; /* hierarchy panel width */
|
|
64
|
+
--ef-thumbnail-gap: 2px; /* minimum gap between thumbnails */
|
|
65
|
+
--ef-radius-sm: 0.25rem; /* 4px */
|
|
66
|
+
--ef-radius-md: 0.375rem; /* 6px */
|
|
67
|
+
|
|
68
|
+
/* Filmstrip component tokens (reference globals) */
|
|
69
|
+
--filmstrip-bg: var(--ef-color-bg-inset);
|
|
70
|
+
--filmstrip-item-bg: rgba(17, 17, 17, 0.9); /* Darker */
|
|
71
|
+
--filmstrip-item-focused: rgba(229, 57, 53, 0.3); /* Poster red */
|
|
72
|
+
--filmstrip-border: var(--ef-color-border);
|
|
73
|
+
--filmstrip-caption-bg: rgba(76, 175, 80, 0.15); /* Green with more opacity */
|
|
74
|
+
--filmstrip-caption-border: rgba(76, 175, 80, 0.5);
|
|
75
|
+
--filmstrip-segment-bg: rgba(76, 175, 80, 0.3);
|
|
76
|
+
--filmstrip-segment-border: rgba(76, 175, 80, 0.6);
|
|
77
|
+
--filmstrip-waveform-bg: rgba(0, 0, 0, 0.4);
|
|
78
|
+
--filmstrip-waveform-border: rgba(255, 255, 255, 0.15);
|
|
79
|
+
--filmstrip-timegroup-focused: var(--ef-color-focused);
|
|
80
|
+
--filmstrip-animation-bg: rgba(229, 57, 53, 0.2); /* Poster red */
|
|
81
|
+
--filmstrip-keyframe-bg: rgba(229, 57, 53, 0.4); /* Poster red */
|
|
82
|
+
|
|
83
|
+
/* Trim handle tokens */
|
|
84
|
+
--trim-handle-color: rgba(255, 255, 255, 0.7);
|
|
85
|
+
--trim-handle-active-color: var(--ef-color-primary);
|
|
86
|
+
--trim-overlay-color: rgba(0, 0, 0, 0.4);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* Light mode theme — High contrast, clean professional */
|
|
90
|
+
.light,
|
|
91
|
+
:host(.light),
|
|
92
|
+
:host-context(.light) {
|
|
93
|
+
/* Backgrounds — Clear hierarchy with strong separation */
|
|
94
|
+
--ef-color-bg: #FFFFFF; /* Pure white workspace */
|
|
95
|
+
--ef-color-bg-panel: #F8F8F8; /* Very light gray panels */
|
|
96
|
+
--ef-color-bg-elevated: #FFFFFF; /* Pure white elevated */
|
|
97
|
+
--ef-color-bg-inset: #EEEEEE; /* Light gray inset (track wells) */
|
|
98
|
+
|
|
99
|
+
/* Borders — Strong, visible */
|
|
100
|
+
--ef-color-border: rgba(0, 0, 0, 0.20); /* Clearly visible borders */
|
|
101
|
+
--ef-color-border-subtle: rgba(0, 0, 0, 0.10); /* Subtle but visible dividers */
|
|
102
|
+
|
|
103
|
+
/* Text — Maximum contrast */
|
|
104
|
+
--ef-color-text: #0A0A0A; /* Near black (neutral-950) */
|
|
105
|
+
--ef-color-text-muted: #404040; /* Neutral-700 */
|
|
106
|
+
--ef-color-text-subtle: #666666; /* Neutral-600 */
|
|
107
|
+
|
|
108
|
+
/* Interactive states — Neutral hover, blue for selection */
|
|
109
|
+
--ef-color-primary: #2563EB; /* Blue-600 — primary actions */
|
|
110
|
+
--ef-color-primary-hover: #1D4ED8; /* Blue-700 — primary hover */
|
|
111
|
+
--ef-color-primary-subtle: rgba(37, 99, 235, 0.12);
|
|
112
|
+
--ef-color-hover: rgba(0, 0, 0, 0.06); /* Visible neutral hover */
|
|
113
|
+
--ef-color-selected: rgba(37, 99, 235, 0.18); /* Stronger selected state */
|
|
114
|
+
--ef-color-selected-subtle: rgba(37, 99, 235, 0.10); /* Visible ancestor selection */
|
|
115
|
+
--ef-color-focused: rgba(37, 99, 235, 0.25); /* Strong keyboard focus */
|
|
116
|
+
|
|
117
|
+
/* Semantic colors — Desaturated but visible */
|
|
118
|
+
--ef-color-danger: #DC2626; /* Red-600 */
|
|
119
|
+
--ef-color-success: #059669; /* Emerald-600 */
|
|
120
|
+
--ef-color-warning: #D97706; /* Amber-600 */
|
|
121
|
+
--ef-color-playhead: #DC2626; /* Red-600 for playhead */
|
|
122
|
+
--ef-color-error: #DC2626;
|
|
123
|
+
|
|
124
|
+
/* Element type colors — More saturated for light mode visibility */
|
|
125
|
+
--ef-color-type-video: #2563EB; /* Blue-600 */
|
|
126
|
+
--ef-color-type-audio: #059669; /* Emerald-600 */
|
|
127
|
+
--ef-color-type-image: #7C3AED; /* Violet-600 */
|
|
128
|
+
--ef-color-type-text: #EA580C; /* Orange-600 */
|
|
129
|
+
--ef-color-type-captions: #0891B2; /* Cyan-600 */
|
|
130
|
+
--ef-color-type-timegroup: #475569; /* Slate-600 */
|
|
131
|
+
|
|
132
|
+
/* Filmstrip light mode adjustments */
|
|
133
|
+
--filmstrip-item-bg: rgba(238, 238, 238, 0.95);
|
|
134
|
+
--filmstrip-waveform-bg: rgba(0, 0, 0, 0.06);
|
|
135
|
+
--filmstrip-waveform-border: rgba(0, 0, 0, 0.12);
|
|
136
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { SelectionContext } from "../../canvas/selection/selectionContext.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as lit11 from "lit";
|
|
3
3
|
import { LitElement, PropertyValues } from "lit";
|
|
4
4
|
import * as lit_html11 from "lit-html";
|
|
5
5
|
|
|
6
6
|
//#region src/gui/hierarchy/EFHierarchy.d.ts
|
|
7
7
|
declare const EFHierarchy_base: typeof LitElement;
|
|
8
8
|
declare class EFHierarchy extends EFHierarchy_base {
|
|
9
|
-
static styles:
|
|
9
|
+
static styles: lit11.CSSResult[];
|
|
10
10
|
target: string;
|
|
11
11
|
header: string;
|
|
12
12
|
showHeader: boolean;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { TWMixin } from "../TWMixin2.js";
|
|
1
2
|
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
|
|
2
3
|
import { isEFTemporal } from "../../elements/EFTemporal.js";
|
|
3
|
-
import { TWMixin } from "../TWMixin2.js";
|
|
4
4
|
import { TargetController } from "../../elements/TargetController.js";
|
|
5
5
|
import { selectionContext } from "../../canvas/selection/selectionContext.js";
|
|
6
6
|
import { hierarchyContext } from "./hierarchyContext.js";
|
|
@@ -113,30 +113,20 @@ let EFHierarchy = class EFHierarchy$1 extends TWMixin(LitElement) {
|
|
|
113
113
|
height: 100%;
|
|
114
114
|
font-size: 12px;
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
--hierarchy-
|
|
118
|
-
--hierarchy-
|
|
119
|
-
--hierarchy-
|
|
120
|
-
--hierarchy-
|
|
121
|
-
--hierarchy-
|
|
122
|
-
--hierarchy-
|
|
123
|
-
--hierarchy-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
:host(.light) {
|
|
127
|
-
--hierarchy-bg: rgb(241 245 249);
|
|
128
|
-
--hierarchy-border: rgb(203 213 225);
|
|
129
|
-
--hierarchy-text: rgb(30 41 59);
|
|
130
|
-
--hierarchy-hover-bg: rgba(100, 116, 139, 0.15);
|
|
131
|
-
--hierarchy-selected-bg: rgba(59, 130, 246, 0.2);
|
|
132
|
-
--hierarchy-ancestor-selected-bg: rgba(59, 130, 246, 0.1);
|
|
133
|
-
--hierarchy-focused-bg: rgba(100, 116, 139, 0.25);
|
|
116
|
+
/* Component tokens (reference globals from ef-theme.css) */
|
|
117
|
+
--hierarchy-bg: var(--ef-color-bg);
|
|
118
|
+
--hierarchy-border: var(--ef-color-border);
|
|
119
|
+
--hierarchy-text: var(--ef-color-text);
|
|
120
|
+
--hierarchy-hover-bg: var(--ef-color-hover);
|
|
121
|
+
--hierarchy-selected-bg: var(--ef-color-selected);
|
|
122
|
+
--hierarchy-ancestor-selected-bg: var(--ef-color-selected-subtle);
|
|
123
|
+
--hierarchy-focused-bg: var(--ef-color-focused);
|
|
124
|
+
--hierarchy-drop-indicator: var(--ef-color-primary);
|
|
134
125
|
}
|
|
135
126
|
|
|
136
127
|
.hierarchy-container {
|
|
137
128
|
background: var(--hierarchy-bg);
|
|
138
129
|
color: var(--hierarchy-text);
|
|
139
|
-
min-height: 100%;
|
|
140
130
|
padding: 4px 0;
|
|
141
131
|
}
|
|
142
132
|
|
|
@@ -146,7 +136,7 @@ let EFHierarchy = class EFHierarchy$1 extends TWMixin(LitElement) {
|
|
|
146
136
|
font-size: 11px;
|
|
147
137
|
text-transform: uppercase;
|
|
148
138
|
letter-spacing: 0.05em;
|
|
149
|
-
color:
|
|
139
|
+
color: var(--ef-color-text-muted);
|
|
150
140
|
border-bottom: 1px solid var(--hierarchy-border);
|
|
151
141
|
margin-bottom: 4px;
|
|
152
142
|
}
|
|
@@ -154,7 +144,7 @@ let EFHierarchy = class EFHierarchy$1 extends TWMixin(LitElement) {
|
|
|
154
144
|
.empty {
|
|
155
145
|
padding: 16px;
|
|
156
146
|
text-align: center;
|
|
157
|
-
color:
|
|
147
|
+
color: var(--ef-color-text-subtle);
|
|
158
148
|
font-style: italic;
|
|
159
149
|
}
|
|
160
150
|
`];
|
|
@@ -303,8 +293,8 @@ let EFHierarchy = class EFHierarchy$1 extends TWMixin(LitElement) {
|
|
|
303
293
|
render() {
|
|
304
294
|
const roots = this.getRootElements();
|
|
305
295
|
return html`
|
|
306
|
-
<div class="hierarchy-container">
|
|
307
|
-
${this.showHeader ? html`<div class="header">${this.header}</div>` : nothing}
|
|
296
|
+
<div class="hierarchy-container" part="list">
|
|
297
|
+
${this.showHeader ? html`<div class="header" part="header">${this.header}</div>` : nothing}
|
|
308
298
|
${roots.length > 0 ? renderHierarchyChildren(roots, this.hideSelectors, this.showSelectors, true) : html`<div class="empty">No elements</div>`}
|
|
309
299
|
</div>
|
|
310
300
|
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EFHierarchy.js","names":["EFHierarchy","selectedId: string | null"],"sources":["../../../src/gui/hierarchy/EFHierarchy.ts"],"sourcesContent":["import { consume, provide } from \"@lit/context\";\nimport { css, html, LitElement, nothing, type PropertyValues } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\n\nimport { isEFTemporal } from \"../../elements/EFTemporal.js\";\nimport { selectionContext } from \"../../canvas/selection/selectionContext.js\";\nimport { TargetController } from \"../../elements/TargetController.js\";\nimport { TWMixin } from \"../TWMixin.js\";\nimport {\n type HierarchyActions,\n type HierarchyContext,\n type HierarchyState,\n hierarchyContext,\n} from \"./hierarchyContext.js\";\nimport { renderHierarchyChildren } from \"./EFHierarchyItem.js\";\nimport type { EFCanvas } from \"../../canvas/EFCanvas.js\";\n\n@customElement(\"ef-hierarchy\")\nexport class EFHierarchy extends TWMixin(LitElement) {\n static styles = [\n css`\n :host {\n display: block;\n overflow: auto;\n height: 100%;\n font-size: 12px;\n \n --hierarchy-bg: rgb(30 41 59);\n --hierarchy-border: rgb(71 85 105);\n --hierarchy-text: rgb(226 232 240);\n --hierarchy-hover-bg: rgba(148, 163, 184, 0.2);\n --hierarchy-selected-bg: rgba(59, 130, 246, 0.3);\n --hierarchy-ancestor-selected-bg: rgba(59, 130, 246, 0.15);\n --hierarchy-focused-bg: rgba(148, 163, 184, 0.4);\n --hierarchy-drop-indicator: #3b82f6;\n }\n \n :host(.light) {\n --hierarchy-bg: rgb(241 245 249);\n --hierarchy-border: rgb(203 213 225);\n --hierarchy-text: rgb(30 41 59);\n --hierarchy-hover-bg: rgba(100, 116, 139, 0.15);\n --hierarchy-selected-bg: rgba(59, 130, 246, 0.2);\n --hierarchy-ancestor-selected-bg: rgba(59, 130, 246, 0.1);\n --hierarchy-focused-bg: rgba(100, 116, 139, 0.25);\n }\n \n .hierarchy-container {\n background: var(--hierarchy-bg);\n color: var(--hierarchy-text);\n min-height: 100%;\n padding: 4px 0;\n }\n \n .header {\n padding: 8px 12px;\n font-weight: 600;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: rgba(148, 163, 184, 0.8);\n border-bottom: 1px solid var(--hierarchy-border);\n margin-bottom: 4px;\n }\n \n .empty {\n padding: 16px;\n text-align: center;\n color: rgba(148, 163, 184, 0.6);\n font-style: italic;\n }\n `,\n ];\n\n @property({ type: String })\n target = \"\";\n\n @property({ type: String })\n header = \"\";\n\n @property({ type: Boolean, attribute: \"show-header\" })\n showHeader = false;\n\n @property({ type: Array, attribute: false })\n hideSelectors?: string[];\n\n @property({ type: Array, attribute: false })\n showSelectors?: string[];\n\n @state()\n targetElement: Element | null = null;\n\n private targetController?: TargetController;\n\n @consume({ context: selectionContext, subscribe: true })\n canvasSelectionContext?: import(\"../../canvas/selection/selectionContext.js\").SelectionContext;\n\n /**\n * Get the target canvas element.\n * The canvas is the source of truth for selection and highlight state.\n */\n private getCanvas(): EFCanvas | null {\n // First try TargetController (for registered elements like EFCanvas)\n if (this.targetElement && (this.targetElement as any).selectionContext) {\n return this.targetElement as EFCanvas;\n }\n // Fall back to direct lookup for any element with matching ID\n if (this.target) {\n const target = document.getElementById(this.target);\n if (target && (target as any).selectionContext) {\n return target as EFCanvas;\n }\n }\n return null;\n }\n\n /**\n * Get canvas selection context from the target canvas element.\n * Used when hierarchy is a sibling of canvas (can't access via Lit context).\n */\n private getCanvasSelectionContext():\n | import(\"../../canvas/selection/selectionContext.js\").SelectionContext\n | undefined {\n // First try Lit context (works when hierarchy is inside canvas)\n if (this.canvasSelectionContext) {\n return this.canvasSelectionContext;\n }\n // Use target canvas\n const canvas = this.getCanvas();\n return canvas?.selectionContext;\n }\n\n /**\n * Get the currently highlighted element from the canvas.\n */\n getHighlightedElement(): HTMLElement | null {\n const canvas = this.getCanvas();\n return canvas?.highlightedElement ?? null;\n }\n\n /**\n * Set the highlighted element on the canvas.\n * Called when user hovers an item in the hierarchy.\n */\n setHighlightedElement(element: HTMLElement | null): void {\n const canvas = this.getCanvas();\n canvas?.setHighlightedElement(element);\n }\n\n @state()\n private hierarchyState: HierarchyState = {\n selectedElementId: null,\n expandedIds: new Set(),\n draggedElementId: null,\n dropTargetId: null,\n dropPosition: null,\n };\n\n private selectionChangeHandler?: (event: CustomEvent) => void;\n\n private hierarchyActions: HierarchyActions = {\n select: (elementId: string | null) => {\n const selectionCtx = this.getCanvasSelectionContext();\n if (selectionCtx) {\n if (elementId) {\n // Ensure element is registered with canvas before selecting\n const element = document.getElementById(elementId);\n if (element) {\n // Find the canvas element\n const canvas = element.closest(\"ef-canvas\") as any;\n if (canvas && canvas.tryRegisterElement) {\n // Try to register if not already registered\n canvas.tryRegisterElement(element);\n }\n }\n\n // Select the element directly by its ID\n selectionCtx.select(elementId);\n } else {\n selectionCtx.clear();\n }\n } else {\n this.hierarchyState = {\n ...this.hierarchyState,\n selectedElementId: elementId,\n };\n }\n this.dispatchEvent(\n new CustomEvent(\"hierarchy-select\", {\n detail: { elementId },\n bubbles: true,\n composed: true,\n }),\n );\n },\n\n toggleExpanded: (elementId: string) => {\n const newExpanded = new Set(this.hierarchyState.expandedIds);\n if (newExpanded.has(elementId)) {\n newExpanded.delete(elementId);\n } else {\n newExpanded.add(elementId);\n }\n this.hierarchyState = {\n ...this.hierarchyState,\n expandedIds: newExpanded,\n };\n },\n\n setExpanded: (elementId: string, expanded: boolean) => {\n const newExpanded = new Set(this.hierarchyState.expandedIds);\n if (expanded) {\n newExpanded.add(elementId);\n } else {\n newExpanded.delete(elementId);\n }\n this.hierarchyState = {\n ...this.hierarchyState,\n expandedIds: newExpanded,\n };\n },\n\n startDrag: (elementId: string) => {\n this.hierarchyState = {\n ...this.hierarchyState,\n draggedElementId: elementId,\n };\n },\n\n updateDropTarget: (\n targetId: string | null,\n position: \"before\" | \"after\" | \"inside\" | null,\n ) => {\n if (targetId === this.hierarchyState.draggedElementId) {\n return;\n }\n this.hierarchyState = {\n ...this.hierarchyState,\n dropTargetId: targetId,\n dropPosition: position,\n };\n },\n\n endDrag: () => {\n this.hierarchyState = {\n ...this.hierarchyState,\n draggedElementId: null,\n dropTargetId: null,\n dropPosition: null,\n };\n },\n\n reorder: (\n sourceId: string,\n targetId: string,\n position: \"before\" | \"after\" | \"inside\",\n ) => {\n this.dispatchEvent(\n new CustomEvent(\"hierarchy-reorder\", {\n detail: { sourceId, targetId, position },\n bubbles: true,\n composed: true,\n }),\n );\n },\n };\n\n @provide({ context: hierarchyContext })\n @state()\n private providedContext: HierarchyContext = {\n state: this.hierarchyState,\n actions: this.hierarchyActions,\n getCanvasSelectionContext: () => this.getCanvasSelectionContext(),\n getHighlightedElement: () => this.getHighlightedElement(),\n setHighlightedElement: (el) => this.setHighlightedElement(el),\n };\n\n private getTargetElement(): Element | null {\n // First try TargetController (for registered elements like EFCanvas)\n if (this.targetElement) {\n return this.targetElement;\n }\n // Fall back to direct lookup for any element with matching ID\n if (this.target) {\n return document.getElementById(this.target);\n }\n return null;\n }\n\n private getRootElements(): Element[] {\n const target = this.getTargetElement();\n if (!target) return [];\n\n if (isEFTemporal(target)) {\n return [target];\n }\n\n return Array.from(target.children);\n }\n\n private initializeExpandedState(): void {\n const roots = this.getRootElements();\n const newExpanded = new Set<string>();\n\n const addExpandedIds = (element: Element) => {\n if (element.id) {\n newExpanded.add(element.id);\n }\n for (const child of Array.from(element.children)) {\n if (child.children.length > 0) {\n addExpandedIds(child);\n }\n }\n };\n\n for (const root of roots) {\n addExpandedIds(root);\n }\n\n this.hierarchyState = {\n ...this.hierarchyState,\n expandedIds: newExpanded,\n };\n }\n\n select(elementId: string | null): void {\n this.hierarchyActions.select(elementId);\n }\n\n getSelectedElementId(): string | null {\n const selectionCtx = this.getCanvasSelectionContext();\n if (selectionCtx) {\n const selectedIds = Array.from(selectionCtx.selectedIds);\n if (selectedIds.length === 0) {\n return null;\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return selectedIds[0]!;\n }\n return this.hierarchyState.selectedElementId;\n }\n\n protected willUpdate(changedProperties: PropertyValues): void {\n // Set up TargetController if target changes\n if (changedProperties.has(\"target\") && !this.targetController) {\n this.targetController = new TargetController(this as any);\n }\n\n // Retry setting up selection listener if not yet connected\n this.setupSelectionListener();\n\n // Check for selection changes from canvas (via context or direct access)\n const selectionCtx = this.getCanvasSelectionContext();\n if (selectionCtx) {\n const selectedIds = Array.from(selectionCtx.selectedIds);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const selectedId: string | null =\n selectedIds.length === 0 ? null : selectedIds[0]!;\n\n if (this.hierarchyState.selectedElementId !== selectedId) {\n this.hierarchyState = {\n ...this.hierarchyState,\n selectedElementId: selectedId,\n };\n }\n }\n\n // Always update provided context to ensure children have fresh getters\n this.providedContext = {\n state: this.hierarchyState,\n actions: this.hierarchyActions,\n getCanvasSelectionContext: () => this.getCanvasSelectionContext(),\n getHighlightedElement: () => this.getHighlightedElement(),\n setHighlightedElement: (el) => this.setHighlightedElement(el),\n };\n\n super.willUpdate(changedProperties);\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this.initializeExpandedState();\n this.setupSelectionListener();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeSelectionListener();\n }\n\n protected updated(changedProperties: PropertyValues): void {\n super.updated(changedProperties);\n\n // Re-initialize when target changes\n if (changedProperties.has(\"targetElement\") || changedProperties.has(\"target\")) {\n this.initializeExpandedState();\n this.removeSelectionListener();\n this.selectionChangeHandler = undefined;\n this.setupSelectionListener();\n \n // Auto-select first root timegroup if nothing is selected\n this.autoSelectFirstRootTimegroup();\n }\n }\n\n /**\n * Auto-select the first root timegroup if nothing is currently selected\n */\n private autoSelectFirstRootTimegroup(): void {\n // Only auto-select if nothing is currently selected\n const currentSelection = this.getSelectedElementId();\n if (currentSelection) return;\n\n const roots = this.getRootElements();\n for (const root of roots) {\n // Select the first root that is a timegroup (ef-timegroup)\n if (root.tagName.toLowerCase() === \"ef-timegroup\" && root.id) {\n this.hierarchyActions.select(root.id);\n return;\n }\n }\n\n // Fallback: select first root with an ID\n for (const root of roots) {\n if (root.id) {\n this.hierarchyActions.select(root.id);\n return;\n }\n }\n }\n\n private setupSelectionListener(): void {\n // Don't set up if already set up\n if (this.selectionChangeHandler) {\n return;\n }\n\n const selectionCtx = this.getCanvasSelectionContext();\n if (selectionCtx && \"addEventListener\" in selectionCtx) {\n this.selectionChangeHandler = () => {\n this.requestUpdate(); // Trigger re-render to update hierarchy items\n };\n (selectionCtx as any).addEventListener(\n \"selectionchange\",\n this.selectionChangeHandler,\n );\n }\n }\n\n private removeSelectionListener(): void {\n const selectionCtx = this.getCanvasSelectionContext();\n if (\n selectionCtx &&\n \"removeEventListener\" in selectionCtx &&\n this.selectionChangeHandler\n ) {\n (selectionCtx as any).removeEventListener(\n \"selectionchange\",\n this.selectionChangeHandler,\n );\n this.selectionChangeHandler = undefined;\n }\n }\n\n render() {\n const roots = this.getRootElements();\n\n return html`\n <div class=\"hierarchy-container\">\n ${this.showHeader ? html`<div class=\"header\">${this.header}</div>` : nothing}\n ${\n roots.length > 0\n ? renderHierarchyChildren(\n roots,\n this.hideSelectors,\n this.showSelectors,\n true,\n )\n : html`<div class=\"empty\">No elements</div>`\n }\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-hierarchy\": EFHierarchy;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EFHierarchy.js","names":["EFHierarchy","selectedId: string | null"],"sources":["../../../src/gui/hierarchy/EFHierarchy.ts"],"sourcesContent":["import { consume, provide } from \"@lit/context\";\nimport { css, html, LitElement, nothing, type PropertyValues } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\n\nimport { isEFTemporal } from \"../../elements/EFTemporal.js\";\nimport { selectionContext } from \"../../canvas/selection/selectionContext.js\";\nimport { TargetController } from \"../../elements/TargetController.js\";\nimport { TWMixin } from \"../TWMixin.js\";\nimport {\n type HierarchyActions,\n type HierarchyContext,\n type HierarchyState,\n hierarchyContext,\n} from \"./hierarchyContext.js\";\nimport { renderHierarchyChildren } from \"./EFHierarchyItem.js\";\nimport type { EFCanvas } from \"../../canvas/EFCanvas.js\";\n\n@customElement(\"ef-hierarchy\")\nexport class EFHierarchy extends TWMixin(LitElement) {\n static styles = [\n css`\n :host {\n display: block;\n overflow: auto;\n height: 100%;\n font-size: 12px;\n \n /* Component tokens (reference globals from ef-theme.css) */\n --hierarchy-bg: var(--ef-color-bg);\n --hierarchy-border: var(--ef-color-border);\n --hierarchy-text: var(--ef-color-text);\n --hierarchy-hover-bg: var(--ef-color-hover);\n --hierarchy-selected-bg: var(--ef-color-selected);\n --hierarchy-ancestor-selected-bg: var(--ef-color-selected-subtle);\n --hierarchy-focused-bg: var(--ef-color-focused);\n --hierarchy-drop-indicator: var(--ef-color-primary);\n }\n \n .hierarchy-container {\n background: var(--hierarchy-bg);\n color: var(--hierarchy-text);\n padding: 4px 0;\n }\n \n .header {\n padding: 8px 12px;\n font-weight: 600;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--ef-color-text-muted);\n border-bottom: 1px solid var(--hierarchy-border);\n margin-bottom: 4px;\n }\n \n .empty {\n padding: 16px;\n text-align: center;\n color: var(--ef-color-text-subtle);\n font-style: italic;\n }\n `,\n ];\n\n @property({ type: String })\n target = \"\";\n\n @property({ type: String })\n header = \"\";\n\n @property({ type: Boolean, attribute: \"show-header\" })\n showHeader = false;\n\n @property({ type: Array, attribute: false })\n hideSelectors?: string[];\n\n @property({ type: Array, attribute: false })\n showSelectors?: string[];\n\n @state()\n targetElement: Element | null = null;\n\n private targetController?: TargetController;\n\n @consume({ context: selectionContext, subscribe: true })\n canvasSelectionContext?: import(\"../../canvas/selection/selectionContext.js\").SelectionContext;\n\n /**\n * Get the target canvas element.\n * The canvas is the source of truth for selection and highlight state.\n */\n private getCanvas(): EFCanvas | null {\n // First try TargetController (for registered elements like EFCanvas)\n if (this.targetElement && (this.targetElement as any).selectionContext) {\n return this.targetElement as EFCanvas;\n }\n // Fall back to direct lookup for any element with matching ID\n if (this.target) {\n const target = document.getElementById(this.target);\n if (target && (target as any).selectionContext) {\n return target as EFCanvas;\n }\n }\n return null;\n }\n\n /**\n * Get canvas selection context from the target canvas element.\n * Used when hierarchy is a sibling of canvas (can't access via Lit context).\n */\n private getCanvasSelectionContext():\n | import(\"../../canvas/selection/selectionContext.js\").SelectionContext\n | undefined {\n // First try Lit context (works when hierarchy is inside canvas)\n if (this.canvasSelectionContext) {\n return this.canvasSelectionContext;\n }\n // Use target canvas\n const canvas = this.getCanvas();\n return canvas?.selectionContext;\n }\n\n /**\n * Get the currently highlighted element from the canvas.\n */\n getHighlightedElement(): HTMLElement | null {\n const canvas = this.getCanvas();\n return canvas?.highlightedElement ?? null;\n }\n\n /**\n * Set the highlighted element on the canvas.\n * Called when user hovers an item in the hierarchy.\n */\n setHighlightedElement(element: HTMLElement | null): void {\n const canvas = this.getCanvas();\n canvas?.setHighlightedElement(element);\n }\n\n @state()\n private hierarchyState: HierarchyState = {\n selectedElementId: null,\n expandedIds: new Set(),\n draggedElementId: null,\n dropTargetId: null,\n dropPosition: null,\n };\n\n private selectionChangeHandler?: (event: CustomEvent) => void;\n\n private hierarchyActions: HierarchyActions = {\n select: (elementId: string | null) => {\n const selectionCtx = this.getCanvasSelectionContext();\n if (selectionCtx) {\n if (elementId) {\n // Ensure element is registered with canvas before selecting\n const element = document.getElementById(elementId);\n if (element) {\n // Find the canvas element\n const canvas = element.closest(\"ef-canvas\") as any;\n if (canvas && canvas.tryRegisterElement) {\n // Try to register if not already registered\n canvas.tryRegisterElement(element);\n }\n }\n\n // Select the element directly by its ID\n selectionCtx.select(elementId);\n } else {\n selectionCtx.clear();\n }\n } else {\n this.hierarchyState = {\n ...this.hierarchyState,\n selectedElementId: elementId,\n };\n }\n this.dispatchEvent(\n new CustomEvent(\"hierarchy-select\", {\n detail: { elementId },\n bubbles: true,\n composed: true,\n }),\n );\n },\n\n toggleExpanded: (elementId: string) => {\n const newExpanded = new Set(this.hierarchyState.expandedIds);\n if (newExpanded.has(elementId)) {\n newExpanded.delete(elementId);\n } else {\n newExpanded.add(elementId);\n }\n this.hierarchyState = {\n ...this.hierarchyState,\n expandedIds: newExpanded,\n };\n },\n\n setExpanded: (elementId: string, expanded: boolean) => {\n const newExpanded = new Set(this.hierarchyState.expandedIds);\n if (expanded) {\n newExpanded.add(elementId);\n } else {\n newExpanded.delete(elementId);\n }\n this.hierarchyState = {\n ...this.hierarchyState,\n expandedIds: newExpanded,\n };\n },\n\n startDrag: (elementId: string) => {\n this.hierarchyState = {\n ...this.hierarchyState,\n draggedElementId: elementId,\n };\n },\n\n updateDropTarget: (\n targetId: string | null,\n position: \"before\" | \"after\" | \"inside\" | null,\n ) => {\n if (targetId === this.hierarchyState.draggedElementId) {\n return;\n }\n this.hierarchyState = {\n ...this.hierarchyState,\n dropTargetId: targetId,\n dropPosition: position,\n };\n },\n\n endDrag: () => {\n this.hierarchyState = {\n ...this.hierarchyState,\n draggedElementId: null,\n dropTargetId: null,\n dropPosition: null,\n };\n },\n\n reorder: (\n sourceId: string,\n targetId: string,\n position: \"before\" | \"after\" | \"inside\",\n ) => {\n this.dispatchEvent(\n new CustomEvent(\"hierarchy-reorder\", {\n detail: { sourceId, targetId, position },\n bubbles: true,\n composed: true,\n }),\n );\n },\n };\n\n @provide({ context: hierarchyContext })\n @state()\n // @ts-ignore\n private providedContext: HierarchyContext = {\n state: this.hierarchyState,\n actions: this.hierarchyActions,\n getCanvasSelectionContext: () => this.getCanvasSelectionContext(),\n getHighlightedElement: () => this.getHighlightedElement(),\n setHighlightedElement: (el) => this.setHighlightedElement(el),\n };\n\n private getTargetElement(): Element | null {\n // First try TargetController (for registered elements like EFCanvas)\n if (this.targetElement) {\n return this.targetElement;\n }\n // Fall back to direct lookup for any element with matching ID\n if (this.target) {\n return document.getElementById(this.target);\n }\n return null;\n }\n\n private getRootElements(): Element[] {\n const target = this.getTargetElement();\n if (!target) {\n return [];\n }\n\n if (isEFTemporal(target)) {\n return [target];\n }\n\n return Array.from(target.children);\n }\n\n private initializeExpandedState(): void {\n const roots = this.getRootElements();\n const newExpanded = new Set<string>();\n\n const addExpandedIds = (element: Element) => {\n if (element.id) {\n newExpanded.add(element.id);\n }\n for (const child of Array.from(element.children)) {\n if (child.children.length > 0) {\n addExpandedIds(child);\n }\n }\n };\n\n for (const root of roots) {\n addExpandedIds(root);\n }\n\n this.hierarchyState = {\n ...this.hierarchyState,\n expandedIds: newExpanded,\n };\n }\n\n select(elementId: string | null): void {\n this.hierarchyActions.select(elementId);\n }\n\n getSelectedElementId(): string | null {\n const selectionCtx = this.getCanvasSelectionContext();\n if (selectionCtx) {\n const selectedIds = Array.from(selectionCtx.selectedIds);\n if (selectedIds.length === 0) {\n return null;\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return selectedIds[0]!;\n }\n return this.hierarchyState.selectedElementId;\n }\n\n protected willUpdate(changedProperties: PropertyValues): void {\n // Set up TargetController if target changes\n if (changedProperties.has(\"target\") && !this.targetController) {\n this.targetController = new TargetController(this as any);\n }\n\n // Retry setting up selection listener if not yet connected\n this.setupSelectionListener();\n\n // Check for selection changes from canvas (via context or direct access)\n const selectionCtx = this.getCanvasSelectionContext();\n if (selectionCtx) {\n const selectedIds = Array.from(selectionCtx.selectedIds);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const selectedId: string | null =\n selectedIds.length === 0 ? null : selectedIds[0]!;\n\n if (this.hierarchyState.selectedElementId !== selectedId) {\n this.hierarchyState = {\n ...this.hierarchyState,\n selectedElementId: selectedId,\n };\n }\n }\n\n // Always update provided context to ensure children have fresh getters\n this.providedContext = {\n state: this.hierarchyState,\n actions: this.hierarchyActions,\n getCanvasSelectionContext: () => this.getCanvasSelectionContext(),\n getHighlightedElement: () => this.getHighlightedElement(),\n setHighlightedElement: (el) => this.setHighlightedElement(el),\n };\n\n super.willUpdate(changedProperties);\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this.initializeExpandedState();\n this.setupSelectionListener();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeSelectionListener();\n }\n\n protected updated(changedProperties: PropertyValues): void {\n super.updated(changedProperties);\n\n // Re-initialize when target changes\n if (\n changedProperties.has(\"targetElement\") ||\n changedProperties.has(\"target\")\n ) {\n this.initializeExpandedState();\n this.removeSelectionListener();\n this.selectionChangeHandler = undefined;\n this.setupSelectionListener();\n\n // Auto-select first root timegroup if nothing is selected\n this.autoSelectFirstRootTimegroup();\n }\n }\n\n /**\n * Auto-select the first root timegroup if nothing is currently selected\n */\n private autoSelectFirstRootTimegroup(): void {\n // Only auto-select if nothing is currently selected\n const currentSelection = this.getSelectedElementId();\n if (currentSelection) return;\n\n const roots = this.getRootElements();\n for (const root of roots) {\n // Select the first root that is a timegroup (ef-timegroup)\n if (root.tagName.toLowerCase() === \"ef-timegroup\" && root.id) {\n this.hierarchyActions.select(root.id);\n return;\n }\n }\n\n // Fallback: select first root with an ID\n for (const root of roots) {\n if (root.id) {\n this.hierarchyActions.select(root.id);\n return;\n }\n }\n }\n\n private setupSelectionListener(): void {\n // Don't set up if already set up\n if (this.selectionChangeHandler) {\n return;\n }\n\n const selectionCtx = this.getCanvasSelectionContext();\n if (selectionCtx && \"addEventListener\" in selectionCtx) {\n this.selectionChangeHandler = () => {\n this.requestUpdate(); // Trigger re-render to update hierarchy items\n };\n (selectionCtx as any).addEventListener(\n \"selectionchange\",\n this.selectionChangeHandler,\n );\n }\n }\n\n private removeSelectionListener(): void {\n const selectionCtx = this.getCanvasSelectionContext();\n if (\n selectionCtx &&\n \"removeEventListener\" in selectionCtx &&\n this.selectionChangeHandler\n ) {\n (selectionCtx as any).removeEventListener(\n \"selectionchange\",\n this.selectionChangeHandler,\n );\n this.selectionChangeHandler = undefined;\n }\n }\n\n render() {\n const roots = this.getRootElements();\n\n return html`\n <div class=\"hierarchy-container\" part=\"list\">\n ${this.showHeader ? html`<div class=\"header\" part=\"header\">${this.header}</div>` : nothing}\n ${\n roots.length > 0\n ? renderHierarchyChildren(\n roots,\n this.hideSelectors,\n this.showSelectors,\n true,\n )\n : html`<div class=\"empty\">No elements</div>`\n }\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-hierarchy\": EFHierarchy;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { EFVideo } from "../../elements/EFVideo.js";
|
|
2
1
|
import { SelectionContext } from "../../canvas/selection/selectionContext.js";
|
|
3
2
|
import { EFAudio } from "../../elements/EFAudio.js";
|
|
3
|
+
import { EFVideo } from "../../elements/EFVideo.js";
|
|
4
4
|
import { EFTimegroup } from "../../elements/EFTimegroup.js";
|
|
5
5
|
import { EFImage } from "../../elements/EFImage.js";
|
|
6
6
|
import { HierarchyContext } from "./hierarchyContext.js";
|
|
7
|
-
import * as
|
|
7
|
+
import * as lit12 from "lit";
|
|
8
8
|
import { LitElement, PropertyValues, TemplateResult, nothing } from "lit";
|
|
9
9
|
|
|
10
10
|
//#region src/gui/hierarchy/EFHierarchyItem.d.ts
|
|
11
11
|
declare const EFHierarchyItem_base: typeof LitElement;
|
|
12
12
|
declare class EFHierarchyItem<ElementType extends HTMLElement = HTMLElement> extends EFHierarchyItem_base {
|
|
13
|
-
static styles:
|
|
13
|
+
static styles: lit12.CSSResult[];
|
|
14
14
|
hierarchyContext?: HierarchyContext;
|
|
15
15
|
canvasSelectionContext?: SelectionContext;
|
|
16
16
|
element: ElementType;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
|
|
2
1
|
import { TWMixin } from "../TWMixin2.js";
|
|
2
|
+
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
|
|
3
3
|
import { selectionContext } from "../../canvas/selection/selectionContext.js";
|
|
4
4
|
import { hierarchyContext } from "./hierarchyContext.js";
|
|
5
5
|
import { EFAudio } from "../../elements/EFAudio.js";
|
|
@@ -10,6 +10,7 @@ import { EFText } from "../../elements/EFText.js";
|
|
|
10
10
|
import { EFTextSegment } from "../../elements/EFTextSegment.js";
|
|
11
11
|
import { EFWaveform } from "../../elements/EFWaveform.js";
|
|
12
12
|
import { ICONS, phosphorIcon } from "../icons.js";
|
|
13
|
+
import { getElementTypeColor } from "../theme.js";
|
|
13
14
|
import { EFTimegroup } from "../../elements/EFTimegroup.js";
|
|
14
15
|
import { consume } from "@lit/context";
|
|
15
16
|
import { LitElement, css, html, nothing } from "lit";
|
|
@@ -147,18 +148,21 @@ let EFHierarchyItem = class EFHierarchyItem$1 extends TWMixin(LitElement) {
|
|
|
147
148
|
cursor: pointer;
|
|
148
149
|
user-select: none;
|
|
149
150
|
border-left: 3px solid transparent;
|
|
151
|
+
transition: background-color 0.1s ease;
|
|
150
152
|
}
|
|
151
153
|
.item-row:hover {
|
|
152
|
-
background: var(--
|
|
154
|
+
background: var(--ef-color-hover);
|
|
153
155
|
}
|
|
154
156
|
.item-row[data-selected] {
|
|
155
|
-
background: var(--
|
|
157
|
+
background: var(--ef-color-selected);
|
|
158
|
+
border-left-color: var(--ef-color-primary);
|
|
156
159
|
}
|
|
157
160
|
.item-row[data-ancestor-selected] {
|
|
158
|
-
background: var(--
|
|
161
|
+
background: var(--ef-color-selected-subtle);
|
|
159
162
|
}
|
|
160
163
|
.item-row[data-focused] {
|
|
161
|
-
background: var(--
|
|
164
|
+
background: var(--ef-color-focused);
|
|
165
|
+
border-left-color: var(--ef-color-primary);
|
|
162
166
|
}
|
|
163
167
|
.item-row[data-dragging] {
|
|
164
168
|
opacity: 0.5;
|
|
@@ -214,7 +218,7 @@ let EFHierarchyItem = class EFHierarchyItem$1 extends TWMixin(LitElement) {
|
|
|
214
218
|
return phosphorIcon(ICONS.code);
|
|
215
219
|
}
|
|
216
220
|
get typeColor() {
|
|
217
|
-
return "
|
|
221
|
+
return getElementTypeColor("timegroup", this);
|
|
218
222
|
}
|
|
219
223
|
get isFocused() {
|
|
220
224
|
const highlightedElement = this.hierarchyContext?.getHighlightedElement?.();
|
|
@@ -342,6 +346,7 @@ let EFHierarchyItem = class EFHierarchyItem$1 extends TWMixin(LitElement) {
|
|
|
342
346
|
${this.dropPosition === "before" ? html`<div class="drop-indicator"></div>` : nothing}
|
|
343
347
|
<div
|
|
344
348
|
class="item-row ${this.dropPosition === "inside" ? "drop-inside" : ""}"
|
|
349
|
+
part="row"
|
|
345
350
|
style=${styleMap({ borderLeftColor: this.typeColor })}
|
|
346
351
|
?data-focused=${this.isFocused}
|
|
347
352
|
?data-selected=${this.isSelected}
|
|
@@ -368,8 +373,8 @@ let EFHierarchyItem = class EFHierarchyItem$1 extends TWMixin(LitElement) {
|
|
|
368
373
|
</svg>
|
|
369
374
|
</span>
|
|
370
375
|
` : html`<span class="expand-icon"></span>`}
|
|
371
|
-
<span class="icon">${this.icon}</span>
|
|
372
|
-
<span class="label">${this.displayLabel()}</span>
|
|
376
|
+
<span class="icon" part="icon">${this.icon}</span>
|
|
377
|
+
<span class="label" part="label">${this.displayLabel()}</span>
|
|
373
378
|
</div>
|
|
374
379
|
${this.hasChildren ? html`
|
|
375
380
|
<div class="children" ?data-collapsed=${!expanded}>
|
|
@@ -430,10 +435,17 @@ let EFTimegroupHierarchyItem = class EFTimegroupHierarchyItem$1 extends EFHierar
|
|
|
430
435
|
return phosphorIcon(ICONS.filmSlate);
|
|
431
436
|
}
|
|
432
437
|
get typeColor() {
|
|
433
|
-
return "
|
|
438
|
+
return getElementTypeColor("timegroup", this);
|
|
434
439
|
}
|
|
435
440
|
displayLabel() {
|
|
436
|
-
|
|
441
|
+
const label = getFriendlyLabel(this.element, "Composition");
|
|
442
|
+
const mode = this.element.mode || "fixed";
|
|
443
|
+
return html`${label} <span style="opacity: 0.5; font-size: 0.65rem;">${{
|
|
444
|
+
fixed: "Fixed",
|
|
445
|
+
sequence: "Sequence",
|
|
446
|
+
contain: "Container",
|
|
447
|
+
fit: "Fit"
|
|
448
|
+
}[mode] || mode}</span>`;
|
|
437
449
|
}
|
|
438
450
|
};
|
|
439
451
|
EFTimegroupHierarchyItem = __decorate([customElement("ef-timegroup-hierarchy-item")], EFTimegroupHierarchyItem);
|