@remotion/studio 4.0.482 → 4.0.483

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.
Files changed (34) hide show
  1. package/dist/components/Canvas.js +19 -0
  2. package/dist/components/InspectorPanel/styles.js +2 -0
  3. package/dist/components/InspectorSequenceSection.js +45 -2
  4. package/dist/components/SelectedOutlineUvControls.js +461 -2
  5. package/dist/components/Timeline/EasingEditorModal.js +39 -1
  6. package/dist/components/Timeline/Timeline.js +2 -1
  7. package/dist/components/Timeline/TimelineEffectItem.js +8 -5
  8. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +2 -2
  9. package/dist/components/Timeline/TimelineKeyframedValue.js +1 -0
  10. package/dist/components/Timeline/TimelineRowChrome.js +6 -4
  11. package/dist/components/Timeline/TimelineSelection.d.ts +7 -1
  12. package/dist/components/Timeline/TimelineSelection.js +19 -3
  13. package/dist/components/Timeline/TimelineSequence.js +20 -8
  14. package/dist/components/Timeline/TimelineSequenceItem.js +16 -13
  15. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +40 -1
  16. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +308 -1
  17. package/dist/components/Timeline/TimelineTrack.js +2 -4
  18. package/dist/components/Timeline/should-subscribe-to-sequence-props.d.ts +4 -0
  19. package/dist/components/Timeline/should-subscribe-to-sequence-props.js +10 -0
  20. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.d.ts +2 -1
  21. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +19 -13
  22. package/dist/components/element-drag-and-drop.d.ts +3 -0
  23. package/dist/components/element-drag-and-drop.js +30 -0
  24. package/dist/components/import-assets.d.ts +11 -0
  25. package/dist/components/import-assets.js +23 -1
  26. package/dist/components/selected-outline-uv.d.ts +71 -1
  27. package/dist/components/selected-outline-uv.js +332 -10
  28. package/dist/esm/{chunk-nkqfa5bw.js → chunk-fq0j774v.js} +2191 -817
  29. package/dist/esm/internals.mjs +2191 -817
  30. package/dist/esm/previewEntry.mjs +2201 -827
  31. package/dist/esm/renderEntry.mjs +1 -1
  32. package/dist/helpers/timeline-layout.d.ts +3 -3
  33. package/dist/helpers/timeline-layout.js +3 -1
  34. package/package.json +11 -11
@@ -37,9 +37,12 @@ const PRESET_PREVIEW_HEIGHT = 30;
37
37
  const PRESET_PREVIEW_PADDING = 5;
38
38
  const PRESET_PREVIEW_Y_MIN = -0.35;
39
39
  const PRESET_PREVIEW_Y_MAX = 1.45;
