@remotion/studio 4.0.512 → 4.0.514
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/Studio.js +2 -1
- package/dist/components/AskAiModal.js +1 -1
- package/dist/components/AssetSelector.js +2 -0
- package/dist/components/AssetSelectorItem.js +1 -2
- package/dist/components/AudioWaveform.d.ts +3 -0
- package/dist/components/AudioWaveform.js +55 -67
- package/dist/components/Canvas.js +40 -5
- package/dist/components/CanvasOrLoading.js +5 -0
- package/dist/components/CompositionSelector.js +2 -0
- package/dist/components/CompositionSelectorItem.js +14 -1
- package/dist/components/ConfigureDefaultEditorModal.js +17 -11
- package/dist/components/Editor.js +16 -1
- package/dist/components/ElementInstallConfirmation.d.ts +1 -0
- package/dist/components/ElementInstallConfirmation.js +4 -2
- package/dist/components/FixComputedValueModal.d.ts +9 -0
- package/dist/components/FixComputedValueModal.js +217 -0
- package/dist/components/InitialCompositionLoader.js +19 -0
- package/dist/components/InlineDropdown.js +4 -4
- package/dist/components/InspectorInfoHeader.js +3 -3
- package/dist/components/InspectorOpenInEditor.js +26 -24
- package/dist/components/InspectorPanel/AlignmentControls.js +13 -2
- package/dist/components/InspectorPanel/CompositionInspector.js +11 -1
- package/dist/components/InspectorPanel/CompositionInspectorHeader.js +12 -8
- package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +13 -2
- package/dist/components/InspectorPanel/EasingInspector.js +12 -3
- package/dist/components/InspectorPanel/KeyframeInspector.js +21 -7
- package/dist/components/InspectorPanel/SequenceInspectorHeader.js +1 -1
- package/dist/components/InspectorPanel/SequenceSelectionInspector.js +35 -6
- package/dist/components/InspectorPanel/common.d.ts +5 -5
- package/dist/components/InspectorPanel/common.js +8 -8
- package/dist/components/InspectorPanel/easing-inspector-selection.js +7 -2
- package/dist/components/InspectorPanel/inspector-section-collapse.d.ts +1 -0
- package/dist/components/InspectorPanel/styles.d.ts +1 -1
- package/dist/components/InspectorPanel/styles.js +4 -2
- package/dist/components/InspectorSourceLocation.d.ts +1 -1
- package/dist/components/InspectorSourceLocation.js +2 -2
- package/dist/components/LicenseKeyValidation.js +2 -2
- package/dist/components/Modals.js +2 -1
- package/dist/components/NewComposition/CodemodFooter.d.ts +1 -0
- package/dist/components/NewComposition/CodemodFooter.js +10 -8
- package/dist/components/NewComposition/DeleteComposition.js +1 -1
- package/dist/components/NewComposition/DeleteFolder.js +1 -1
- package/dist/components/NewComposition/DuplicateComposition.js +7 -2
- package/dist/components/NewComposition/NewComposition.js +1 -1
- package/dist/components/NewComposition/NewFolder.js +1 -1
- package/dist/components/NewComposition/RenameComposition.js +1 -1
- package/dist/components/NewComposition/RenameFolder.js +1 -1
- package/dist/components/NewComposition/duplicate-composition-api.d.ts +16 -0
- package/dist/components/NewComposition/duplicate-composition-api.js +16 -0
- package/dist/components/NoRegisterRoot.js +1 -1
- package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.js +4 -3
- package/dist/components/QuickSwitcher/QuickSwitcherContent.js +1 -0
- package/dist/components/QuickSwitcher/fuzzy-search.js +1 -1
- package/dist/components/RefreshCompositionOverlay.js +1 -1
- package/dist/components/RenderButton.js +6 -3
- package/dist/components/RenderModal/WebRenderModal.js +6 -2
- package/dist/components/RenderModal/WebRenderModalAdvanced.d.ts +2 -0
- package/dist/components/RenderModal/WebRenderModalAdvanced.js +9 -2
- package/dist/components/RenderModal/render-modals.js +5 -1
- package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +5 -1
- package/dist/components/RenderQueue/actions.js +12 -2
- package/dist/components/RenderQueue/client-side-render-types.d.ts +1 -0
- package/dist/components/RenderingSettings.d.ts +2 -0
- package/dist/components/RenderingSettings.js +355 -0
- package/dist/components/SelectedOutlineElement.js +15 -13
- package/dist/components/SelectedOutlineOverlay.js +30 -8
- package/dist/components/SelectedOutlinePolygon.d.ts +1 -0
- package/dist/components/SelectedOutlinePolygon.js +53 -9
- package/dist/components/SettingsContext.d.ts +4 -1
- package/dist/components/SettingsContext.js +9 -2
- package/dist/components/SettingsModal.d.ts +1 -1
- package/dist/components/SettingsModal.js +10 -1
- package/dist/components/SettingsModalFooter.js +1 -1
- package/dist/components/StudioSettings.d.ts +2 -0
- package/dist/components/StudioSettings.js +185 -0
- package/dist/components/Timeline/LoopedIndicator.js +1 -1
- package/dist/components/Timeline/LoopedTimelineIndicators.d.ts +3 -0
- package/dist/components/Timeline/LoopedTimelineIndicators.js +22 -14
- package/dist/components/Timeline/Timeline.js +11 -9
- package/dist/components/Timeline/TimelineArrayField.js +1 -0
- package/dist/components/Timeline/TimelineAssetField.d.ts +2 -2
- package/dist/components/Timeline/TimelineAssetField.js +1 -1
- package/dist/components/Timeline/TimelineDragHandler.js +62 -76
- package/dist/components/Timeline/TimelineEffectItem.js +1 -1
- package/dist/components/Timeline/TimelineEffectPropItem.d.ts +4 -2
- package/dist/components/Timeline/TimelineEffectPropItem.js +25 -14
- package/dist/components/Timeline/TimelineExpandedRow.d.ts +1 -1
- package/dist/components/Timeline/TimelineExpandedRow.js +4 -4
- package/dist/components/Timeline/TimelineExpandedSection.js +1 -1
- package/dist/components/Timeline/TimelineHeightContainer.d.ts +0 -4
- package/dist/components/Timeline/TimelineHeightContainer.js +4 -4
- package/dist/components/Timeline/TimelineImageInfo.d.ts +1 -0
- package/dist/components/Timeline/TimelineImageInfo.js +3 -2
- package/dist/components/Timeline/TimelineKeyframeControls.js +31 -8
- package/dist/components/Timeline/TimelineKeyframedValue.js +1 -0
- package/dist/components/Timeline/TimelineList.d.ts +1 -5
- package/dist/components/Timeline/TimelineList.js +14 -9
- package/dist/components/Timeline/TimelinePinchZoom.js +5 -5
- package/dist/components/Timeline/TimelineRowChrome.d.ts +0 -2
- package/dist/components/Timeline/TimelineRowChrome.js +12 -5
- package/dist/components/Timeline/TimelineSchemaField.d.ts +7 -3
- package/dist/components/Timeline/TimelineSchemaField.js +71 -13
- package/dist/components/Timeline/TimelineScrollable.js +3 -1
- package/dist/components/Timeline/TimelineSelection.d.ts +5 -2
- package/dist/components/Timeline/TimelineSelection.js +90 -103
- package/dist/components/Timeline/TimelineSequence.js +59 -25
- package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -1
- package/dist/components/Timeline/TimelineSequenceItem.js +15 -9
- package/dist/components/Timeline/TimelineSequencePropItem.d.ts +2 -1
- package/dist/components/Timeline/TimelineSequencePropItem.js +14 -7
- package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +3 -0
- package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +128 -27
- package/dist/components/Timeline/TimelineSlider.js +42 -33
- package/dist/components/Timeline/TimelineTimeIndicators.js +90 -98
- package/dist/components/Timeline/TimelineTracks.d.ts +0 -2
- package/dist/components/Timeline/TimelineTracks.js +11 -4
- package/dist/components/Timeline/TimelineTransformOriginField.js +1 -1
- package/dist/components/Timeline/TimelineVideoInfo.d.ts +4 -4
- package/dist/components/Timeline/TimelineVideoInfo.js +151 -61
- package/dist/components/Timeline/TimelineViewport.d.ts +12 -0
- package/dist/components/Timeline/TimelineViewport.js +62 -0
- package/dist/components/Timeline/TimelineVirtualization.d.ts +22 -0
- package/dist/components/Timeline/TimelineVirtualization.js +144 -0
- package/dist/components/Timeline/TimelineZoomControls.js +16 -8
- package/dist/components/Timeline/call-add-keyframe.js +31 -3
- package/dist/components/Timeline/call-delete-keyframe.js +13 -3
- package/dist/components/Timeline/call-move-keyframe.d.ts +2 -1
- package/dist/components/Timeline/call-move-keyframe.js +81 -18
- package/dist/components/Timeline/call-update-keyframe-settings.js +31 -3
- package/dist/components/Timeline/delete-selected-keyframe.d.ts +0 -8
- package/dist/components/Timeline/delete-selected-keyframe.js +23 -44
- package/dist/components/Timeline/delete-selected-timeline-item.d.ts +0 -8
- package/dist/components/Timeline/delete-selected-timeline-item.js +18 -44
- package/dist/components/Timeline/get-easing-selection-after-keyframe-delete.js +8 -3
- package/dist/components/Timeline/get-sequence-context-menu-items.js +10 -8
- package/dist/components/Timeline/get-timeline-keyframes.d.ts +5 -2
- package/dist/components/Timeline/get-timeline-keyframes.js +16 -10
- package/dist/components/Timeline/get-timeline-sequence-visible-layout.d.ts +30 -0
- package/dist/components/Timeline/get-timeline-sequence-visible-layout.js +61 -0
- package/dist/components/Timeline/keyframe-clipboard.js +9 -2
- package/dist/components/Timeline/split-selected-timeline-item.js +2 -2
- package/dist/components/Timeline/timeline-scroll-logic.d.ts +24 -0
- package/dist/components/Timeline/timeline-scroll-logic.js +127 -4
- package/dist/components/Timeline/use-open-sequence-in-apps.js +8 -8
- package/dist/components/Timeline/use-timeline-height.d.ts +3 -5
- package/dist/components/Timeline/use-timeline-height.js +16 -18
- package/dist/components/Timeline/use-timeline-keyframe-drag.js +14 -4
- package/dist/components/UpdateCheck.d.ts +2 -10
- package/dist/components/UpdateCheck.js +8 -2
- package/dist/components/VisualControls/ClickableFileName.js +13 -6
- package/dist/components/VisualControls/VisualControlHandle.js +8 -0
- package/dist/components/composition-menu-items.d.ts +6 -1
- package/dist/components/composition-menu-items.js +9 -6
- package/dist/components/delete-jsx-node-api.d.ts +2 -0
- package/dist/components/delete-jsx-node-api.js +12 -0
- package/dist/components/element-install-api.d.ts +3 -0
- package/dist/components/element-install-api.js +19 -0
- package/dist/components/folder-menu-items.d.ts +4 -1
- package/dist/components/folder-menu-items.js +4 -5
- package/dist/components/get-open-in-menu-items.d.ts +1 -1
- package/dist/components/get-open-in-menu-items.js +15 -13
- package/dist/components/import-assets.js +20 -9
- package/dist/components/reorder-sequence-api.d.ts +2 -0
- package/dist/components/reorder-sequence-api.js +12 -0
- package/dist/components/sequence-props-api.js +44 -3
- package/dist/components/split-jsx-sequence-api.d.ts +2 -0
- package/dist/components/split-jsx-sequence-api.js +12 -0
- package/dist/components/split-video-from-audio-api.d.ts +2 -0
- package/dist/components/split-video-from-audio-api.js +12 -0
- package/dist/components/use-default-editor-info.d.ts +8 -0
- package/dist/components/use-default-editor-info.js +25 -9
- package/dist/error-overlay/remotion-overlay/ErrorDisplay.js +10 -3
- package/dist/error-overlay/remotion-overlay/OpenInEditor.d.ts +3 -1
- package/dist/error-overlay/remotion-overlay/OpenInEditor.js +6 -6
- package/dist/error-overlay/remotion-overlay/Overlay.js +14 -12
- package/dist/error-overlay/remotion-overlay/StackFrame.d.ts +2 -1
- package/dist/error-overlay/remotion-overlay/StackFrame.js +7 -4
- package/dist/esm/{chunk-s8gwjng0.js → chunk-xn2q7eem.js} +11983 -8035
- package/dist/esm/index.mjs +7 -5
- package/dist/esm/internals.mjs +11983 -8035
- package/dist/esm/previewEntry.mjs +13059 -9107
- package/dist/esm/renderEntry.mjs +2 -3
- package/dist/helpers/browser-studio-operations.d.ts +2 -0
- package/dist/helpers/browser-studio-operations.js +10 -1
- package/dist/helpers/get-timeline-max-zoom.d.ts +26 -0
- package/dist/helpers/get-timeline-max-zoom.js +45 -0
- package/dist/helpers/inject-css.js +2 -2
- package/dist/helpers/open-in-editor.d.ts +6 -4
- package/dist/helpers/open-in-editor.js +4 -4
- package/dist/helpers/render-codec-label.d.ts +1 -1
- package/dist/helpers/retry-payload.js +1 -0
- package/dist/helpers/studio-runtime-config.d.ts +1 -1
- package/dist/helpers/studio-runtime-config.js +2 -3
- package/dist/helpers/timeline-layout.d.ts +3 -1
- package/dist/helpers/timeline-layout.js +6 -1
- package/dist/helpers/url-state.js +3 -2
- package/dist/helpers/use-menu-structure.js +12 -11
- package/dist/helpers/use-runtime-values.d.ts +2 -1
- package/dist/helpers/use-runtime-values.js +7 -3
- package/dist/icons/remotion-triangle.d.ts +2 -0
- package/dist/icons/remotion-triangle.js +7 -0
- package/dist/renderEntry.js +1 -1
- package/dist/state/composition-list.d.ts +13 -0
- package/dist/state/composition-list.js +21 -0
- package/dist/state/modals.d.ts +7 -1
- package/dist/state/timeline-zoom.d.ts +1 -2
- package/dist/state/timeline-zoom.js +9 -5
- package/package.json +14 -13
|
@@ -3,16 +3,16 @@ import type { LoopDisplay } from 'remotion';
|
|
|
3
3
|
export declare const TimelineVideoInfo: React.NamedExoticComponent<{
|
|
4
4
|
readonly src: string;
|
|
5
5
|
readonly visualizationWidth: number;
|
|
6
|
-
readonly
|
|
6
|
+
readonly displayOffsetInFrames: number;
|
|
7
|
+
readonly displayDurationInFrames: number;
|
|
7
8
|
readonly startMediaFrom: number;
|
|
8
9
|
readonly mediaFrameAtSequenceZero: number | null;
|
|
9
10
|
readonly sequenceFrameOffset: number;
|
|
10
|
-
readonly durationInFrames: number;
|
|
11
11
|
readonly playbackRate: number;
|
|
12
12
|
readonly volume: string | number;
|
|
13
13
|
readonly doesVolumeChange: boolean;
|
|
14
|
-
readonly
|
|
15
|
-
readonly
|
|
14
|
+
readonly muted: boolean;
|
|
15
|
+
readonly marginLeft: number;
|
|
16
16
|
readonly loopDisplay: LoopDisplay | undefined;
|
|
17
17
|
readonly frozenMediaFrame: number | null;
|
|
18
18
|
readonly extendLastFrame: boolean;
|
|
@@ -42,7 +42,6 @@ const colors_1 = require("../../helpers/colors");
|
|
|
42
42
|
const timeline_layout_1 = require("../../helpers/timeline-layout");
|
|
43
43
|
const AudioWaveform_1 = require("../AudioWaveform");
|
|
44
44
|
const get_timeline_media_start_frame_1 = require("./get-timeline-media-start-frame");
|
|
45
|
-
const get_timeline_video_info_widths_1 = require("./get-timeline-video-info-widths");
|
|
46
45
|
const timeline_video_filmstrip_times_1 = require("./timeline-video-filmstrip-times");
|
|
47
46
|
const outerStyle = {
|
|
48
47
|
width: '100%',
|
|
@@ -59,7 +58,8 @@ const filmstripContainerStyle = {
|
|
|
59
58
|
fontFamily: 'Arial, Helvetica',
|
|
60
59
|
};
|
|
61
60
|
const MAX_FROZEN_FRAME_CACHE_DEVIATION = timeline_utils_1.WEBCODECS_TIMESCALE * 0.05;
|
|
62
|
-
const
|
|
61
|
+
const TimelineVideoInfoSegment = ({ src, visualizationWidth, startMediaFrom, mediaFrameAtSequenceZero, sequenceFrameOffset, durationInFrames, sourceOffsetInFrames, tiledLoop, playbackRate, volume, doesVolumeChange, muted, frozenMediaFrame, extendLastFrame, }) => {
|
|
62
|
+
var _a, _b;
|
|
63
63
|
const { fps } = (0, remotion_1.useVideoConfig)();
|
|
64
64
|
const ref = (0, react_1.useRef)(null);
|
|
65
65
|
const [error, setError] = (0, react_1.useState)(null);
|
|
@@ -69,15 +69,8 @@ const TimelineVideoInfoInner = ({ src, visualizationWidth, naturalWidth, startMe
|
|
|
69
69
|
mediaFrameAtSequenceZero,
|
|
70
70
|
sequenceFrameOffset,
|
|
71
71
|
playbackRate,
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
return (0, get_timeline_video_info_widths_1.getTimelineVideoInfoWidths)({
|
|
75
|
-
visualizationWidth,
|
|
76
|
-
naturalWidth,
|
|
77
|
-
premountWidth,
|
|
78
|
-
postmountWidth,
|
|
79
|
-
});
|
|
80
|
-
}, [naturalWidth, postmountWidth, premountWidth, visualizationWidth]);
|
|
72
|
+
}) +
|
|
73
|
+
sourceOffsetInFrames * playbackRate;
|
|
81
74
|
// for rendering frames
|
|
82
75
|
(0, react_1.useEffect)(() => {
|
|
83
76
|
if (error) {
|
|
@@ -88,19 +81,22 @@ const TimelineVideoInfoInner = ({ src, visualizationWidth, naturalWidth, startMe
|
|
|
88
81
|
return;
|
|
89
82
|
}
|
|
90
83
|
const controller = new AbortController();
|
|
84
|
+
const pixelRatio = window.devicePixelRatio;
|
|
91
85
|
const canvas = document.createElement('canvas');
|
|
92
|
-
canvas.width =
|
|
93
|
-
canvas.height = timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT;
|
|
86
|
+
canvas.width = Math.ceil(visualizationWidth * pixelRatio);
|
|
87
|
+
canvas.height = Math.ceil(timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT * pixelRatio);
|
|
88
|
+
canvas.style.width = visualizationWidth + 'px';
|
|
89
|
+
canvas.style.height = timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT + 'px';
|
|
94
90
|
const ctx = canvas.getContext('2d');
|
|
95
91
|
if (!ctx) {
|
|
96
92
|
return;
|
|
97
93
|
}
|
|
98
94
|
current.appendChild(canvas);
|
|
99
95
|
const drawRepeatedFrame = (frame) => {
|
|
100
|
-
const thumbnailWidth = Math.max(1, frame.displayWidth
|
|
96
|
+
const thumbnailWidth = Math.max(1, frame.displayWidth);
|
|
101
97
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
102
98
|
for (let x = 0; x < canvas.width; x += thumbnailWidth) {
|
|
103
|
-
ctx.drawImage(frame, x, 0, thumbnailWidth,
|
|
99
|
+
ctx.drawImage(frame, x, 0, thumbnailWidth, canvas.height);
|
|
104
100
|
}
|
|
105
101
|
};
|
|
106
102
|
const getCachedFrozenFrame = (timestamp) => {
|
|
@@ -128,7 +124,7 @@ const TimelineVideoInfoInner = ({ src, visualizationWidth, naturalWidth, startMe
|
|
|
128
124
|
durationInFrames,
|
|
129
125
|
playbackRate,
|
|
130
126
|
fps,
|
|
131
|
-
loopDisplay,
|
|
127
|
+
loopDisplay: undefined,
|
|
132
128
|
frozenMediaFrame,
|
|
133
129
|
});
|
|
134
130
|
if (times.type === 'frozen') {
|
|
@@ -152,8 +148,7 @@ const TimelineVideoInfoInner = ({ src, visualizationWidth, naturalWidth, startMe
|
|
|
152
148
|
let frame;
|
|
153
149
|
try {
|
|
154
150
|
frame = sample.toVideoFrame();
|
|
155
|
-
const scale =
|
|
156
|
-
window.devicePixelRatio;
|
|
151
|
+
const scale = canvas.height / frame.displayHeight;
|
|
157
152
|
const transformed = (0, timeline_utils_1.resizeVideoFrame)({
|
|
158
153
|
frame,
|
|
159
154
|
scale,
|
|
@@ -185,42 +180,44 @@ const TimelineVideoInfoInner = ({ src, visualizationWidth, naturalWidth, startMe
|
|
|
185
180
|
current.removeChild(canvas);
|
|
186
181
|
};
|
|
187
182
|
}
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
});
|
|
192
|
-
const shouldRepeatVideo = (0, timeline_utils_1.shouldTileLoopDisplay)(loopDisplay);
|
|
193
|
-
const targetCanvas = shouldRepeatVideo
|
|
194
|
-
? document.createElement('canvas')
|
|
195
|
-
: canvas;
|
|
196
|
-
targetCanvas.width = shouldRepeatVideo
|
|
197
|
-
? Math.max(1, Math.ceil(loopWidth))
|
|
183
|
+
const targetCanvas = tiledLoop ? document.createElement('canvas') : canvas;
|
|
184
|
+
targetCanvas.width = tiledLoop
|
|
185
|
+
? Math.max(1, Math.ceil(tiledLoop.loopWidth * pixelRatio))
|
|
198
186
|
: canvas.width;
|
|
199
187
|
targetCanvas.height = canvas.height;
|
|
200
|
-
const targetCtx =
|
|
188
|
+
const targetCtx = tiledLoop ? targetCanvas.getContext('2d') : ctx;
|
|
201
189
|
if (!targetCtx) {
|
|
202
190
|
current.removeChild(canvas);
|
|
203
191
|
return;
|
|
204
192
|
}
|
|
193
|
+
// desired-timestamp -> filled-timestamp
|
|
194
|
+
const filledSlots = new Map();
|
|
195
|
+
const { fromSeconds, toSeconds } = times;
|
|
196
|
+
const targetWidth = targetCanvas.width;
|
|
205
197
|
const repeatTarget = () => {
|
|
206
|
-
if (!
|
|
198
|
+
if (!tiledLoop) {
|
|
207
199
|
return;
|
|
208
200
|
}
|
|
209
201
|
const pattern = ctx.createPattern(targetCanvas, 'repeat-x');
|
|
210
202
|
if (!pattern) {
|
|
211
203
|
return;
|
|
212
204
|
}
|
|
213
|
-
|
|
205
|
+
const phase = (tiledLoop.displayOffsetInFrames %
|
|
206
|
+
tiledLoop.loopDisplay.durationInFrames) *
|
|
207
|
+
((tiledLoop.loopWidth * pixelRatio) /
|
|
208
|
+
tiledLoop.loopDisplay.durationInFrames);
|
|
209
|
+
pattern.setTransform(new DOMMatrix([
|
|
210
|
+
(tiledLoop.loopWidth * pixelRatio) / targetCanvas.width,
|
|
211
|
+
0,
|
|
212
|
+
0,
|
|
213
|
+
1,
|
|
214
|
+
-phase,
|
|
215
|
+
0,
|
|
216
|
+
]));
|
|
214
217
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
215
218
|
ctx.fillStyle = pattern;
|
|
216
219
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
217
220
|
};
|
|
218
|
-
// desired-timestamp -> filled-timestamp
|
|
219
|
-
const filledSlots = new Map();
|
|
220
|
-
const { fromSeconds, toSeconds } = times;
|
|
221
|
-
const targetWidth = shouldRepeatVideo
|
|
222
|
-
? targetCanvas.width
|
|
223
|
-
: mediaNaturalWidth;
|
|
224
221
|
if (aspectRatio.current !== null) {
|
|
225
222
|
(0, timeline_utils_1.ensureSlots)({
|
|
226
223
|
filledSlots,
|
|
@@ -228,7 +225,7 @@ const TimelineVideoInfoInner = ({ src, visualizationWidth, naturalWidth, startMe
|
|
|
228
225
|
fromSeconds,
|
|
229
226
|
toSeconds,
|
|
230
227
|
aspectRatio: aspectRatio.current,
|
|
231
|
-
frameHeight:
|
|
228
|
+
frameHeight: canvas.height,
|
|
232
229
|
});
|
|
233
230
|
(0, timeline_utils_1.fillWithCachedFrames)({
|
|
234
231
|
ctx: targetCtx,
|
|
@@ -237,11 +234,11 @@ const TimelineVideoInfoInner = ({ src, visualizationWidth, naturalWidth, startMe
|
|
|
237
234
|
src,
|
|
238
235
|
segmentDuration: toSeconds - fromSeconds,
|
|
239
236
|
fromSeconds,
|
|
240
|
-
devicePixelRatio:
|
|
241
|
-
frameHeight:
|
|
237
|
+
devicePixelRatio: 1,
|
|
238
|
+
frameHeight: canvas.height,
|
|
242
239
|
});
|
|
243
240
|
repeatTarget();
|
|
244
|
-
const unfilled = Array.from(filledSlots.keys()).filter((timestamp) =>
|
|
241
|
+
const unfilled = Array.from(filledSlots.keys()).filter((timestamp) => filledSlots.get(timestamp) === undefined);
|
|
245
242
|
// Don't extract frames if all slots are filled
|
|
246
243
|
if (unfilled.length === 0) {
|
|
247
244
|
return () => {
|
|
@@ -260,17 +257,29 @@ const TimelineVideoInfoInner = ({ src, visualizationWidth, naturalWidth, startMe
|
|
|
260
257
|
toSeconds,
|
|
261
258
|
naturalWidth: targetWidth,
|
|
262
259
|
aspectRatio: aspectRatio.current,
|
|
263
|
-
frameHeight:
|
|
260
|
+
frameHeight: canvas.height,
|
|
261
|
+
});
|
|
262
|
+
(0, timeline_utils_1.fillWithCachedFrames)({
|
|
263
|
+
ctx: targetCtx,
|
|
264
|
+
naturalWidth: targetWidth,
|
|
265
|
+
filledSlots,
|
|
266
|
+
src,
|
|
267
|
+
segmentDuration: toSeconds - fromSeconds,
|
|
268
|
+
fromSeconds,
|
|
269
|
+
devicePixelRatio: 1,
|
|
270
|
+
frameHeight: canvas.height,
|
|
264
271
|
});
|
|
265
|
-
|
|
272
|
+
repeatTarget();
|
|
273
|
+
return Array.from(filledSlots.keys())
|
|
274
|
+
.filter((timestamp) => filledSlots.get(timestamp) === undefined)
|
|
275
|
+
.map((timestamp) => timestamp / timeline_utils_1.WEBCODECS_TIMESCALE);
|
|
266
276
|
},
|
|
267
277
|
src,
|
|
268
278
|
onVideoSample: (sample) => {
|
|
269
279
|
let frame;
|
|
270
280
|
try {
|
|
271
281
|
frame = sample.toVideoFrame();
|
|
272
|
-
const scale =
|
|
273
|
-
window.devicePixelRatio;
|
|
282
|
+
const scale = canvas.height / frame.displayHeight;
|
|
274
283
|
const transformed = (0, timeline_utils_1.resizeVideoFrame)({
|
|
275
284
|
frame,
|
|
276
285
|
scale,
|
|
@@ -290,7 +299,7 @@ const TimelineVideoInfoInner = ({ src, visualizationWidth, naturalWidth, startMe
|
|
|
290
299
|
toSeconds,
|
|
291
300
|
naturalWidth: targetWidth,
|
|
292
301
|
aspectRatio: aspectRatio.current,
|
|
293
|
-
frameHeight:
|
|
302
|
+
frameHeight: canvas.height,
|
|
294
303
|
});
|
|
295
304
|
(0, timeline_utils_1.fillFrameWhereItFits)({
|
|
296
305
|
ctx: targetCtx,
|
|
@@ -299,8 +308,8 @@ const TimelineVideoInfoInner = ({ src, visualizationWidth, naturalWidth, startMe
|
|
|
299
308
|
frame: transformed,
|
|
300
309
|
segmentDuration: toSeconds - fromSeconds,
|
|
301
310
|
fromSeconds,
|
|
302
|
-
devicePixelRatio:
|
|
303
|
-
frameHeight:
|
|
311
|
+
devicePixelRatio: 1,
|
|
312
|
+
frameHeight: canvas.height,
|
|
304
313
|
});
|
|
305
314
|
repeatTarget();
|
|
306
315
|
}
|
|
@@ -327,8 +336,8 @@ const TimelineVideoInfoInner = ({ src, visualizationWidth, naturalWidth, startMe
|
|
|
327
336
|
src,
|
|
328
337
|
segmentDuration: toSeconds - fromSeconds,
|
|
329
338
|
fromSeconds,
|
|
330
|
-
devicePixelRatio:
|
|
331
|
-
frameHeight:
|
|
339
|
+
devicePixelRatio: 1,
|
|
340
|
+
frameHeight: canvas.height,
|
|
332
341
|
});
|
|
333
342
|
repeatTarget();
|
|
334
343
|
})
|
|
@@ -345,30 +354,111 @@ const TimelineVideoInfoInner = ({ src, visualizationWidth, naturalWidth, startMe
|
|
|
345
354
|
extendLastFrame,
|
|
346
355
|
fps,
|
|
347
356
|
frozenMediaFrame,
|
|
348
|
-
loopDisplay,
|
|
349
|
-
mediaNaturalWidth,
|
|
350
|
-
mediaVisualizationWidth,
|
|
351
357
|
mediaStartFrame,
|
|
352
358
|
playbackRate,
|
|
353
359
|
src,
|
|
360
|
+
tiledLoop,
|
|
361
|
+
visualizationWidth,
|
|
354
362
|
]);
|
|
355
|
-
const audioWidth =
|
|
363
|
+
const audioWidth = visualizationWidth;
|
|
356
364
|
const filmstripStyle = (0, react_1.useMemo)(() => {
|
|
357
365
|
return {
|
|
358
366
|
...filmstripContainerStyle,
|
|
359
|
-
width:
|
|
360
|
-
marginLeft: premountWidth,
|
|
367
|
+
width: visualizationWidth,
|
|
361
368
|
};
|
|
362
|
-
}, [
|
|
369
|
+
}, [visualizationWidth]);
|
|
363
370
|
const audioStyle = (0, react_1.useMemo)(() => {
|
|
364
371
|
return {
|
|
365
372
|
width: audioWidth,
|
|
366
373
|
position: 'relative',
|
|
367
|
-
marginLeft: premountWidth,
|
|
368
374
|
};
|
|
369
|
-
}, [audioWidth
|
|
370
|
-
|
|
371
|
-
|
|
375
|
+
}, [audioWidth]);
|
|
376
|
+
const segmentStyle = (0, react_1.useMemo)(() => {
|
|
377
|
+
return {
|
|
378
|
+
...outerStyle,
|
|
379
|
+
width: visualizationWidth,
|
|
380
|
+
flexShrink: 0,
|
|
381
|
+
};
|
|
382
|
+
}, [visualizationWidth]);
|
|
383
|
+
return (jsx_runtime_1.jsxs("div", { style: segmentStyle, children: [
|
|
384
|
+
jsx_runtime_1.jsx("div", { ref: ref, style: filmstripStyle }), jsx_runtime_1.jsx("div", { style: audioStyle, children: jsx_runtime_1.jsx(AudioWaveform_1.AudioWaveform, { src: src, height: timeline_layout_1.TIMELINE_VIDEO_INFO_WAVEFORM_HEIGHT, visualizationWidth: audioWidth, startFrom: mediaStartFrame, durationInFrames: durationInFrames, displayOffsetInFrames: (_a = tiledLoop === null || tiledLoop === void 0 ? void 0 : tiledLoop.displayOffsetInFrames) !== null && _a !== void 0 ? _a : 0, displayDurationInFrames: (_b = tiledLoop === null || tiledLoop === void 0 ? void 0 : tiledLoop.displayDurationInFrames) !== null && _b !== void 0 ? _b : durationInFrames, volume: volume, doesVolumeChange: doesVolumeChange, muted: muted, playbackRate: playbackRate, loopDisplay: tiledLoop === null || tiledLoop === void 0 ? void 0 : tiledLoop.loopDisplay }) })
|
|
372
385
|
] }));
|
|
373
386
|
};
|
|
387
|
+
const getVisibleSegments = ({ displayDurationInFrames, displayOffsetInFrames, loopDisplay, }) => {
|
|
388
|
+
if (!loopDisplay ||
|
|
389
|
+
loopDisplay.numberOfTimes <= 1 ||
|
|
390
|
+
loopDisplay.durationInFrames <= 0) {
|
|
391
|
+
return [
|
|
392
|
+
{
|
|
393
|
+
key: 'single',
|
|
394
|
+
displayOffsetInFrames,
|
|
395
|
+
durationInFrames: displayDurationInFrames,
|
|
396
|
+
sourceOffsetInFrames: displayOffsetInFrames,
|
|
397
|
+
},
|
|
398
|
+
];
|
|
399
|
+
}
|
|
400
|
+
return (0, timeline_utils_1.getLoopDisplaySegments)({
|
|
401
|
+
displayDurationInFrames,
|
|
402
|
+
displayOffsetInFrames,
|
|
403
|
+
loopDurationInFrames: loopDisplay.durationInFrames,
|
|
404
|
+
}).map((segment) => {
|
|
405
|
+
return {
|
|
406
|
+
key: `loop-${segment.loopIndex}`,
|
|
407
|
+
displayOffsetInFrames: segment.absoluteOffsetInFrames,
|
|
408
|
+
durationInFrames: segment.durationInFrames,
|
|
409
|
+
sourceOffsetInFrames: segment.loopOffsetInFrames,
|
|
410
|
+
};
|
|
411
|
+
});
|
|
412
|
+
};
|
|
413
|
+
const TimelineVideoInfoInner = ({ src, visualizationWidth, displayOffsetInFrames, displayDurationInFrames, startMediaFrom, mediaFrameAtSequenceZero, sequenceFrameOffset, playbackRate, volume, doesVolumeChange, muted, marginLeft, loopDisplay, frozenMediaFrame, extendLastFrame, }) => {
|
|
414
|
+
const pixelsPerFrame = visualizationWidth / displayDurationInFrames;
|
|
415
|
+
const loopWidth = loopDisplay
|
|
416
|
+
? loopDisplay.durationInFrames * pixelsPerFrame
|
|
417
|
+
: null;
|
|
418
|
+
const shouldTileLoop = loopDisplay !== undefined &&
|
|
419
|
+
loopWidth !== null &&
|
|
420
|
+
loopWidth <= visualizationWidth;
|
|
421
|
+
const tiledLoop = (0, react_1.useMemo)(() => {
|
|
422
|
+
if (!shouldTileLoop || !loopDisplay || loopWidth === null) {
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
return {
|
|
426
|
+
displayDurationInFrames,
|
|
427
|
+
displayOffsetInFrames,
|
|
428
|
+
loopDisplay,
|
|
429
|
+
loopWidth,
|
|
430
|
+
};
|
|
431
|
+
}, [
|
|
432
|
+
displayDurationInFrames,
|
|
433
|
+
displayOffsetInFrames,
|
|
434
|
+
loopDisplay,
|
|
435
|
+
loopWidth,
|
|
436
|
+
shouldTileLoop,
|
|
437
|
+
]);
|
|
438
|
+
const segments = (0, react_1.useMemo)(() => {
|
|
439
|
+
if (shouldTileLoop) {
|
|
440
|
+
return [];
|
|
441
|
+
}
|
|
442
|
+
return getVisibleSegments({
|
|
443
|
+
displayDurationInFrames,
|
|
444
|
+
displayOffsetInFrames,
|
|
445
|
+
loopDisplay,
|
|
446
|
+
});
|
|
447
|
+
}, [
|
|
448
|
+
displayDurationInFrames,
|
|
449
|
+
displayOffsetInFrames,
|
|
450
|
+
loopDisplay,
|
|
451
|
+
shouldTileLoop,
|
|
452
|
+
]);
|
|
453
|
+
const getSegmentVolume = (segmentDisplayOffsetInFrames, segmentDurationInFrames) => {
|
|
454
|
+
if (typeof volume === 'number') {
|
|
455
|
+
return volume;
|
|
456
|
+
}
|
|
457
|
+
const values = volume.split(',');
|
|
458
|
+
return values
|
|
459
|
+
.slice(Math.max(0, Math.floor(segmentDisplayOffsetInFrames)), Math.min(values.length, Math.ceil(segmentDisplayOffsetInFrames + segmentDurationInFrames)))
|
|
460
|
+
.join(',');
|
|
461
|
+
};
|
|
462
|
+
return (jsx_runtime_1.jsx("div", { style: { display: 'flex', marginLeft, height: '100%' }, children: tiledLoop ? (jsx_runtime_1.jsx(TimelineVideoInfoSegment, { src: src, visualizationWidth: visualizationWidth, startMediaFrom: startMediaFrom, mediaFrameAtSequenceZero: mediaFrameAtSequenceZero, sequenceFrameOffset: sequenceFrameOffset, durationInFrames: tiledLoop.loopDisplay.durationInFrames, sourceOffsetInFrames: 0, tiledLoop: tiledLoop, playbackRate: playbackRate, volume: volume, doesVolumeChange: doesVolumeChange, muted: muted, frozenMediaFrame: frozenMediaFrame, extendLastFrame: extendLastFrame })) : (segments.map((segment) => (jsx_runtime_1.jsx(TimelineVideoInfoSegment, { src: src, visualizationWidth: segment.durationInFrames * pixelsPerFrame, startMediaFrom: startMediaFrom, mediaFrameAtSequenceZero: mediaFrameAtSequenceZero, sequenceFrameOffset: sequenceFrameOffset, durationInFrames: segment.durationInFrames, sourceOffsetInFrames: segment.sourceOffsetInFrames, tiledLoop: null, playbackRate: playbackRate, volume: getSegmentVolume(segment.sourceOffsetInFrames, segment.durationInFrames), doesVolumeChange: doesVolumeChange, muted: muted, frozenMediaFrame: frozenMediaFrame, extendLastFrame: extendLastFrame }, segment.key)))) }));
|
|
463
|
+
};
|
|
374
464
|
exports.TimelineVideoInfo = react_1.default.memo(TimelineVideoInfoInner);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
type TimelineRenderWindow = {
|
|
3
|
+
readonly left: number;
|
|
4
|
+
readonly width: number;
|
|
5
|
+
};
|
|
6
|
+
export declare const TimelineViewportContext: React.Context<TimelineRenderWindow | null>;
|
|
7
|
+
export declare const getTimelineRenderWindow: (scrollable: HTMLDivElement) => TimelineRenderWindow;
|
|
8
|
+
export declare const TimelineViewportProvider: React.FC<{
|
|
9
|
+
readonly children: React.ReactNode;
|
|
10
|
+
readonly scrollable: React.RefObject<HTMLDivElement | null>;
|
|
11
|
+
}>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TimelineViewportProvider = exports.getTimelineRenderWindow = exports.TimelineViewportContext = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
exports.TimelineViewportContext = (0, react_1.createContext)(null);
|
|
7
|
+
const getTimelineRenderWindow = (scrollable) => {
|
|
8
|
+
const viewportWidth = scrollable.clientWidth;
|
|
9
|
+
if (viewportWidth === 0) {
|
|
10
|
+
return { left: 0, width: 0 };
|
|
11
|
+
}
|
|
12
|
+
// Move the render window half a viewport before the visible viewport reaches
|
|
13
|
+
// its right edge. This keeps at least half a viewport rendered ahead while
|
|
14
|
+
// retaining the three-viewport-wide window.
|
|
15
|
+
const currentSection = Math.floor((scrollable.scrollLeft + viewportWidth / 2) / viewportWidth);
|
|
16
|
+
const left = Math.max(0, (currentSection - 1) * viewportWidth);
|
|
17
|
+
return {
|
|
18
|
+
left,
|
|
19
|
+
width: viewportWidth * 3,
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
exports.getTimelineRenderWindow = getTimelineRenderWindow;
|
|
23
|
+
const TimelineViewportProvider = ({ children, scrollable }) => {
|
|
24
|
+
const [renderWindow, setRenderWindow] = (0, react_1.useState)({
|
|
25
|
+
left: 0,
|
|
26
|
+
width: window.innerWidth * 3,
|
|
27
|
+
});
|
|
28
|
+
const update = (0, react_1.useCallback)(() => {
|
|
29
|
+
const element = scrollable.current;
|
|
30
|
+
if (!element) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const next = (0, exports.getTimelineRenderWindow)(element);
|
|
34
|
+
setRenderWindow((previous) => {
|
|
35
|
+
if (previous.left === next.left && previous.width === next.width) {
|
|
36
|
+
return previous;
|
|
37
|
+
}
|
|
38
|
+
return next;
|
|
39
|
+
});
|
|
40
|
+
}, [scrollable]);
|
|
41
|
+
(0, react_1.useLayoutEffect)(() => {
|
|
42
|
+
let element = null;
|
|
43
|
+
let resizeObserver = null;
|
|
44
|
+
const animationFrame = requestAnimationFrame(() => {
|
|
45
|
+
element = scrollable.current;
|
|
46
|
+
if (!element) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
resizeObserver = new ResizeObserver(update);
|
|
50
|
+
resizeObserver.observe(element);
|
|
51
|
+
update();
|
|
52
|
+
element.addEventListener('scroll', update);
|
|
53
|
+
});
|
|
54
|
+
return () => {
|
|
55
|
+
cancelAnimationFrame(animationFrame);
|
|
56
|
+
resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect();
|
|
57
|
+
element === null || element === void 0 ? void 0 : element.removeEventListener('scroll', update);
|
|
58
|
+
};
|
|
59
|
+
}, [scrollable, update]);
|
|
60
|
+
return (jsx_runtime_1.jsx(exports.TimelineViewportContext.Provider, { value: renderWindow, children: children }));
|
|
61
|
+
};
|
|
62
|
+
exports.TimelineViewportProvider = TimelineViewportProvider;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type VirtualItem } from '@tanstack/react-virtual';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import type { TimelineTrackData } from '../../helpers/get-timeline-sequence-sort-key';
|
|
4
|
+
export type TimelineVirtualRow = {
|
|
5
|
+
readonly afterDropLineOffset: number;
|
|
6
|
+
readonly siblingIndex: number;
|
|
7
|
+
readonly track: TimelineTrackData;
|
|
8
|
+
};
|
|
9
|
+
type TimelineVirtualizationContextValue = {
|
|
10
|
+
readonly rows: readonly TimelineVirtualRow[];
|
|
11
|
+
readonly totalSize: number;
|
|
12
|
+
readonly tracksEnd: number;
|
|
13
|
+
readonly virtualItems: readonly VirtualItem[];
|
|
14
|
+
};
|
|
15
|
+
export declare const TimelineVirtualizationProvider: React.FC<{
|
|
16
|
+
readonly children: React.ReactNode;
|
|
17
|
+
readonly hasBeenCut: boolean;
|
|
18
|
+
readonly isStill: boolean;
|
|
19
|
+
readonly timeline: readonly TimelineTrackData[];
|
|
20
|
+
}>;
|
|
21
|
+
export declare const useTimelineVirtualization: () => TimelineVirtualizationContextValue;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useTimelineVirtualization = exports.TimelineVirtualizationProvider = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_virtual_1 = require("@tanstack/react-virtual");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const timeline_layout_1 = require("../../helpers/timeline-layout");
|
|
8
|
+
const MaxTimelineTracks_1 = require("./MaxTimelineTracks");
|
|
9
|
+
const timeline_refs_1 = require("./timeline-refs");
|
|
10
|
+
const TimelineSelection_1 = require("./TimelineSelection");
|
|
11
|
+
const TimelineTimeIndicators_1 = require("./TimelineTimeIndicators");
|
|
12
|
+
const use_timeline_height_1 = require("./use-timeline-height");
|
|
13
|
+
const TimelineVirtualizationContext = (0, react_1.createContext)(null);
|
|
14
|
+
const getSelectionTrackKey = (selection) => {
|
|
15
|
+
if (selection.type === 'guide') {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return (0, TimelineSelection_1.getTimelineSequenceSelectionKey)(selection.nodePathInfo);
|
|
19
|
+
};
|
|
20
|
+
const TimelineVirtualizationProvider = ({ children, hasBeenCut, isStill, timeline }) => {
|
|
21
|
+
const trackHeights = (0, use_timeline_height_1.useTimelineTrackHeights)({ timeline });
|
|
22
|
+
const { revealRequest, selectedItems } = (0, TimelineSelection_1.useTimelineSelection)();
|
|
23
|
+
const paddingStart = isStill ? 0 : TimelineTimeIndicators_1.TIMELINE_TIME_INDICATOR_HEIGHT;
|
|
24
|
+
const paddingEnd = timeline_layout_1.TIMELINE_ITEM_BORDER_BOTTOM +
|
|
25
|
+
(hasBeenCut ? MaxTimelineTracks_1.MAX_TIMELINE_TRACKS_NOTICE_HEIGHT : 0);
|
|
26
|
+
const layout = (0, react_1.useMemo)(() => {
|
|
27
|
+
var _a;
|
|
28
|
+
var _b, _c;
|
|
29
|
+
const siblingIndexes = new Array(timeline.length);
|
|
30
|
+
const subtreeEndIndexes = new Array(timeline.length).fill(timeline.length);
|
|
31
|
+
const openTracks = [];
|
|
32
|
+
const siblingCounts = new Map();
|
|
33
|
+
for (let index = 0; index < timeline.length; index++) {
|
|
34
|
+
const { depth } = timeline[index];
|
|
35
|
+
while (openTracks.length > 0 &&
|
|
36
|
+
openTracks[openTracks.length - 1].depth >= depth) {
|
|
37
|
+
const completed = openTracks.pop();
|
|
38
|
+
subtreeEndIndexes[completed.index] = index;
|
|
39
|
+
}
|
|
40
|
+
const parentIndex = (_b = (_a = openTracks[openTracks.length - 1]) === null || _a === void 0 ? void 0 : _a.index) !== null && _b !== void 0 ? _b : null;
|
|
41
|
+
const siblingIndex = (_c = siblingCounts.get(parentIndex)) !== null && _c !== void 0 ? _c : 0;
|
|
42
|
+
siblingIndexes[index] = siblingIndex;
|
|
43
|
+
siblingCounts.set(parentIndex, siblingIndex + 1);
|
|
44
|
+
openTracks.push({ depth, index });
|
|
45
|
+
}
|
|
46
|
+
const offsets = new Array(timeline.length + 1);
|
|
47
|
+
offsets[0] = paddingStart;
|
|
48
|
+
for (let index = 0; index < trackHeights.length; index++) {
|
|
49
|
+
offsets[index + 1] = offsets[index] + trackHeights[index];
|
|
50
|
+
}
|
|
51
|
+
const rows = timeline.map((track, index) => ({
|
|
52
|
+
afterDropLineOffset: offsets[subtreeEndIndexes[index]] - offsets[index],
|
|
53
|
+
siblingIndex: siblingIndexes[index],
|
|
54
|
+
track,
|
|
55
|
+
}));
|
|
56
|
+
const rootTrackIndexes = new Map();
|
|
57
|
+
for (let index = 0; index < timeline.length; index++) {
|
|
58
|
+
const { nodePathInfo } = timeline[index];
|
|
59
|
+
if (nodePathInfo !== null) {
|
|
60
|
+
rootTrackIndexes.set((0, TimelineSelection_1.getTimelineSequenceSelectionKey)(nodePathInfo), index);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
rootTrackIndexes,
|
|
65
|
+
rows,
|
|
66
|
+
tracksEnd: offsets[offsets.length - 1],
|
|
67
|
+
};
|
|
68
|
+
}, [paddingStart, timeline, trackHeights]);
|
|
69
|
+
const selectedTrackIndexes = (0, react_1.useMemo)(() => {
|
|
70
|
+
const indexes = new Set();
|
|
71
|
+
if (selectedItems.length !== 1) {
|
|
72
|
+
return indexes;
|
|
73
|
+
}
|
|
74
|
+
for (const selectedItem of selectedItems) {
|
|
75
|
+
const key = getSelectionTrackKey(selectedItem);
|
|
76
|
+
const index = key === null ? undefined : layout.rootTrackIndexes.get(key);
|
|
77
|
+
if (index !== undefined) {
|
|
78
|
+
indexes.add(index);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return indexes;
|
|
82
|
+
}, [layout.rootTrackIndexes, selectedItems]);
|
|
83
|
+
const trackHeightsRef = (0, react_1.useRef)(trackHeights);
|
|
84
|
+
trackHeightsRef.current = trackHeights;
|
|
85
|
+
const timelineRef = (0, react_1.useRef)(timeline);
|
|
86
|
+
timelineRef.current = timeline;
|
|
87
|
+
const estimateSize = (0, react_1.useCallback)((index) => {
|
|
88
|
+
var _a;
|
|
89
|
+
return (_a = trackHeightsRef.current[index]) !== null && _a !== void 0 ? _a : 0;
|
|
90
|
+
}, []);
|
|
91
|
+
const getItemKey = (0, react_1.useCallback)((index) => {
|
|
92
|
+
var _a;
|
|
93
|
+
var _b;
|
|
94
|
+
return (_b = (_a = timelineRef.current[index]) === null || _a === void 0 ? void 0 : _a.sequence.id) !== null && _b !== void 0 ? _b : index;
|
|
95
|
+
}, []);
|
|
96
|
+
const rangeExtractor = (0, react_1.useCallback)((range) => {
|
|
97
|
+
const indexes = new Set((0, react_virtual_1.defaultRangeExtractor)(range));
|
|
98
|
+
for (const selectedIndex of selectedTrackIndexes) {
|
|
99
|
+
indexes.add(selectedIndex);
|
|
100
|
+
}
|
|
101
|
+
return [...indexes].sort((a, b) => a - b);
|
|
102
|
+
}, [selectedTrackIndexes]);
|
|
103
|
+
const getScrollElement = (0, react_1.useCallback)(() => timeline_refs_1.timelineVerticalScroll.current, []);
|
|
104
|
+
const virtualizer = (0, react_virtual_1.useVirtualizer)({
|
|
105
|
+
count: timeline.length,
|
|
106
|
+
estimateSize,
|
|
107
|
+
getItemKey,
|
|
108
|
+
getScrollElement,
|
|
109
|
+
overscan: 8,
|
|
110
|
+
paddingEnd,
|
|
111
|
+
paddingStart,
|
|
112
|
+
rangeExtractor,
|
|
113
|
+
});
|
|
114
|
+
(0, react_1.useLayoutEffect)(() => {
|
|
115
|
+
virtualizer.measure();
|
|
116
|
+
}, [trackHeights, virtualizer]);
|
|
117
|
+
(0, react_1.useEffect)(() => {
|
|
118
|
+
if (revealRequest === null) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const key = getSelectionTrackKey(revealRequest.item);
|
|
122
|
+
const index = key === null ? undefined : layout.rootTrackIndexes.get(key);
|
|
123
|
+
if (index !== undefined) {
|
|
124
|
+
virtualizer.scrollToIndex(index, { align: 'center' });
|
|
125
|
+
}
|
|
126
|
+
}, [layout.rootTrackIndexes, revealRequest, virtualizer]);
|
|
127
|
+
const virtualItems = virtualizer.getVirtualItems();
|
|
128
|
+
const value = (0, react_1.useMemo)(() => ({
|
|
129
|
+
rows: layout.rows,
|
|
130
|
+
totalSize: layout.tracksEnd + paddingEnd,
|
|
131
|
+
tracksEnd: layout.tracksEnd,
|
|
132
|
+
virtualItems,
|
|
133
|
+
}), [layout.rows, layout.tracksEnd, paddingEnd, virtualItems]);
|
|
134
|
+
return (jsx_runtime_1.jsx(TimelineVirtualizationContext.Provider, { value: value, children: children }));
|
|
135
|
+
};
|
|
136
|
+
exports.TimelineVirtualizationProvider = TimelineVirtualizationProvider;
|
|
137
|
+
const useTimelineVirtualization = () => {
|
|
138
|
+
const context = (0, react_1.useContext)(TimelineVirtualizationContext);
|
|
139
|
+
if (context === null) {
|
|
140
|
+
throw new Error('useTimelineVirtualization must be used inside TimelineVirtualizationProvider');
|
|
141
|
+
}
|
|
142
|
+
return context;
|
|
143
|
+
};
|
|
144
|
+
exports.useTimelineVirtualization = useTimelineVirtualization;
|