40
+ const DEFAULT_DURATION_REST_THRESHOLD = 0.02;
40
41
  const DEFAULT_SPRING_EASING = {
41
42
  type: 'spring',
43
+ allowTail: true,
42
44
  damping: 10,
45
+ durationRestThreshold: DEFAULT_DURATION_REST_THRESHOLD,
43
46
  mass: 1,
44
47
  overshootClamping: false,
45
48
  stiffness: 100,
@@ -54,14 +57,22 @@ const EDITOR_EASING_PRESETS = [
54
57
  ];
55
58
  const SPRING_LIMITS = {
56
59
  damping: { min: 1, max: 200, step: 1 },
60
+ durationRestThreshold: { min: 0.001, max: 0.5, step: 0.001 },
57
61
  mass: { min: 0.1, max: 20, step: 0.1 },
58
62
  stiffness: { min: 1, max: 1000, step: 1 },
59
63
  };
60
64
  const SPRING_DECIMAL_PLACES = {
61
65
  damping: 0,
66
+ durationRestThreshold: 3,
62
67
  mass: 2,
63
68
  stiffness: 0,
64
69
  };
70
+ const SPRING_FALLBACKS = {
71
+ damping: DEFAULT_SPRING_EASING.damping,
72
+ durationRestThreshold: DEFAULT_DURATION_REST_THRESHOLD,
73
+ mass: DEFAULT_SPRING_EASING.mass,
74
+ stiffness: DEFAULT_SPRING_EASING.stiffness,
75
+ };
65
76
  const inlineContainer = {
66
77
  width: '100%',
67
78
  minWidth: 0,
@@ -186,7 +197,11 @@ const sanitizeSpringValue = (value, key, fallback) => {
186
197
  };
187
198
  const sanitizeSpring = (spring) => ({
188
199
  type: 'spring',
200
+ allowTail: spring.allowTail,
189
201
  damping: sanitizeSpringValue(spring.damping, 'damping', DEFAULT_SPRING_EASING.damping),
202
+ durationRestThreshold: spring.durationRestThreshold === null
203
+ ? null
204
+ : sanitizeSpringValue(spring.durationRestThreshold, 'durationRestThreshold', DEFAULT_DURATION_REST_THRESHOLD),
190
205
  mass: sanitizeSpringValue(spring.mass, 'mass', DEFAULT_SPRING_EASING.mass),
191
206
  overshootClamping: spring.overshootClamping,
192
207
  stiffness: sanitizeSpringValue(spring.stiffness, 'stiffness', DEFAULT_SPRING_EASING.stiffness),
@@ -210,6 +225,7 @@ const formatNumberWithDecimalPlaces = (decimalPlaces) => (value) => {
210
225
  };
211
226
  const springFormatters = {
212
227
  damping: formatNumberWithDecimalPlaces(SPRING_DECIMAL_PLACES.damping),
228
+ durationRestThreshold: formatNumberWithDecimalPlaces(SPRING_DECIMAL_PLACES.durationRestThreshold),
213
229
  mass: formatNumberWithDecimalPlaces(SPRING_DECIMAL_PLACES.mass),
214
230
  stiffness: formatNumberWithDecimalPlaces(SPRING_DECIMAL_PLACES.stiffness),
215
231
  };
@@ -225,7 +241,9 @@ const areEasingsEqual = (first, second) => {
225
241
  return true;
226
242
  case 'spring':
227
243
  return (second.type === 'spring' &&
244
+ first.allowTail === second.allowTail &&
228
245
  first.damping === second.damping &&
246
+ first.durationRestThreshold === second.durationRestThreshold &&
229
247
  first.mass === second.mass &&
230
248
  first.overshootClamping === second.overshootClamping &&
231
249
  first.stiffness === second.stiffness);
@@ -295,6 +313,7 @@ const presetPreviewYToSvg = (value) => PRESET_PREVIEW_PADDING +
295
313
  (PRESET_PREVIEW_Y_MAX - PRESET_PREVIEW_Y_MIN)) *
296
314
  (PRESET_PREVIEW_HEIGHT - PRESET_PREVIEW_PADDING * 2);
297
315
  const getEasingFunction = (easing) => {
316
+ var _a, _b;
298
317
  switch (easing.type) {
299
318
  case 'linear':
300
319
  return remotion_1.Easing.linear;
@@ -302,7 +321,9 @@ const getEasingFunction = (easing) => {
302
321
  return remotion_1.Easing.bezier(easing.x1, easing.y1, easing.x2, easing.y2);
303
322
  case 'spring':
304
323
  return remotion_1.Easing.spring({
324
+ allowTail: (_a = easing.allowTail) !== null && _a !== void 0 ? _a : undefined,
305
325
  damping: easing.damping,
326
+ durationRestThreshold: (_b = easing.durationRestThreshold) !== null && _b !== void 0 ? _b : undefined,
306
327
  mass: easing.mass,
307
328
  overshootClamping: easing.overshootClamping,
308
329
  stiffness: easing.stiffness,
@@ -374,6 +395,7 @@ const EasingPresetButton = ({ currentEasing, disabled, onClick, preset }) => {
374
395
  return (jsx_runtime_1.jsx("button", { type: "button", style: style, title: preset.label, "aria-label": `Apply ${preset.label} easing`, disabled: disabled, onClick: handleClick, children: jsx_runtime_1.jsx("svg", { width: PRESET_PREVIEW_WIDTH, height: PRESET_PREVIEW_HEIGHT, viewBox: `0 0 ${PRESET_PREVIEW_WIDTH} ${PRESET_PREVIEW_HEIGHT}`, style: presetPreviewSvgStyle, "aria-hidden": "true", focusable: false, children: jsx_runtime_1.jsx("path", { d: path, fill: "none", stroke: "white", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
375
396
  };
376
397
  const EasingEditor = ({ state, renderHeader }) => {
398
+ var _a, _b;
377
399
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
378
400
  const sequencesRef = (0, react_1.useContext)(remotion_1.Internals.SequenceManagerRefContext);
379
401
  const propStatusesRef = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesRefContext);
@@ -532,7 +554,7 @@ const EasingEditor = ({ state, renderHeader }) => {
532
554
  const setSpringNumber = (0, react_1.useCallback)((key, value, commit) => {
533
555
  const next = {
534
556
  ...springRef.current,
535
- [key]: sanitizeSpringValue(value, key, DEFAULT_SPRING_EASING[key]),
557
+ [key]: sanitizeSpringValue(value, key, SPRING_FALLBACKS[key]),
536
558
  };
537
559
  const version = setSpringAndPreview(next);
538
560
  if (commit) {
@@ -547,6 +569,15 @@ const EasingEditor = ({ state, renderHeader }) => {
547
569
  const version = setSpringAndPreview(next);
548
570
  commitEasing(serializeSpring(next), version);
549
571
  }, [commitEasing, setSpringAndPreview]);
572
+ const setAllowTail = (0, react_1.useCallback)(() => {
573
+ var _a;
574
+ const next = {
575
+ ...springRef.current,
576
+ allowTail: !((_a = springRef.current.allowTail) !== null && _a !== void 0 ? _a : false),
577
+ };
578
+ const version = setSpringAndPreview(next);
579
+ commitEasing(serializeSpring(next), version);
580
+ }, [commitEasing, setSpringAndPreview]);
550
581
  const switchMode = (0, react_1.useCallback)((nextMode) => {
551
582
  setMode(nextMode);
552
583
  if (mode === nextMode || previewServerState.type !== 'connected') {
@@ -647,8 +678,11 @@ const EasingEditor = ({ state, renderHeader }) => {
647
678
  return `M ${startPoint.x} ${startPoint.y} C ${firstHandle.x} ${firstHandle.y}, ${secondHandle.x} ${secondHandle.y}, ${endPoint.x} ${endPoint.y}`;
648
679
  }, [endPoint, firstHandle, secondHandle, startPoint]);
649
680
  const springPath = (0, react_1.useMemo)(() => {
681
+ var _a, _b;
650
682
  const easing = remotion_1.Easing.spring({
683
+ allowTail: (_a = spring.allowTail) !== null && _a !== void 0 ? _a : undefined,
651
684
  damping: spring.damping,
685
+ durationRestThreshold: (_b = spring.durationRestThreshold) !== null && _b !== void 0 ? _b : undefined,
652
686
  mass: spring.mass,
653
687
  overshootClamping: spring.overshootClamping,
654
688
  stiffness: spring.stiffness,
@@ -711,8 +745,12 @@ const EasingEditor = ({ state, renderHeader }) => {
711
745
  jsx_runtime_1.jsx("div", { style: coordinateLabel, children: "Mass" }), jsx_runtime_1.jsx("div", { style: coordinateInputWrapper, children: jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: spring.mass, status: "ok", onValueChange: (value) => setSpringNumber('mass', value, false), onValueChangeEnd: (value) => setSpringNumber('mass', value, true), onTextChange: () => undefined, min: SPRING_LIMITS.mass.min, max: SPRING_LIMITS.mass.max, step: SPRING_LIMITS.mass.step, formatter: springFormatters.mass, rightAlign: false, style: numberInputStyle, snapToStep: false, dragDecimalPlaces: SPRING_DECIMAL_PLACES.mass, disabled: disabled }) })
712
746
  ] }), jsx_runtime_1.jsxs("div", { style: coordinateRow, children: [
713
747
  jsx_runtime_1.jsx("div", { style: coordinateLabel, children: "Stiffness" }), jsx_runtime_1.jsx("div", { style: coordinateInputWrapper, children: jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: spring.stiffness, status: "ok", onValueChange: (value) => setSpringNumber('stiffness', value, false), onValueChangeEnd: (value) => setSpringNumber('stiffness', value, true), onTextChange: () => undefined, min: SPRING_LIMITS.stiffness.min, max: SPRING_LIMITS.stiffness.max, step: SPRING_LIMITS.stiffness.step, formatter: springFormatters.stiffness, rightAlign: false, style: numberInputStyle, snapToStep: false, dragDecimalPlaces: SPRING_DECIMAL_PLACES.stiffness, disabled: disabled }) })
748
+ ] }), jsx_runtime_1.jsxs("div", { style: coordinateRow, children: [
749
+ jsx_runtime_1.jsx("div", { style: coordinateLabel, children: "Rest threshold" }), jsx_runtime_1.jsx("div", { style: coordinateInputWrapper, children: jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: (_a = spring.durationRestThreshold) !== null && _a !== void 0 ? _a : DEFAULT_DURATION_REST_THRESHOLD, status: "ok", onValueChange: (value) => setSpringNumber('durationRestThreshold', value, false), onValueChangeEnd: (value) => setSpringNumber('durationRestThreshold', value, true), onTextChange: () => undefined, min: SPRING_LIMITS.durationRestThreshold.min, max: SPRING_LIMITS.durationRestThreshold.max, step: SPRING_LIMITS.durationRestThreshold.step, formatter: springFormatters.durationRestThreshold, rightAlign: false, style: numberInputStyle, snapToStep: false, dragDecimalPlaces: SPRING_DECIMAL_PLACES.durationRestThreshold, disabled: disabled }) })
714
750
  ] }), jsx_runtime_1.jsxs("div", { style: coordinateRow, children: [
715
751
  jsx_runtime_1.jsx("div", { style: coordinateLabel, children: "Clamp overshoot" }), jsx_runtime_1.jsx("div", { style: checkboxWrapper, children: jsx_runtime_1.jsx(Checkbox_1.Checkbox, { checked: spring.overshootClamping, onChange: setOvershootClamping, name: "spring-overshoot-clamping", disabled: disabled, variant: "small" }) })
752
+ ] }), jsx_runtime_1.jsxs("div", { style: coordinateRow, children: [
753
+ jsx_runtime_1.jsx("div", { style: coordinateLabel, children: "Allow tail" }), jsx_runtime_1.jsx("div", { style: checkboxWrapper, children: jsx_runtime_1.jsx(Checkbox_1.Checkbox, { checked: (_b = spring.allowTail) !== null && _b !== void 0 ? _b : false, onChange: setAllowTail, name: "spring-allow-tail", disabled: disabled, variant: "small" }) })
716
754
  ] })
717
755
  ] })
718
756
  ] }))] }));
@@ -53,6 +53,7 @@ const SplitterHandle_1 = require("../Splitter/SplitterHandle");
53
53
  const MaxTimelineTracks_1 = require("./MaxTimelineTracks");
54
54
  const SequencePropsObserver_1 = require("./SequencePropsObserver");
55
55
  const should_show_track_in_timeline_1 = require("./should-show-track-in-timeline");
56
+ const should_subscribe_to_sequence_props_1 = require("./should-subscribe-to-sequence-props");
56
57
  const SubscribeToNodePaths_1 = require("./SubscribeToNodePaths");
57
58
  const timeline_refs_1 = require("./timeline-refs");
58
59
  const TimelineDragHandler_1 = require("./TimelineDragHandler");
@@ -227,7 +228,7 @@ const TimelineInner = () => {
227
228
  }, [filtered]);
228
229
  const hasBeenCut = filtered.length > shown.length;
229
230
  return (jsx_runtime_1.jsxs(TimelineContextMenuArea, { children: [sequences.map((sequence) => {
230
- if (!sequence.controls || !previewConnected || !sequence.getStack()) {
231
+ if (!(0, should_subscribe_to_sequence_props_1.shouldSubscribeToSequenceProps)(sequence, previewConnected)) {
231
232
  return null;
232
233
  }
233
234
  return (jsx_runtime_1.jsx(SubscribeToNodePaths_1.SubscribeToNodePaths, { overrideId: sequence.controls.overrideId, componentIdentity: sequence.controls.componentIdentity, schema: sequence.controls.schema, getStack: sequence.getStack, effects: sequence.effects }, sequence.id));
@@ -71,6 +71,7 @@ const TimelineEffectItem = ({ label, nodePathInfo, effectIndex, effectSchema, do
71
71
  const { propStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
72
72
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
73
73
  const selection = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
74
+ const containsSelection = (0, TimelineSelection_1.useTimelineRowContainsSelection)(nodePathInfo);
74
75
  const [dropIndicator, setDropIndicator] = (0, react_1.useState)(null);
75
76
  const effectStatus = (0, react_1.useMemo)(() => remotion_1.Internals.getEffectPropStatusesCtx({
76
77
  propStatuses,
@@ -205,12 +206,14 @@ const TimelineEffectItem = ({ label, nodePathInfo, effectIndex, effectSchema, do
205
206
  alignSelf: 'stretch',
206
207
  alignItems: 'center',
207
208
  color: (0, TimelineSelection_1.getTimelineColor)(selection.selected, true),
208
- display: 'flex',
209
- flex: 1,
209
+ display: 'inline-flex',
210
+ marginRight: timeline_layout_1.EXPANDED_SECTION_PADDING_RIGHT,
210
211
  minWidth: 0,
211
- paddingRight: timeline_layout_1.EXPANDED_SECTION_PADDING_RIGHT,
212
+ boxShadow: containsSelection && !selection.selected
213
+ ? `inset 0 0 0 2px ${TimelineSelection_1.TIMELINE_SELECTED_LABEL_BACKGROUND}`
214
+ : undefined,
212
215
  };
213
- }, [selection.selected]);
216
+ }, [containsSelection, selection.selected]);
214
217
  const getDropTarget = (0, react_1.useCallback)((e) => {
215
218
  const dragData = getEffectReorderDragData(e.dataTransfer);
216
219
  if (!dragData || dragData.nodePathKey !== nodePathKey) {
@@ -316,7 +319,7 @@ const TimelineEffectItem = ({ label, nodePathInfo, effectIndex, effectSchema, do
316
319
  ...(dropIndicator === 'before' ? { top: -1 } : { bottom: -1 }),
317
320
  };
318
321
  }, [dropIndicator]);
319
- const row = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: canToggle ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: "effect", hidden: isDisabled, onInvoked: onToggle })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: () => toggleTrack(nodePathInfo), label: `${label} section`, disabled: false }), style: rowStyle, selected: selection.selected, selectable: selection.selectable, selectionItem: selection.selectionItem, onSelect: selection.onSelect, showSelectedBackground: true, containsSelection: false, outerHeight: null, children: jsx_runtime_1.jsx("span", { title: label, style: labelStyle, children: label }) }));
322
+ const row = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: canToggle ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: "effect", hidden: isDisabled, onInvoked: onToggle })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: () => toggleTrack(nodePathInfo), label: `${label} section`, disabled: false }), style: rowStyle, selected: selection.selected, selectable: selection.selectable, selectionItem: selection.selectionItem, onSelect: selection.onSelect, showSelectedBackground: true, containsSelection: containsSelection, outerHeight: null, children: jsx_runtime_1.jsx("span", { title: label, style: labelStyle, children: label }) }));
320
323
  const draggableRow = canReorder ? (jsx_runtime_1.jsxs("div", { draggable: true, onDragStart: onDragStart, onDragEnd: onDragEnd, onDragOver: onDragOver, onDragLeave: onDragLeave, onDrop: onDrop, style: reorderWrapper, children: [reorderLineStyle ? jsx_runtime_1.jsx("div", { style: reorderLineStyle }) : null, row] })) : (row);
321
324
  return previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: selection.selectable ? selection.onSelect : null, children: draggableRow })) : (draggableRow);
322
325
  };
@@ -50,11 +50,11 @@ const rowSeparator = {
50
50
  };
51
51
  const TimelineExpandedKeyframeRowUnmemoized = ({ height, keyframes, canEditEasing, nodePathInfo, showSeparator }) => {
52
52
  const timelineWidth = (0, react_1.useContext)(TimelineWidthProvider_1.TimelineWidthContext);
53
- const { selected: rowSelected } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
53
+ const rowHighlightBackground = (0, TimelineSelection_1.useTimelineRowHighlightBackground)(nodePathInfo);
54
54
  const easingSegments = canEditEasing
55
55
  ? (0, get_timeline_easing_segments_1.getTimelineEasingSegments)(keyframes)
56
56
  : [];
57
- return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [showSeparator ? jsx_runtime_1.jsx("div", { style: rowSeparator }) : null, jsx_runtime_1.jsxs("div", { style: { ...row, height }, children: [rowSelected && timelineWidth !== null ? (jsx_runtime_1.jsx("div", { style: (0, TimelineSelection_1.getTimelineSelectedTrackHighlightStyle)(timelineWidth) })) : null, easingSegments.map((segment) => (jsx_runtime_1.jsx(TimelineKeyframeEasingLine_1.TimelineKeyframeEasingLine, { fromFrame: segment.fromFrame, toFrame: segment.toFrame, rowHeight: height, nodePathInfo: nodePathInfo, segmentIndex: segment.segmentIndex }, `${segment.segmentIndex}-${segment.fromFrame}-${segment.toFrame}`))), keyframes.map((keyframe) => (jsx_runtime_1.jsx(TimelineKeyframeDiamond_1.TimelineKeyframeDiamond, { frame: keyframe.frame, rowHeight: height, nodePathInfo: nodePathInfo }, keyframe.frame)))] })
57
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [showSeparator ? jsx_runtime_1.jsx("div", { style: rowSeparator }) : null, jsx_runtime_1.jsxs("div", { style: { ...row, height }, children: [rowHighlightBackground && timelineWidth !== null ? (jsx_runtime_1.jsx("div", { style: (0, TimelineSelection_1.getTimelineSelectedTrackHighlightStyle)(timelineWidth, rowHighlightBackground) })) : null, easingSegments.map((segment) => (jsx_runtime_1.jsx(TimelineKeyframeEasingLine_1.TimelineKeyframeEasingLine, { fromFrame: segment.fromFrame, toFrame: segment.toFrame, rowHeight: height, nodePathInfo: nodePathInfo, segmentIndex: segment.segmentIndex }, `${segment.segmentIndex}-${segment.fromFrame}-${segment.toFrame}`))), keyframes.map((keyframe) => (jsx_runtime_1.jsx(TimelineKeyframeDiamond_1.TimelineKeyframeDiamond, { frame: keyframe.frame, rowHeight: height, nodePathInfo: nodePathInfo }, keyframe.frame)))] })
58
58
  ] }));
59
59
  };
60
60
  exports.TimelineExpandedKeyframeRow = react_1.default.memo(TimelineExpandedKeyframeRowUnmemoized);
@@ -11,6 +11,7 @@ const valuesEqual = (left, right) => {
11
11
  const TimelineKeyframedValue = ({ field, propStatus, sourceFrame, dragOverrideValue, onSave, onDragValueChange, onDragEnd, scaleLockNodePath, }) => {
12
12
  const computedValue = (0, react_1.useMemo)(() => {
13
13
  const raw = remotion_1.Internals.interpolateKeyframedStatus({
14
+ forceSpringAllowTail: false,
14
15
  frame: sourceFrame,
15
16
  status: propStatus,
16
17
  });
@@ -51,13 +51,15 @@ const TimelineRowChrome = ({ depth, eye, keyframeControls, arrow, children, styl
51
51
  e.stopPropagation();
52
52
  onSelect();
53
53
  }, [onSelect]);
54
- const highlightBackground = showSelectedBackground && (selected || containsSelection)
55
- ? TimelineSelection_1.TIMELINE_SELECTED_BACKGROUND
56
- : undefined;
54
+ const highlightBackground = (0, TimelineSelection_1.getTimelineRowHighlightBackground)({
55
+ showSelectedBackground,
56
+ selected,
57
+ containsSelection,
58
+ });
57
59
  const innerRowStyle = (0, react_1.useMemo)(() => ({
58
60
  ...rowBase,
59
61
  ...style,
60
- backgroundColor: outerHeight === undefined ? highlightBackground : undefined,
62
+ backgroundColor: outerHeight === null ? highlightBackground : undefined,
61
63
  }), [style, outerHeight, highlightBackground]);
62
64
  const outerStyle = (0, react_1.useMemo)(() => {
63
65
  if (outerHeight === null) {
@@ -8,7 +8,12 @@ export declare const TIMELINE_SELECTED_LABEL_TEXT = "black";
8
8
  export declare const TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING = 2;
9
9
  export declare const getTimelineSelectedLabelStyle: (selected: boolean, subcategory: boolean) => CSSProperties;
10
10
  export declare const getTimelineColor: (selected: boolean, subcategory: boolean) => "black" | "rgba(255, 255, 255, 0.8)";
11
- export declare const getTimelineSelectedTrackHighlightStyle: (timelineWidth: number) => CSSProperties;
11
+ export declare const getTimelineSelectedTrackHighlightStyle: (timelineWidth: number, backgroundColor?: string) => CSSProperties;
12
+ export declare const getTimelineRowHighlightBackground: ({ showSelectedBackground, selected, containsSelection, }: {
13
+ readonly showSelectedBackground: boolean;
14
+ readonly selected: boolean;
15
+ readonly containsSelection: boolean;
16
+ }) => string | undefined;
12
17
  export declare const TIMELINE_BACKGROUND = "#0F1113";
13
18
  export declare const TIMELINE_TICKS_BACKGROUND = "rgb(31,36,40)";
14
19
  export type TimelineSelection = {
@@ -204,4 +209,5 @@ export declare const useTimelineGuideSelection: (guideId: string) => {
204
209
  selectionItem: TimelineSelection;
205
210
  };
206
211
  export declare const useTimelineRowContainsSelection: (nodePathInfo: SequenceNodePathInfo | null) => boolean;
212
+ export declare const useTimelineRowHighlightBackground: (nodePathInfo: SequenceNodePathInfo | null) => string | undefined;
207
213
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useTimelineRowContainsSelection = exports.useTimelineGuideSelection = exports.useTimelineEasingSelection = exports.useTimelineKeyframeSelection = exports.useTimelineRowSelection = exports.useTimelineFocusableItem = exports.useTimelineMarqueeSelectableItem = exports.useTimelineMarqueeSelection = exports.useCurrentTimelineSelectionStateAsRef = exports.TIMELINE_SCRUBBER_ATTR = exports.TIMELINE_MARQUEE_ITEM_ATTR = exports.useTimelineSelection = exports.TimelineSelectionProvider = exports.TimelineSelectableItemsProvider = exports.TimelineSelectAllKeybindings = exports.getTimelineSequenceSelectionKey = exports.getSelectableTimelineItems = exports.getSelectableTimelineSequenceSelections = exports.getTimelineSelectionKey = exports.getTimelineSelectionFromNodePathInfo = exports.TimelineSelectionOrderProvider = exports.getTimelineMarqueeSelection = exports.timelineMarqueeRectsIntersect = exports.getClampedTimelineMarqueePoint = exports.getNormalizedTimelineMarqueeRect = exports.getAvailableTimelineSelectionState = exports.getTimelineSelectionAfterInteraction = exports.EMPTY_TIMELINE_SELECTION_STATE = exports.shouldSelectTimelineRowOnPointerDown = exports.isTimelineSelectionModifierEvent = exports.TIMELINE_TICKS_BACKGROUND = exports.TIMELINE_BACKGROUND = exports.getTimelineSelectedTrackHighlightStyle = exports.getTimelineColor = exports.getTimelineSelectedLabelStyle = exports.TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING = exports.TIMELINE_SELECTED_LABEL_TEXT = exports.TIMELINE_SELECTED_LABEL_BACKGROUND = exports.TIMELINE_SELECTED_BACKGROUND = void 0;
3
+ exports.useTimelineRowHighlightBackground = exports.useTimelineRowContainsSelection = exports.useTimelineGuideSelection = exports.useTimelineEasingSelection = exports.useTimelineKeyframeSelection = exports.useTimelineRowSelection = exports.useTimelineFocusableItem = exports.useTimelineMarqueeSelectableItem = exports.useTimelineMarqueeSelection = exports.useCurrentTimelineSelectionStateAsRef = exports.TIMELINE_SCRUBBER_ATTR = exports.TIMELINE_MARQUEE_ITEM_ATTR = exports.useTimelineSelection = exports.TimelineSelectionProvider = exports.TimelineSelectableItemsProvider = exports.TimelineSelectAllKeybindings = exports.getTimelineSequenceSelectionKey = exports.getSelectableTimelineItems = exports.getSelectableTimelineSequenceSelections = exports.getTimelineSelectionKey = exports.getTimelineSelectionFromNodePathInfo = exports.TimelineSelectionOrderProvider = exports.getTimelineMarqueeSelection = exports.timelineMarqueeRectsIntersect = exports.getClampedTimelineMarqueePoint = exports.getNormalizedTimelineMarqueeRect = exports.getAvailableTimelineSelectionState = exports.getTimelineSelectionAfterInteraction = exports.EMPTY_TIMELINE_SELECTION_STATE = exports.shouldSelectTimelineRowOnPointerDown = exports.isTimelineSelectionModifierEvent = exports.TIMELINE_TICKS_BACKGROUND = exports.TIMELINE_BACKGROUND = exports.getTimelineRowHighlightBackground = exports.getTimelineSelectedTrackHighlightStyle = exports.getTimelineColor = exports.getTimelineSelectedLabelStyle = exports.TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING = exports.TIMELINE_SELECTED_LABEL_TEXT = exports.TIMELINE_SELECTED_LABEL_BACKGROUND = exports.TIMELINE_SELECTED_BACKGROUND = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const studio_shared_1 = require("@remotion/studio-shared");
6
6
  const react_1 = require("react");
@@ -42,8 +42,8 @@ const getTimelineColor = (selected, subcategory) => {
42
42
  : 'rgba(255, 255, 255, 0.8)';
43
43
  };
44
44
  exports.getTimelineColor = getTimelineColor;
45
- const getTimelineSelectedTrackHighlightStyle = (timelineWidth) => ({
46
- backgroundColor: exports.TIMELINE_SELECTED_BACKGROUND,
45
+ const getTimelineSelectedTrackHighlightStyle = (timelineWidth, backgroundColor = exports.TIMELINE_SELECTED_BACKGROUND) => ({
46
+ backgroundColor,
47
47
  bottom: 0,
48
48
  left: -timeline_layout_1.TIMELINE_PADDING,
49
49
  pointerEvents: 'none',
@@ -52,6 +52,12 @@ const getTimelineSelectedTrackHighlightStyle = (timelineWidth) => ({
52
52
  width: timelineWidth,
53
53
  });
54
54
  exports.getTimelineSelectedTrackHighlightStyle = getTimelineSelectedTrackHighlightStyle;
55
+ const getTimelineRowHighlightBackground = ({ showSelectedBackground, selected, containsSelection, }) => {
56
+ return showSelectedBackground && (selected || containsSelection)
57
+ ? exports.TIMELINE_SELECTED_BACKGROUND
58
+ : undefined;
59
+ };
60
+ exports.getTimelineRowHighlightBackground = getTimelineRowHighlightBackground;
55
61
  exports.TIMELINE_BACKGROUND = '#0F1113';
56
62
  exports.TIMELINE_TICKS_BACKGROUND = colors_1.BACKGROUND;
57
63
  const isTimelineSelectionModifierEvent = ({ shiftKey, metaKey, ctrlKey, }) => {
@@ -1043,3 +1049,13 @@ const useTimelineRowContainsSelection = (nodePathInfo) => {
1043
1049
  return containsSelection(nodePathInfo);
1044
1050
  };
1045
1051
  exports.useTimelineRowContainsSelection = useTimelineRowContainsSelection;
1052
+ const useTimelineRowHighlightBackground = (nodePathInfo) => {
1053
+ const { selected } = (0, exports.useTimelineRowSelection)(nodePathInfo);
1054
+ const containsSelection = (0, exports.useTimelineRowContainsSelection)(nodePathInfo);
1055
+ return (0, exports.getTimelineRowHighlightBackground)({
1056
+ showSelectedBackground: true,
1057
+ selected,
1058
+ containsSelection,
1059
+ });
1060
+ };
1061
+ exports.useTimelineRowHighlightBackground = useTimelineRowHighlightBackground;
@@ -154,10 +154,10 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
154
154
  // If a duration is 1, it is essentially a still and it should have width 0
155
155
  // Some compositions may not be longer than their media duration,
156
156
  // if that is the case, it needs to be asynchronously determined
157
- var _a, _b;
158
- var _c, _d, _e, _f, _g;
157
+ var _a, _b, _c;
158
+ var _d, _e, _f, _g, _h, _j;
159
159
  const video = remotion_1.Internals.useVideo();
160
- const maxMediaDuration = (0, use_max_media_duration_1.useMaxMediaDuration)(s, (_c = video === null || video === void 0 ? void 0 : video.fps) !== null && _c !== void 0 ? _c : 30);
160
+ const maxMediaDuration = (0, use_max_media_duration_1.useMaxMediaDuration)(s, (_d = video === null || video === void 0 ? void 0 : video.fps) !== null && _d !== void 0 ? _d : 30);
161
161
  const effectiveMaxMediaDuration = s.loopDisplay ? null : maxMediaDuration;
162
162
  const originalLocation = (0, use_resolved_stack_react_to_change_1.useResolveStackAndReactToChange)(s.getStack);
163
163
  const validatedLocation = (0, react_1.useMemo)(() => {
@@ -174,7 +174,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
174
174
  };
175
175
  }, [originalLocation]);
176
176
  const { propStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
177
- const nodePath = (_d = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _d !== void 0 ? _d : null;
177
+ const nodePath = (_e = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _e !== void 0 ? _e : null;
178
178
  const propStatusesForOverride = (0, react_1.useMemo)(() => {
179
179
  return nodePath
180
180
  ? remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)
@@ -182,6 +182,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
182
182
  }, [propStatuses, nodePath]);
183
183
  const durationCanUpdate = Boolean(((_a = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.durationInFrames) === null || _a === void 0 ? void 0 : _a.status) === 'static');
184
184
  const fromCanUpdate = Boolean(((_b = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.from) === null || _b === void 0 ? void 0 : _b.status) === 'static');
185
+ const trimBeforeCanUpdate = Boolean(((_c = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.trimBefore) === null || _c === void 0 ? void 0 : _c.status) === 'static');
185
186
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
186
187
  const previewConnected = previewServerState.type === 'connected';
187
188
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
@@ -291,7 +292,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
291
292
  sequenceFrameOffset,
292
293
  setPropStatuses,
293
294
  timelinePosition,
294
- validatedSource: (_e = validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) !== null && _e !== void 0 ? _e : null,
295
+ validatedSource: (_f = validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) !== null && _f !== void 0 ? _f : null,
295
296
  });
296
297
  const contextMenuValues = (0, react_1.useMemo)(() => {
297
298
  if (!previewConnected) {
@@ -312,7 +313,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
312
313
  originalLocation,
313
314
  selectAsset,
314
315
  sequence: s,
315
- sourceActions: [freezeFrameMenuItem],
316
+ sourceActions: freezeFrameMenuItem ? [freezeFrameMenuItem] : [],
316
317
  });
317
318
  }, [
318
319
  assetLinkInfo,
@@ -340,7 +341,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
340
341
  const { onPointerDown: onMoveDragPointerDown } = (0, TimelineSequenceRightEdgeDragHandle_1.useTimelineSequenceFromDrag)({
341
342
  nodePathInfo,
342
343
  windowWidth,
343
- timelineDurationInFrames: (_f = video === null || video === void 0 ? void 0 : video.durationInFrames) !== null && _f !== void 0 ? _f : 1,
344
+ timelineDurationInFrames: (_g = video === null || video === void 0 ? void 0 : video.durationInFrames) !== null && _g !== void 0 ? _g : 1,
344
345
  });
345
346
  if (!video) {
346
347
  throw new TypeError('Expected video config');
@@ -391,10 +392,21 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
391
392
  nodePath !== null &&
392
393
  validatedLocation !== null &&
393
394
  durationCanUpdate;
395
+ const showLeftEdgeDragHandle = (s.type === 'sequence' ||
396
+ s.type === 'image' ||
397
+ s.type === 'audio' ||
398
+ s.type === 'video') &&
399
+ !s.isInsideSeries &&
400
+ nodePath !== null &&
401
+ validatedLocation !== null &&
402
+ Boolean(s.controls) &&
403
+ fromCanUpdate &&
404
+ durationCanUpdate &&
405
+ trimBeforeCanUpdate;
394
406
  if (maxMediaDuration === null && !s.loopDisplay) {
395
407
  return null;
396
408
  }
397
- const sequence = (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premountWidth: premountWidth, postmountWidth: postmountWidth, style: style, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset, fromCanUpdate: fromCanUpdate, frozenFrame: frozenFrame, onMoveDragPointerDown: onMoveDragPointerDown, children: [s.type === 'audio' ? (jsx_runtime_1.jsx(AudioWaveform_1.AudioWaveform, { src: s.src, height: timeline_layout_1.TIMELINE_LAYER_HEIGHT_AUDIO, doesVolumeChange: s.doesVolumeChange, visualizationWidth: width, startFrom: s.startMediaFrom, durationInFrames: s.duration, volume: s.volume, playbackRate: s.playbackRate, loopDisplay: s.loopDisplay })) : null, s.type === 'video' ? (jsx_runtime_1.jsx(TimelineVideoInfo_1.TimelineVideoInfo, { src: s.src, visualizationWidth: width, naturalWidth: naturalWidth, trimBefore: s.startMediaFrom, durationInFrames: s.duration, playbackRate: s.playbackRate, volume: s.volume, doesVolumeChange: s.doesVolumeChange, premountWidth: premountWidth !== null && premountWidth !== void 0 ? premountWidth : 0, postmountWidth: postmountWidth !== null && postmountWidth !== void 0 ? postmountWidth : 0, loopDisplay: s.loopDisplay, frozenMediaFrame: s.frozenMediaFrame })) : null, s.type === 'image' ? (jsx_runtime_1.jsx(TimelineImageInfo_1.TimelineImageInfo, { src: s.src, visualizationWidth: width })) : null, s.loopDisplay === undefined ? null : (jsx_runtime_1.jsx(LoopedTimelineIndicators_1.LoopedTimelineIndicator, { loops: s.loopDisplay.numberOfTimes })), showRightEdgeDragHandle && nodePathInfo && validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceRightEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_g = video.durationInFrames) !== null && _g !== void 0 ? _g : 1 })) : null] }));
409
+ const sequence = (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premountWidth: premountWidth, postmountWidth: postmountWidth, style: style, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset, fromCanUpdate: fromCanUpdate, frozenFrame: frozenFrame, onMoveDragPointerDown: onMoveDragPointerDown, children: [s.type === 'audio' ? (jsx_runtime_1.jsx(AudioWaveform_1.AudioWaveform, { src: s.src, height: timeline_layout_1.TIMELINE_LAYER_HEIGHT_AUDIO, doesVolumeChange: s.doesVolumeChange, visualizationWidth: width, startFrom: s.startMediaFrom, durationInFrames: s.duration, volume: s.volume, playbackRate: s.playbackRate, loopDisplay: s.loopDisplay })) : null, s.type === 'video' ? (jsx_runtime_1.jsx(TimelineVideoInfo_1.TimelineVideoInfo, { src: s.src, visualizationWidth: width, naturalWidth: naturalWidth, trimBefore: s.startMediaFrom, durationInFrames: s.duration, playbackRate: s.playbackRate, volume: s.volume, doesVolumeChange: s.doesVolumeChange, premountWidth: premountWidth !== null && premountWidth !== void 0 ? premountWidth : 0, postmountWidth: postmountWidth !== null && postmountWidth !== void 0 ? postmountWidth : 0, loopDisplay: s.loopDisplay, frozenMediaFrame: s.frozenMediaFrame })) : null, s.type === 'image' ? (jsx_runtime_1.jsx(TimelineImageInfo_1.TimelineImageInfo, { src: s.src, visualizationWidth: width })) : null, s.loopDisplay === undefined ? null : (jsx_runtime_1.jsx(LoopedTimelineIndicators_1.LoopedTimelineIndicator, { loops: s.loopDisplay.numberOfTimes })), showLeftEdgeDragHandle && nodePathInfo && validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceLeftEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_h = video.durationInFrames) !== null && _h !== void 0 ? _h : 1 })) : null, showRightEdgeDragHandle && nodePathInfo && validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceRightEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_j = video.durationInFrames) !== null && _j !== void 0 ? _j : 1 })) : null] }));
398
410
  return previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: onContextMenuOpen, children: sequence })) : (sequence);
399
411
  };
400
412
  exports.TimelineSequence = react_1.default.memo(TimelineSequenceFn);
@@ -437,17 +437,6 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
437
437
  }
438
438
  toggleTrack(nodePathInfo);
439
439
  }, [nodePathInfo, toggleTrack]);
440
- const onShowInEditorDoubleClick = (0, react_1.useCallback)((e) => {
441
- if (!canOpenInEditor) {
442
- return;
443
- }
444
- if ((0, TimelineSelection_1.isTimelineSelectionModifierEvent)(e)) {
445
- e.stopPropagation();
446
- return;
447
- }
448
- e.stopPropagation();
449
- openInEditor();
450
- }, [canOpenInEditor, openInEditor]);
451
440
  const propStatusesForOverride = (0, react_1.useMemo)(() => {
452
441
  return nodePath
453
442
  ? remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)
@@ -548,6 +537,18 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
548
537
  codeNameStatus !== undefined &&
549
538
  codeNameStatus !== null &&
550
539
  codeNameStatus.status === 'static';
540
+ const onSequenceDoubleClick = (0, react_1.useCallback)((e) => {
541
+ if ((0, TimelineSelection_1.isTimelineSelectionModifierEvent)(e)) {
542
+ e.stopPropagation();
543
+ return;
544
+ }
545
+ e.stopPropagation();
546
+ if (canRenameThisSequence) {
547
+ setIsRenaming(true);
548
+ return;
549
+ }
550
+ openInEditor();
551
+ }, [canRenameThisSequence, openInEditor]);
551
552
  const canRenameSelectedSequence = canRenameThisSequence &&
552
553
  selected &&
553
554
  selectedItems.length === 1 &&
@@ -718,7 +719,7 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
718
719
  subMenu: null,
719
720
  value: 'rename-sequence',
720
721
  },
721
- freezeFrameMenuItem,
722
+ ...(freezeFrameMenuItem ? [freezeFrameMenuItem] : []),
722
723
  ],
723
724
  });
724
725
  }, [
@@ -801,7 +802,9 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
801
802
  clientId: previewServerState.clientId,
802
803
  });
803
804
  }, [canDropEffect, nodePath, previewServerState, validatedLocation]);
804
- const trackRow = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: nestedDepth, eye: canToggleVisibility ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: hasExpandableContent && nodePathInfo !== null ? (jsx_runtime_1.jsx(TimelineSequenceExpandArrow, { disabled: !previewConnected, isExpanded: isExpanded, nodePathInfo: nodePathInfo, onToggleExpand: onToggleExpand, sequence: sequence })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {})), style: rowStyle, selected: selected, selectable: selectable, selectionItem: selectionItem, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, outerHeight: outerHeight, onDragLeave: canDropEffect ? onEffectDragLeave : undefined, onDragOver: canDropEffect ? onEffectDragOver : undefined, onDrop: canDropEffect ? onEffectDrop : undefined, onDoubleClick: canOpenInEditor ? onShowInEditorDoubleClick : undefined, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [
805
+ const trackRow = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: nestedDepth, eye: canToggleVisibility ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: hasExpandableContent && nodePathInfo !== null ? (jsx_runtime_1.jsx(TimelineSequenceExpandArrow, { disabled: !previewConnected, isExpanded: isExpanded, nodePathInfo: nodePathInfo, onToggleExpand: onToggleExpand, sequence: sequence })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {})), style: rowStyle, selected: selected, selectable: selectable, selectionItem: selectionItem, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, outerHeight: outerHeight, onDragLeave: canDropEffect ? onEffectDragLeave : undefined, onDragOver: canDropEffect ? onEffectDragOver : undefined, onDrop: canDropEffect ? onEffectDrop : undefined, onDoubleClick: canRenameThisSequence || canOpenInEditor
806
+ ? onSequenceDoubleClick
807
+ : undefined, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [
805
808
  jsx_runtime_1.jsx(TimelineSequenceName_1.TimelineSequenceName, { displayName: displayName, selected: selected, containsSelection: containsSelection, editing: isRenaming, onCancelEditing: onCancelRenaming, onSaveName: onSaveName }), mediaSrc ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
806
809
  jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }),
807
810
  " ",
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { OverrideIdToNodePaths, PropStatuses, SequencePropsSubscriptionKey, TSequence } from 'remotion';
2
+ import type { OverrideIdToNodePaths, PropStatuses, SequencePropsSubscriptionKey, TSequence, InteractivitySchema } from 'remotion';
3
3
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
4
4
  import { type SaveSequencePropChange } from './save-sequence-prop';
5
5
  import { type TimelineSelection } from './TimelineSelection';
@@ -8,6 +8,14 @@ export type TimelineSequenceDurationDragTarget = {
8
8
  readonly initialDuration: number;
9
9
  readonly nodePath: SequencePropsSubscriptionKey;
10
10
  };
11
+ export type TimelineSequenceLeftEdgeDragTarget = {
12
+ readonly fileName: string;
13
+ readonly initialDuration: number;
14
+ readonly initialFrom: number;
15
+ readonly initialTrimBefore: number;
16
+ readonly nodePath: SequencePropsSubscriptionKey;
17
+ readonly schema: InteractivitySchema;
18
+ };
11
19
  export type TimelineSequenceFromDragTarget = {
12
20
  readonly fileName: string;
13
21
  readonly initialFrom: number;
@@ -17,6 +25,25 @@ export declare const getTimelineSequenceDurationDragValue: ({ initialDuration, d
17
25
  readonly initialDuration: number;
18
26
  readonly deltaFrames: number;
19
27
  }) => number;
28
+ export declare const getTimelineSequenceLeftEdgeDragDelta: ({ initialDuration, initialTrimBefore, deltaFrames, }: {
29
+ readonly initialDuration: number;
30
+ readonly initialTrimBefore: number;
31
+ readonly deltaFrames: number;
32
+ }) => number;
33
+ export declare const getTimelineSequenceLeftEdgeDragValues: ({ initialDuration, initialFrom, initialTrimBefore, deltaFrames, }: {
34
+ readonly initialDuration: number;
35
+ readonly initialFrom: number;
36
+ readonly initialTrimBefore: number;
37
+ readonly deltaFrames: number;
38
+ }) => {
39
+ durationInFrames: number;
40
+ from: number;
41
+ trimBefore: number;
42
+ };
43
+ export declare const getTimelineSequenceLeftEdgeDragChanges: ({ targets, deltaFrames, }: {
44
+ readonly targets: readonly TimelineSequenceLeftEdgeDragTarget[];
45
+ readonly deltaFrames: number;
46
+ }) => SaveSequencePropChange[];
20
47
  export declare const getTimelineSequenceDurationDragChanges: ({ targets, deltaFrames, }: {
21
48
  readonly targets: readonly TimelineSequenceDurationDragTarget[];
22
49
  readonly deltaFrames: number;
@@ -36,6 +63,13 @@ export declare const getTimelineSequenceDurationDragTargets: ({ draggedNodePathI
36
63
  readonly overrideIdsToNodePaths: OverrideIdToNodePaths;
37
64
  readonly propStatuses: PropStatuses;
38
65
  }) => TimelineSequenceDurationDragTarget[] | null;
66
+ export declare const getTimelineSequenceLeftEdgeDragTargets: ({ draggedNodePathInfo, selectedItems, sequences, overrideIdsToNodePaths, propStatuses, }: {
67
+ readonly draggedNodePathInfo: SequenceNodePathInfo;
68
+ readonly selectedItems: readonly TimelineSelection[];
69
+ readonly sequences: TSequence[];
70
+ readonly overrideIdsToNodePaths: OverrideIdToNodePaths;
71
+ readonly propStatuses: PropStatuses;
72
+ }) => TimelineSequenceLeftEdgeDragTarget[] | null;
39
73
  export declare const getTimelineSequenceFromDragTargets: ({ draggedNodePathInfo, selectedItems, sequences, overrideIdsToNodePaths, propStatuses, }: {
40
74
  readonly draggedNodePathInfo: SequenceNodePathInfo;
41
75
  readonly selectedItems: readonly TimelineSelection[];
@@ -43,6 +77,11 @@ export declare const getTimelineSequenceFromDragTargets: ({ draggedNodePathInfo,
43
77
  readonly overrideIdsToNodePaths: OverrideIdToNodePaths;
44
78
  readonly propStatuses: PropStatuses;
45
79
  }) => TimelineSequenceFromDragTarget[] | null;
80
+ export declare const TimelineSequenceLeftEdgeDragHandle: React.FC<{
81
+ readonly nodePathInfo: SequenceNodePathInfo;
82
+ readonly windowWidth: number;
83
+ readonly timelineDurationInFrames: number;
84
+ }>;
46
85
  export declare const useTimelineSequenceFromDrag: ({ nodePathInfo, windowWidth, timelineDurationInFrames, }: {
47
86
  readonly nodePathInfo: SequenceNodePathInfo | null;
48
87
  readonly windowWidth: number;