@remotion/studio 4.0.483 → 4.0.485

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 (113) hide show
  1. package/dist/components/ColorPicker/ColorPicker.js +65 -3
  2. package/dist/components/ColorPicker/ColorPickerPopup.d.ts +1 -0
  3. package/dist/components/ColorPicker/ColorPickerPopup.js +3 -2
  4. package/dist/components/ContextMenu.js +75 -1
  5. package/dist/components/CurrentComposition.js +3 -2
  6. package/dist/components/InlineCompositionName.d.ts +7 -0
  7. package/dist/components/InlineCompositionName.js +58 -0
  8. package/dist/components/InlineEditableTitle.d.ts +7 -0
  9. package/dist/components/InlineEditableTitle.js +129 -0
  10. package/dist/components/InspectorPanel/EasingInspector.js +184 -10
  11. package/dist/components/InspectorPanel/KeyframeEasingNavigator.d.ts +14 -0
  12. package/dist/components/InspectorPanel/KeyframeEasingNavigator.js +146 -0
  13. package/dist/components/InspectorPanel/KeyframeInspector.d.ts +1 -1
  14. package/dist/components/InspectorPanel/KeyframeInspector.js +229 -5
  15. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +17 -0
  16. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +80 -0
  17. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +4 -58
  18. package/dist/components/InspectorPanel/common.d.ts +12 -0
  19. package/dist/components/InspectorPanel/common.js +78 -1
  20. package/dist/components/InspectorPanel/easing-inspector-selection.d.ts +14 -0
  21. package/dist/components/InspectorPanel/easing-inspector-selection.js +18 -0
  22. package/dist/components/InspectorPanel/keyframe-easing-navigator-items.d.ts +24 -0
  23. package/dist/components/InspectorPanel/keyframe-easing-navigator-items.js +40 -0
  24. package/dist/components/InspectorPanel/keyframe-inspector-frame.d.ts +8 -0
  25. package/dist/components/InspectorPanel/keyframe-inspector-frame.js +14 -0
  26. package/dist/components/InspectorPanel/styles.d.ts +1 -0
  27. package/dist/components/InspectorPanel/styles.js +9 -3
  28. package/dist/components/InspectorSequenceSection.js +37 -10
  29. package/dist/components/Modals.js +1 -1
  30. package/dist/components/NewComposition/CodemodFooter.d.ts +7 -1
  31. package/dist/components/NewComposition/CodemodFooter.js +17 -12
  32. package/dist/components/NewComposition/DeleteComposition.js +7 -1
  33. package/dist/components/NewComposition/DeleteFolder.js +7 -1
  34. package/dist/components/NewComposition/DuplicateComposition.js +17 -10
  35. package/dist/components/NewComposition/InputAndValidationContainer.d.ts +3 -0
  36. package/dist/components/NewComposition/InputAndValidationContainer.js +15 -0
  37. package/dist/components/NewComposition/NewCompDuration.js +7 -6
  38. package/dist/components/NewComposition/NewComposition.d.ts +5 -1
  39. package/dist/components/NewComposition/NewComposition.js +29 -86
  40. package/dist/components/NewComposition/RenameComposition.js +13 -14
  41. package/dist/components/NewComposition/RenameFolder.js +9 -2
  42. package/dist/components/NewComposition/RenameStaticFile.js +2 -1
  43. package/dist/components/NewComposition/ValidationMessage.js +9 -1
  44. package/dist/components/OptionsPanel.d.ts +0 -3
  45. package/dist/components/OptionsPanel.js +7 -3
  46. package/dist/components/Preview.js +1 -1
  47. package/dist/components/RenderModal/ServerRenderModal.js +4 -3
  48. package/dist/components/RenderModal/WebRenderModal.js +2 -1
  49. package/dist/components/SelectedOutlineElement.js +45 -3
  50. package/dist/components/SelectedOutlineOverlay.d.ts +3 -1
  51. package/dist/components/SelectedOutlineOverlay.js +48 -15
  52. package/dist/components/Timeline/EasingEditorModal.js +9 -4
  53. package/dist/components/Timeline/TimelineDeleteKeybindings.js +45 -2
  54. package/dist/components/Timeline/TimelineEffectPropItem.js +82 -1
  55. package/dist/components/Timeline/TimelineExpandedSection.js +1 -0
  56. package/dist/components/Timeline/TimelineInOutPointerHandle.js +2 -1
  57. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +1 -1
  58. package/dist/components/Timeline/TimelineKeyframeControls.js +38 -7
  59. package/dist/components/Timeline/TimelineKeyframeEasingLine.d.ts +4 -0
  60. package/dist/components/Timeline/TimelineKeyframeEasingLine.js +12 -6
  61. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +4 -0
  62. package/dist/components/Timeline/TimelineSelection.js +1 -0
  63. package/dist/components/Timeline/TimelineSequenceItem.js +13 -62
  64. package/dist/components/Timeline/TimelineSequenceName.d.ts +1 -0
  65. package/dist/components/Timeline/TimelineSequenceName.js +7 -6
  66. package/dist/components/Timeline/TimelineSequencePropItem.d.ts +1 -1
  67. package/dist/components/Timeline/TimelineSequencePropItem.js +86 -4
  68. package/dist/components/Timeline/TimelineSlider.js +17 -3
  69. package/dist/components/Timeline/TimelineTextContentField.d.ts +12 -0
  70. package/dist/components/Timeline/TimelineTextContentField.js +100 -0
  71. package/dist/components/Timeline/TimelineWidthProvider.js +18 -3
  72. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +8 -2
  73. package/dist/components/Timeline/delete-selected-timeline-item.js +80 -1
  74. package/dist/components/Timeline/focus-inspector-field.d.ts +16 -0
  75. package/dist/components/Timeline/focus-inspector-field.js +49 -0
  76. package/dist/components/Timeline/get-animation-item-selection-for-frame.d.ts +18 -0
  77. package/dist/components/Timeline/get-animation-item-selection-for-frame.js +49 -0
  78. package/dist/components/Timeline/get-easing-selection-after-keyframe-delete.d.ts +15 -0
  79. package/dist/components/Timeline/get-easing-selection-after-keyframe-delete.js +26 -0
  80. package/dist/components/Timeline/save-sequence-prop.js +2 -0
  81. package/dist/components/Timeline/split-selected-timeline-item.d.ts +38 -0
  82. package/dist/components/Timeline/split-selected-timeline-item.js +156 -0
  83. package/dist/components/Timeline/timeline-field-display-utils.js +2 -0
  84. package/dist/components/Timeline/update-selected-easing.d.ts +1 -0
  85. package/dist/components/Timeline/update-selected-easing.js +4 -3
  86. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +1 -0
  87. package/dist/components/Timeline/use-rename-sequence.d.ts +30 -0
  88. package/dist/components/Timeline/use-rename-sequence.js +115 -0
  89. package/dist/components/Timeline/use-timeline-expanded-tree.d.ts +2 -1
  90. package/dist/components/Timeline/use-timeline-expanded-tree.js +3 -1
  91. package/dist/components/Timeline/use-timeline-height.js +1 -0
  92. package/dist/components/composition-menu-items.js +3 -0
  93. package/dist/components/folder-menu-items.js +20 -0
  94. package/dist/components/options-sidebar-tabs.d.ts +4 -0
  95. package/dist/components/options-sidebar-tabs.js +5 -0
  96. package/dist/components/selected-outline-types.d.ts +6 -1
  97. package/dist/esm/{chunk-fq0j774v.js → chunk-103pp4n7.js} +17652 -15098
  98. package/dist/esm/internals.mjs +17652 -15098
  99. package/dist/esm/previewEntry.mjs +18357 -15803
  100. package/dist/esm/renderEntry.mjs +1 -1
  101. package/dist/helpers/render-codec-label.d.ts +1 -1
  102. package/dist/helpers/timeline-layout.d.ts +4 -3
  103. package/dist/helpers/timeline-layout.js +3 -1
  104. package/dist/helpers/use-create-composition.d.ts +35 -0
  105. package/dist/helpers/use-create-composition.js +111 -0
  106. package/dist/helpers/use-menu-structure.js +0 -14
  107. package/dist/helpers/use-rename-composition.d.ts +16 -0
  108. package/dist/helpers/use-rename-composition.js +49 -0
  109. package/dist/state/modals.d.ts +3 -0
  110. package/dist/state/timeline-zoom.js +17 -14
  111. package/dist/state/z-index.d.ts +1 -0
  112. package/dist/state/z-index.js +11 -2
  113. package/package.json +12 -12
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.SelectedOutlineOverlay = exports.orderOutlinesForRendering = exports.selectedOutlineDragThresholdPx = exports.getTransformedSvgViewportPoints = exports.getSequencesWithSelectableOutlines = exports.getSelectedSequenceKeys = exports.getSelectedOutlineRotationPivot = exports.getSelectedOutlineRotationDeltaDegrees = exports.getSelectedOutlineRotationCornerInfo = exports.getSelectedEffectFieldsBySequenceKey = exports.getOutlineSelectionInteraction = exports.snapSelectedOutlineTransformOriginUv = exports.snapSelectedOutlineUv = exports.snapSelectedOutlineRotationDeltaDegrees = exports.selectedOutlineTransformOriginSnapThresholdPx = exports.selectedOutlineUvSnapThresholdPx = exports.isSelectedOutlineDragPastThreshold = exports.getSelectedOutlineTransformOriginLockedAxis = exports.getSelectedOutlineScaleEdgeInfo = exports.getSelectedOutlineScaleDragValues = exports.getSelectedOutlineScaleDragStates = exports.getSelectedOutlineScaleDragChanges = exports.getSelectedOutlineRotationDragValues = exports.getSelectedOutlineRotationDragStates = exports.getSelectedOutlineRotationDragChanges = exports.getSelectedOutlineKeyboardNudgeDeltas = exports.getSelectedOutlineKeyboardNudgeDelta = exports.getSelectedOutlineDragValues = exports.getSelectedOutlineDragChanges = exports.getSelectedOutlineActiveSchema = exports.compensateTranslateForTransformOrigin = exports.applySelectedOutlineTransformOriginAxisLock = exports.applySelectedOutlineDragAxisLock = void 0;
36
+ exports.SelectedOutlineOverlay = exports.orderOutlinesForRendering = exports.selectedOutlineDragThresholdPx = exports.getTransformedSvgViewportPoints = exports.getSequencesWithSelectableOutlines = exports.getSelectedSequenceKeys = exports.getSelectedOutlineRotationPivot = exports.getSelectedOutlineRotationDeltaDegrees = exports.getSelectedOutlineRotationCornerInfo = exports.getSelectedEffectFieldsBySequenceKey = exports.getOutlineSelectionInteraction = exports.snapSelectedOutlineUv = exports.snapSelectedOutlineTransformOriginUv = exports.snapSelectedOutlineRotationDeltaDegrees = exports.selectedOutlineUvSnapThresholdPx = exports.selectedOutlineTransformOriginSnapThresholdPx = exports.isSelectedOutlineDragPastThreshold = exports.getSelectedOutlineTransformOriginLockedAxis = exports.getSelectedOutlineScaleEdgeInfo = exports.getSelectedOutlineScaleDragValues = exports.getSelectedOutlineScaleDragStates = exports.getSelectedOutlineScaleDragChanges = exports.getSelectedOutlineRotationDragValues = exports.getSelectedOutlineRotationDragStates = exports.getSelectedOutlineRotationDragChanges = exports.getSelectedOutlineKeyboardNudgeDeltas = exports.getSelectedOutlineKeyboardNudgeDelta = exports.getSelectedOutlineDragValues = exports.getSelectedOutlineDragChanges = exports.getSelectedOutlineActiveSchema = exports.compensateTranslateForTransformOrigin = exports.applySelectedOutlineTransformOriginAxisLock = exports.applySelectedOutlineDragAxisLock = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const player_1 = require("@remotion/player");
39
39
  const react_1 = __importStar(require("react"));
@@ -73,11 +73,11 @@ Object.defineProperty(exports, "getSelectedOutlineScaleDragValues", { enumerable
73
73
  Object.defineProperty(exports, "getSelectedOutlineScaleEdgeInfo", { enumerable: true, get: function () { return selected_outline_drag_2.getSelectedOutlineScaleEdgeInfo; } });
74
74
  Object.defineProperty(exports, "getSelectedOutlineTransformOriginLockedAxis", { enumerable: true, get: function () { return selected_outline_drag_2.getSelectedOutlineTransformOriginLockedAxis; } });
75
75
  Object.defineProperty(exports, "isSelectedOutlineDragPastThreshold", { enumerable: true, get: function () { return selected_outline_drag_2.isSelectedOutlineDragPastThreshold; } });
76
- Object.defineProperty(exports, "selectedOutlineUvSnapThresholdPx", { enumerable: true, get: function () { return selected_outline_drag_2.selectedOutlineUvSnapThresholdPx; } });
77
76
  Object.defineProperty(exports, "selectedOutlineTransformOriginSnapThresholdPx", { enumerable: true, get: function () { return selected_outline_drag_2.selectedOutlineTransformOriginSnapThresholdPx; } });
77
+ Object.defineProperty(exports, "selectedOutlineUvSnapThresholdPx", { enumerable: true, get: function () { return selected_outline_drag_2.selectedOutlineUvSnapThresholdPx; } });
78
78
  Object.defineProperty(exports, "snapSelectedOutlineRotationDeltaDegrees", { enumerable: true, get: function () { return selected_outline_drag_2.snapSelectedOutlineRotationDeltaDegrees; } });
79
- Object.defineProperty(exports, "snapSelectedOutlineUv", { enumerable: true, get: function () { return selected_outline_drag_2.snapSelectedOutlineUv; } });
80
79
  Object.defineProperty(exports, "snapSelectedOutlineTransformOriginUv", { enumerable: true, get: function () { return selected_outline_drag_2.snapSelectedOutlineTransformOriginUv; } });
80
+ Object.defineProperty(exports, "snapSelectedOutlineUv", { enumerable: true, get: function () { return selected_outline_drag_2.snapSelectedOutlineUv; } });
81
81
  const selected_outline_measurement_2 = require("./selected-outline-measurement");
82
82
  Object.defineProperty(exports, "getOutlineSelectionInteraction", { enumerable: true, get: function () { return selected_outline_measurement_2.getOutlineSelectionInteraction; } });
83
83
  Object.defineProperty(exports, "getSelectedEffectFieldsBySequenceKey", { enumerable: true, get: function () { return selected_outline_measurement_2.getSelectedEffectFieldsBySequenceKey; } });
@@ -105,7 +105,7 @@ const orderOutlinesForRendering = ({ outlines, targetsByKey, }) => {
105
105
  });
106
106
  };
107
107
  exports.orderOutlinesForRendering = orderOutlinesForRendering;
108
- const SelectedOutlineOverlay = ({ scale }) => {
108
+ const SelectedOutlineOverlay = ({ scale, translationX, translationY }) => {
109
109
  const { selectedItems, selectItem } = (0, TimelineSelection_1.useTimelineSelection)();
110
110
  const { sequences } = (0, react_1.useContext)(remotion_1.Internals.SequenceManager);
111
111
  const { propStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
@@ -176,6 +176,8 @@ const SelectedOutlineOverlay = ({ scale }) => {
176
176
  const rotationPropStatus = nodePropStatuses === null || nodePropStatuses === void 0 ? void 0 : nodePropStatuses[selected_outline_types_1.rotateFieldKey];
177
177
  const transformOriginFieldSchema = activeSchema === null || activeSchema === void 0 ? void 0 : activeSchema[selected_outline_types_1.transformOriginFieldKey];
178
178
  const transformOriginPropStatus = nodePropStatuses === null || nodePropStatuses === void 0 ? void 0 : nodePropStatuses[selected_outline_types_1.transformOriginFieldKey];
179
+ const textContentFieldSchema = activeSchema === null || activeSchema === void 0 ? void 0 : activeSchema.children;
180
+ const textContentPropStatus = nodePropStatuses === null || nodePropStatuses === void 0 ? void 0 : nodePropStatuses.children;
179
181
  const transformOriginValueForRotation = (transformOriginFieldSchema === null || transformOriginFieldSchema === void 0 ? void 0 : transformOriginFieldSchema.type) === 'transform-origin' &&
180
182
  ((transformOriginPropStatus === null || transformOriginPropStatus === void 0 ? void 0 : transformOriginPropStatus.status) === 'static' ||
181
183
  (transformOriginPropStatus === null || transformOriginPropStatus === void 0 ? void 0 : transformOriginPropStatus.status) === 'keyframed')
@@ -228,6 +230,10 @@ const SelectedOutlineOverlay = ({ scale }) => {
228
230
  canTransformOriginTranslateStatus;
229
231
  const canDropEffect = previewServerState.type === 'connected' &&
230
232
  (controls === null || controls === void 0 ? void 0 : controls.supportsEffects) === true;
233
+ const canTextEdit = previewServerState.type === 'connected' &&
234
+ controls !== null &&
235
+ (textContentFieldSchema === null || textContentFieldSchema === void 0 ? void 0 : textContentFieldSchema.type) === 'text-content' &&
236
+ textContentPropStatus !== undefined;
231
237
  return {
232
238
  key,
233
239
  containsSelection,
@@ -342,6 +348,12 @@ const SelectedOutlineOverlay = ({ scale }) => {
342
348
  })) !== null && _f !== void 0 ? _f : fieldSchema.default),
343
349
  }
344
350
  : null,
351
+ textEdit: canTextEdit
352
+ ? {
353
+ nodePath,
354
+ propStatus: textContentPropStatus,
355
+ }
356
+ : null,
345
357
  uvHandles: containsSelection
346
358
  ? (0, selected_outline_uv_1.getSelectedUvHandles)({
347
359
  propStatuses,
@@ -613,28 +625,49 @@ const SelectedOutlineOverlay = ({ scale }) => {
613
625
  }
614
626
  };
615
627
  }, [keybindings, onArrowKeyDown, onArrowKeyUp, saveKeyboardNudgeSession]);
616
- (0, react_1.useEffect)(() => {
617
- if (outlineTargets.length === 0) {
628
+ const updateOutlines = (0, react_1.useCallback)(() => {
629
+ if (overlayRef.current === null || outlineTargets.length === 0) {
618
630
  setOutlines((prevOutlines) => prevOutlines.length === 0 ? prevOutlines : []);
619
631
  return;
620
632
  }
633
+ const nextOutlines = (0, selected_outline_measurement_1.measureOutlines)(overlayRef.current, outlineTargets);
634
+ setOutlines((prevOutlines) => (0, selected_outline_measurement_1.outlinesAreEqual)(prevOutlines, nextOutlines)
635
+ ? prevOutlines
636
+ : nextOutlines);
637
+ }, [outlineTargets]);
638
+ (0, react_1.useLayoutEffect)(() => {
639
+ updateOutlines();
640
+ }, [outlineTargets, scale, translationX, translationY, updateOutlines]);
641
+ (0, react_1.useLayoutEffect)(() => {
642
+ if (outlineTargets.length === 0 || typeof ResizeObserver === 'undefined') {
643
+ return;
644
+ }
621
645
  let animationFrame = null;
622
- const updateOutlines = () => {
623
- if (overlayRef.current) {
624
- const nextOutlines = (0, selected_outline_measurement_1.measureOutlines)(overlayRef.current, outlineTargets);
625
- setOutlines((prevOutlines) => (0, selected_outline_measurement_1.outlinesAreEqual)(prevOutlines, nextOutlines)
626
- ? prevOutlines
627
- : nextOutlines);
646
+ const scheduleUpdate = () => {
647
+ if (animationFrame !== null) {
648
+ return;
628
649
  }
629
- animationFrame = requestAnimationFrame(updateOutlines);
650
+ animationFrame = requestAnimationFrame(() => {
651
+ animationFrame = null;
652
+ updateOutlines();
653
+ });
630
654
  };
631
- updateOutlines();
655
+ const resizeObserver = new ResizeObserver(scheduleUpdate);
656
+ if (overlayRef.current !== null) {
657
+ resizeObserver.observe(overlayRef.current);
658
+ }
659
+ for (const target of outlineTargets) {
660
+ if (target.ref.current !== null) {
661
+ resizeObserver.observe(target.ref.current);
662
+ }
663
+ }
632
664
  return () => {
633
665
  if (animationFrame !== null) {
634
666
  cancelAnimationFrame(animationFrame);
635
667
  }
668
+ resizeObserver.disconnect();
636
669
  };
637
- }, [outlineTargets]);
670
+ }, [outlineTargets, updateOutlines]);
638
671
  if (outlineTargets.length === 0) {
639
672
  return null;
640
673
  }
@@ -80,8 +80,8 @@ const inlineContainer = {
80
80
  const segmentedControlWrapper = {
81
81
  display: 'flex',
82
82
  justifyContent: 'flex-start',
83
+ marginTop: 8,
83
84
  padding: `0 ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px`,
84
- marginBottom: 10,
85
85
  };
86
86
  const presetButtonsWrapper = {
87
87
  display: 'flex',
@@ -91,6 +91,10 @@ const presetButtonsWrapper = {
91
91
  marginBottom: 8,
92
92
  padding: `0 ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px`,
93
93
  };
94
+ const inspectorPresetButtonsWrapper = {
95
+ ...presetButtonsWrapper,
96
+ padding: `8px ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px 0`,
97
+ };
94
98
  const presetButtonBase = {
95
99
  alignItems: 'center',
96
100
  backgroundColor: colors_1.INPUT_BACKGROUND,
@@ -721,10 +725,11 @@ const EasingEditor = ({ state, renderHeader }) => {
721
725
  gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
722
726
  padding: '0 12px 12px',
723
727
  }), []);
724
- return (jsx_runtime_1.jsxs("div", { style: inlineContainer, children: [renderHeader ? (renderHeader(modeItems)) : (jsx_runtime_1.jsx("div", { style: segmentedControlWrapper, children: jsx_runtime_1.jsx(SegmentedControl_1.SegmentedControl, { items: modeItems, needsWrapping: false, size: "compact" }) })), jsx_runtime_1.jsx("div", { style: presetButtonsWrapper, children: EDITOR_EASING_PRESETS.map((preset) => (jsx_runtime_1.jsx(EasingPresetButton, { currentEasing: currentEasing, disabled: disabled, onClick: applyPreset, preset: preset }, preset.id))) }), mode === 'bezier' ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
728
+ const modeSwitcher = (jsx_runtime_1.jsx("div", { style: segmentedControlWrapper, children: jsx_runtime_1.jsx(SegmentedControl_1.SegmentedControl, { items: modeItems, needsWrapping: false }) }));
729
+ return (jsx_runtime_1.jsxs("div", { style: inlineContainer, children: [renderHeader ? renderHeader(modeItems) : null, jsx_runtime_1.jsx("div", { style: renderHeader ? inspectorPresetButtonsWrapper : presetButtonsWrapper, children: EDITOR_EASING_PRESETS.map((preset) => (jsx_runtime_1.jsx(EasingPresetButton, { currentEasing: currentEasing, disabled: disabled, onClick: applyPreset, preset: preset }, preset.id))) }), mode === 'bezier' ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
725
730
  jsx_runtime_1.jsxs("svg", { ref: svgRef, width: SVG_WIDTH, height: SVG_HEIGHT, viewBox: `0 0 ${SVG_WIDTH} ${SVG_HEIGHT}`, style: svgStyle, "aria-label": "Bezier curve editor", children: [
726
731
  jsx_runtime_1.jsx(EasingGraphScaffold, { labels: graphLabels }), jsx_runtime_1.jsx("line", { x1: startPoint.x, y1: startPoint.y, x2: firstHandle.x, y2: firstHandle.y, stroke: "rgba(255, 255, 255, 0.35)", strokeWidth: 1 }), jsx_runtime_1.jsx("line", { x1: endPoint.x, y1: endPoint.y, x2: secondHandle.x, y2: secondHandle.y, stroke: "rgba(255, 255, 255, 0.35)", strokeWidth: 1 }), jsx_runtime_1.jsx("path", { d: bezierPath, fill: "none", stroke: colors_1.BLUE, strokeWidth: 3 }), jsx_runtime_1.jsx("circle", { cx: startPoint.x, cy: startPoint.y, r: 4, fill: "white" }), jsx_runtime_1.jsx("circle", { cx: endPoint.x, cy: endPoint.y, r: 4, fill: "white" }), jsx_runtime_1.jsx("circle", { cx: firstHandle.x, cy: firstHandle.y, r: 6, fill: "white", stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: disabled ? 'none' : 'all', cursor: activeHandle === 0 ? 'grabbing' : 'default', onPointerDown: (event) => onHandlePointerDown(0, event) }), jsx_runtime_1.jsx("circle", { cx: secondHandle.x, cy: secondHandle.y, r: 6, fill: "white", stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: disabled ? 'none' : 'all', cursor: activeHandle === 1 ? 'grabbing' : 'default', onPointerDown: (event) => onHandlePointerDown(1, event) })
727
- ] }), jsx_runtime_1.jsxs("div", { style: coordinatesGrid, children: [
732
+ ] }), modeSwitcher, jsx_runtime_1.jsxs("div", { style: coordinatesGrid, children: [
728
733
  jsx_runtime_1.jsxs("div", { style: coordinateRow, children: [
729
734
  jsx_runtime_1.jsx("div", { style: coordinateLabel, children: "X1" }), jsx_runtime_1.jsx("div", { style: coordinateInputWrapper, children: jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: bezier[0], status: "ok", onValueChange: (value) => setCoordinate(0, 'x', value, false), onValueChangeEnd: (value) => setCoordinate(0, 'x', value, true), onTextChange: () => undefined, min: 0, max: 1, step: 0.01, formatter: formatNumber, rightAlign: false, style: numberInputStyle, snapToStep: false, disabled: disabled }) })
730
735
  ] }), jsx_runtime_1.jsxs("div", { style: coordinateRow, children: [
@@ -738,7 +743,7 @@ const EasingEditor = ({ state, renderHeader }) => {
738
743
  ] })) : (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
739
744
  jsx_runtime_1.jsxs("svg", { width: SVG_WIDTH, height: SVG_HEIGHT, viewBox: `0 0 ${SVG_WIDTH} ${SVG_HEIGHT}`, style: svgStyle, "aria-label": "Spring easing curve", children: [
740
745
  jsx_runtime_1.jsx(EasingGraphScaffold, { labels: graphLabels }), jsx_runtime_1.jsx("path", { d: springPath, fill: "none", stroke: colors_1.BLUE, strokeWidth: 3 }), jsx_runtime_1.jsx("circle", { cx: xToSvg(0), cy: yToSvg(0), r: 4, fill: "white" }), jsx_runtime_1.jsx("circle", { cx: xToSvg(1), cy: yToSvg(1), r: 4, fill: "white" })
741
- ] }), jsx_runtime_1.jsxs("div", { style: coordinatesGrid, children: [
746
+ ] }), modeSwitcher, jsx_runtime_1.jsxs("div", { style: coordinatesGrid, children: [
742
747
  jsx_runtime_1.jsxs("div", { style: coordinateRow, children: [
743
748
  jsx_runtime_1.jsx("div", { style: coordinateLabel, children: "Damping" }), jsx_runtime_1.jsx("div", { style: coordinateInputWrapper, children: jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: spring.damping, status: "ok", onValueChange: (value) => setSpringNumber('damping', value, false), onValueChangeEnd: (value) => setSpringNumber('damping', value, true), onTextChange: () => undefined, min: SPRING_LIMITS.damping.min, max: SPRING_LIMITS.damping.max, step: SPRING_LIMITS.damping.step, formatter: springFormatters.damping, rightAlign: false, style: numberInputStyle, snapToStep: false, dragDecimalPlaces: SPRING_DECIMAL_PLACES.damping, disabled: disabled }) })
744
749
  ] }), jsx_runtime_1.jsxs("div", { style: coordinateRow, children: [
@@ -11,6 +11,7 @@ const ConfirmationDialog_1 = require("../ConfirmationDialog");
11
11
  const delete_selected_timeline_item_1 = require("./delete-selected-timeline-item");
12
12
  const duplicate_selected_timeline_item_1 = require("./duplicate-selected-timeline-item");
13
13
  const reset_selected_timeline_props_1 = require("./reset-selected-timeline-props");
14
+ const split_selected_timeline_item_1 = require("./split-selected-timeline-item");
14
15
  const TimelineSelection_1 = require("./TimelineSelection");
15
16
  const update_selected_easing_1 = require("./update-selected-easing");
16
17
  const TimelineDeleteKeybindings = () => {
@@ -24,6 +25,9 @@ const TimelineDeleteKeybindings = () => {
24
25
  const { canSelect } = (0, TimelineSelection_1.useTimelineSelection)();
25
26
  const currentSelection = (0, TimelineSelection_1.useCurrentTimelineSelectionStateAsRef)();
26
27
  const confirm = (0, ConfirmationDialog_1.useConfirmationDialog)();
28
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
29
+ const timelinePositionRef = (0, react_1.useRef)(timelinePosition);
30
+ timelinePositionRef.current = timelinePosition;
27
31
  (0, react_1.useEffect)(() => {
28
32
  if (!canSelect || previewServerState.type !== 'connected') {
29
33
  return;
@@ -58,7 +62,13 @@ const TimelineDeleteKeybindings = () => {
58
62
  deletePromise
59
63
  .then((deleted) => {
60
64
  if (deleted) {
61
- const nextSelection = (0, delete_selected_timeline_item_1.getTimelineSelectionAfterDeletingItems)(selectedItems);
65
+ const nextSelection = (0, delete_selected_timeline_item_1.getTimelineSelectionAfterDeletingItems)({
66
+ selections: selectedItems,
67
+ sequences,
68
+ overrideIdsToNodePaths: overrideIdToNodePathMappings,
69
+ propStatuses,
70
+ timelinePosition: timelinePositionRef.current,
71
+ });
62
72
  if (nextSelection.length === 0) {
63
73
  clearSelection();
64
74
  }
@@ -119,7 +129,10 @@ const TimelineDeleteKeybindings = () => {
119
129
  const duplicate = keybindings.registerKeybinding({
120
130
  event: 'keydown',
121
131
  key: 'd',
122
- callback: () => {
132
+ callback: (event) => {
133
+ if (!(0, split_selected_timeline_item_1.shouldHandleTimelineDuplicateShortcut)(event)) {
134
+ return;
135
+ }
123
136
  const { selectedItems } = currentSelection.current;
124
137
  if (selectedItems.length === 0) {
125
138
  return;
@@ -138,10 +151,39 @@ const TimelineDeleteKeybindings = () => {
138
151
  triggerIfInputFieldFocused: false,
139
152
  keepRegisteredWhenNotHighestContext: false,
140
153
  });
154
+ const split = keybindings.registerKeybinding({
155
+ event: 'keydown',
156
+ key: 'd',
157
+ callback: (event) => {
158
+ if (!(0, split_selected_timeline_item_1.shouldHandleTimelineSplitShortcut)(event)) {
159
+ return;
160
+ }
161
+ const { selectedItems } = currentSelection.current;
162
+ if (selectedItems.length === 0) {
163
+ return;
164
+ }
165
+ const splitPromise = (0, split_selected_timeline_item_1.splitSelectedTimelineItems)({
166
+ selections: selectedItems,
167
+ sequences: sequencesRef.current,
168
+ overrideIdsToNodePaths: overrideIdToNodePathMappings,
169
+ propStatuses: propStatusesRef.current,
170
+ splitFrame: timelinePositionRef.current,
171
+ });
172
+ if (splitPromise === null) {
173
+ return;
174
+ }
175
+ splitPromise.catch(() => undefined);
176
+ },
177
+ commandCtrlKey: true,
178
+ preventDefault: true,
179
+ triggerIfInputFieldFocused: false,
180
+ keepRegisteredWhenNotHighestContext: false,
181
+ });
141
182
  return () => {
142
183
  backspace.unregister();
143
184
  deleteKey.unregister();
144
185
  duplicate.unregister();
186
+ split.unregister();
145
187
  };
146
188
  }, [
147
189
  canSelect,
@@ -154,6 +196,7 @@ const TimelineDeleteKeybindings = () => {
154
196
  sequencesRef,
155
197
  setGuidesList,
156
198
  setPropStatuses,
199
+ timelinePositionRef,
157
200
  ]);
158
201
  return null;
159
202
  };
@@ -10,6 +10,7 @@ const modals_1 = require("../../state/modals");
10
10
  const call_api_1 = require("../call-api");
11
11
  const ContextMenu_1 = require("../ContextMenu");
12
12
  const call_add_keyframe_1 = require("./call-add-keyframe");
13
+ const get_animation_item_selection_for_frame_1 = require("./get-animation-item-selection-for-frame");
13
14
  const get_timeline_keyframes_1 = require("./get-timeline-keyframes");
14
15
  const save_effect_prop_1 = require("./save-effect-prop");
15
16
  const save_prop_queue_1 = require("./save-prop-queue");
@@ -22,6 +23,7 @@ const TimelineLayerEye_1 = require("./TimelineLayerEye");
22
23
  const TimelineRowChrome_1 = require("./TimelineRowChrome");
23
24
  const TimelineSchemaField_1 = require("./TimelineSchemaField");
24
25
  const TimelineSelection_1 = require("./TimelineSelection");
26
+ const update_selected_easing_1 = require("./update-selected-easing");
25
27
  const fieldRowBase = {};
26
28
  const isKeyframedStatus = (status) => {
27
29
  return status.status === 'keyframed';
@@ -219,6 +221,9 @@ const TimelineEffectPropItem = ({ field, validatedLocation, rowDepth, nodePath,
219
221
  const { propStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
220
222
  const { getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
221
223
  const selection = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
224
+ const { selectItems } = (0, TimelineSelection_1.useTimelineSelection)();
225
+ const setFrame = remotion_1.Internals.useTimelineSetFrame();
226
+ const videoConfig = (0, remotion_1.useVideoConfig)();
222
227
  const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
223
228
  const sourceFrame = timelinePosition - keyframeDisplayOffset;
224
229
  const style = (0, react_1.useMemo)(() => {
@@ -359,7 +364,83 @@ const TimelineEffectPropItem = ({ field, validatedLocation, rowDepth, nodePath,
359
364
  previewServerState,
360
365
  propStatus,
361
366
  ]);
362
- const row = (jsx_runtime_1.jsxs(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {}), keyframeControls: keyframeControls, arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {}), style: style, selected: selection.selected, selectable: selection.selectable, selectionItem: selection.selectionItem, onSelect: selection.onSelect, showSelectedBackground: true, containsSelection: false, outerHeight: null, children: [
367
+ const seekToDisplayFrame = (0, react_1.useCallback)((frame) => {
368
+ setFrame((current) => {
369
+ const next = { ...current, [videoConfig.id]: frame };
370
+ remotion_1.Internals.persistCurrentFrame(next);
371
+ return next;
372
+ });
373
+ }, [setFrame, videoConfig.id]);
374
+ const onPropertyDoubleClick = (0, react_1.useCallback)((event) => {
375
+ if (propStatus === null || propStatus.status === 'computed') {
376
+ return;
377
+ }
378
+ const keyframeSelection = {
379
+ type: 'keyframe',
380
+ nodePathInfo,
381
+ frame: sourceFrame + keyframeDisplayOffset,
382
+ };
383
+ if (propStatus.status === 'static') {
384
+ if (!keyframable || previewServerState.type !== 'connected') {
385
+ return;
386
+ }
387
+ const value = remotion_1.Internals.getEffectiveVisualModeValue({
388
+ propStatus,
389
+ dragOverrideValue,
390
+ frame: sourceFrame,
391
+ defaultValue: field.fieldSchema.default,
392
+ shouldResortToDefaultValueIfUndefined: true,
393
+ });
394
+ event.stopPropagation();
395
+ (0, call_add_keyframe_1.callAddEffectKeyframe)({
396
+ fileName: validatedLocation.source,
397
+ nodePath,
398
+ effectIndex: field.effectIndex,
399
+ fieldKey: field.key,
400
+ sourceFrame,
401
+ value,
402
+ schema: field.effectSchema,
403
+ setPropStatuses,
404
+ clientId: previewServerState.clientId,
405
+ }).catch(() => undefined);
406
+ selectItems([keyframeSelection], { reveal: true });
407
+ seekToDisplayFrame(keyframeSelection.frame);
408
+ return;
409
+ }
410
+ const targetSelection = (0, get_animation_item_selection_for_frame_1.getAnimationItemSelectionForSourceFrame)({
411
+ includeEasings: (0, update_selected_easing_1.canEditEasingForInterpolationFunction)(propStatus.interpolationFunction),
412
+ keyframeDisplayOffset,
413
+ keyframes: propStatus.keyframes,
414
+ nodePathInfo,
415
+ sourceFrame,
416
+ });
417
+ if (targetSelection === null) {
418
+ return;
419
+ }
420
+ event.stopPropagation();
421
+ selectItems([targetSelection], { reveal: true });
422
+ if (targetSelection.type === 'keyframe') {
423
+ seekToDisplayFrame(targetSelection.frame);
424
+ }
425
+ }, [
426
+ dragOverrideValue,
427
+ field.effectIndex,
428
+ field.effectSchema,
429
+ field.fieldSchema.default,
430
+ field.key,
431
+ keyframeDisplayOffset,
432
+ keyframable,
433
+ nodePath,
434
+ nodePathInfo,
435
+ previewServerState,
436
+ propStatus,
437
+ seekToDisplayFrame,
438
+ selectItems,
439
+ setPropStatuses,
440
+ sourceFrame,
441
+ validatedLocation.source,
442
+ ]);
443
+ const row = (jsx_runtime_1.jsxs(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {}), keyframeControls: keyframeControls, arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {}), style: style, selected: selection.selected, selectable: selection.selectable, selectionItem: selection.selectionItem, onSelect: selection.onSelect, onDoubleClick: onPropertyDoubleClick, showSelectedBackground: true, containsSelection: false, outerHeight: null, children: [
363
444
  jsx_runtime_1.jsx(TimelineFieldLabel_1.TimelineFieldLabel, { rowDepth: rowDepth, selected: selection.selected, label: (_c = field.description) !== null && _c !== void 0 ? _c : field.key }), jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(exports.TimelineEffectPropValue, { field: field, nodePath: nodePath, validatedLocation: validatedLocation, sourceFrame: sourceFrame }) })
364
445
  ] }));
365
446
  return (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: selection.selectable ? selection.onSelect : null, children: row }));
@@ -56,6 +56,7 @@ const TimelineExpandedSection = ({ sequence, validatedLocation, nodePathInfo, ne
56
56
  const { filteredTree, getIsExpanded, toggleTrack } = (0, use_timeline_expanded_tree_1.useTimelineExpandedTree)({
57
57
  sequence,
58
58
  nodePathInfo,
59
+ includeTextContent: false,
59
60
  });
60
61
  const flat = (0, react_1.useMemo)(() => (0, timeline_layout_1.flattenVisibleTreeNodes)({ nodes: filteredTree, getIsExpanded }), [filteredTree, getIsExpanded]);
61
62
  const expandedHeight = (0, react_1.useMemo)(() => {
@@ -6,6 +6,7 @@ const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
7
  const colors_1 = require("../../helpers/colors");
8
8
  const get_left_of_timeline_slider_1 = require("../../helpers/get-left-of-timeline-slider");
9
+ const TimelineSelection_1 = require("./TimelineSelection");
9
10
  const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
10
11
  const line = {
11
12
  height: '100%',
@@ -30,7 +31,7 @@ const InnerTimelineInOutPointerHandle = ({ atFrame, dragging, onPointerDown, tim
30
31
  top: 0,
31
32
  };
32
33
  }, [atFrame, dragging, timelineWidth, videoConfig.durationInFrames]);
33
- return (jsx_runtime_1.jsx("div", { ref: type === 'in' ? exports.inPointerHandle : exports.outPointerHandle, style: style, onPointerDown: onPointerDown }));
34
+ return (jsx_runtime_1.jsx("div", { ref: type === 'in' ? exports.inPointerHandle : exports.outPointerHandle, style: style, onPointerDown: onPointerDown, [TimelineSelection_1.TIMELINE_SCRUBBER_ATTR]: true }));
34
35
  };
35
36
  const TimelineInOutPointerHandle = ({ dragging, onPointerDown, type, atFrame, }) => {
36
37
  const timelineWidth = (0, react_1.useContext)(TimelineWidthProvider_1.TimelineWidthContext);
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { CanUpdateSequencePropStatus, DragOverrideValue, SequencePropsSubscriptionKey, InteractivitySchema } from 'remotion';
2
+ import type { CanUpdateSequencePropStatus, DragOverrideValue, InteractivitySchema, SequencePropsSubscriptionKey } from 'remotion';
3
3
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
4
4
  import { type TimelineSelection } from './TimelineSelection';
5
5
  export declare const getSelectedKeyframeControlNodePathInfos: ({ clickedNodePathInfo, selectedItems, }: {
@@ -11,11 +11,13 @@ const timeline_layout_1 = require("../../helpers/timeline-layout");
11
11
  const timeline_node_path_key_1 = require("../../helpers/timeline-node-path-key");
12
12
  const call_add_keyframe_1 = require("./call-add-keyframe");
13
13
  const call_delete_keyframe_1 = require("./call-delete-keyframe");
14
+ const get_easing_selection_after_keyframe_delete_1 = require("./get-easing-selection-after-keyframe-delete");
14
15
  const get_keyframe_navigation_1 = require("./get-keyframe-navigation");
15
16
  const get_timeline_keyframes_1 = require("./get-timeline-keyframes");
16
17
  const TimelineKeyframeDiamondIcon_1 = require("./TimelineKeyframeDiamondIcon");
17
18
  const TimelineKeyframeTracksContext_1 = require("./TimelineKeyframeTracksContext");
18
19
  const TimelineSelection_1 = require("./TimelineSelection");
20
+ const update_selected_easing_1 = require("./update-selected-easing");
19
21
  const controlsContainerStyle = {
20
22
  alignItems: 'center',
21
23
  display: 'flex',
@@ -111,6 +113,7 @@ const resolveKeyframeControlTarget = ({ nodePathInfo, tracks, propStatuses, getD
111
113
  getDragOverrides,
112
114
  getEffectDragOverrides,
113
115
  propStatuses,
116
+ includeTextContent: false,
114
117
  });
115
118
  const fieldNode = findFieldNode(tree, (0, timeline_node_path_key_1.timelineNodePathInfoToKey)(nodePathInfo));
116
119
  if (fieldNode === null || fieldNode.field === null) {
@@ -262,7 +265,7 @@ const shouldShowTimelineKeyframeNavigation = ({ propStatus, selected, }) => {
262
265
  return isKeyframedStatus(propStatus);
263
266
  };
264
267
  exports.shouldShowTimelineKeyframeNavigation = shouldShowTimelineKeyframeNavigation;
265
- const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, keyframeDisplayOffset, defaultValue, dragOverrideValue, schema, effectIndex, nodePathInfo, }) => {
268
+ const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, keyframeDisplayOffset, defaultValue, dragOverrideValue, schema, effectIndex, nodePathInfo, mode = 'timeline', }) => {
266
269
  const videoConfig = (0, remotion_1.useVideoConfig)();
267
270
  const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
268
271
  const setFrame = remotion_1.Internals.useTimelineSetFrame();
@@ -270,7 +273,7 @@ const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, ke
270
273
  const { propStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
271
274
  const { getDragOverrides, getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
272
275
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
273
- const { selectedItems } = (0, TimelineSelection_1.useTimelineSelection)();
276
+ const { selectedItems, selectItems } = (0, TimelineSelection_1.useTimelineSelection)();
274
277
  const tracks = (0, TimelineKeyframeTracksContext_1.useTimelineKeyframeTracks)();
275
278
  const clientId = previewServerState.type === 'connected'
276
279
  ? previewServerState.clientId
@@ -385,37 +388,65 @@ const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, ke
385
388
  return;
386
389
  }
387
390
  if (hasKeyframeAtCurrentFrame) {
388
- const deleteChanges = keyframeToggleTargets.flatMap((target) => {
391
+ const deleteTargets = keyframeToggleTargets.flatMap((target) => {
389
392
  const change = getDeleteChange(target);
390
- return change === null ? [] : [change];
393
+ return change === null ? [] : [{ target, change }];
391
394
  });
395
+ const singleDeleteTarget = deleteTargets[0];
396
+ const easingSelection = deleteTargets.length === 1 &&
397
+ singleDeleteTarget &&
398
+ isKeyframedStatus(singleDeleteTarget.target.propStatus) &&
399
+ (0, update_selected_easing_1.canEditEasingForInterpolationFunction)(singleDeleteTarget.target.propStatus.interpolationFunction)
400
+ ? (0, get_easing_selection_after_keyframe_delete_1.getEasingSelectionAfterKeyframeDelete)({
401
+ deletedSourceFrames: [singleDeleteTarget.target.sourceFrame],
402
+ keyframeDisplayOffset: singleDeleteTarget.target.keyframeDisplayOffset,
403
+ nodePathInfo: singleDeleteTarget.target.nodePathInfo,
404
+ propStatus: singleDeleteTarget.target.propStatus,
405
+ timelinePosition,
406
+ })
407
+ : null;
408
+ const deleteChanges = deleteTargets.map(({ change }) => change);
392
409
  await (0, call_delete_keyframe_1.callDeleteKeyframes)({
393
410
  sequenceKeyframes: deleteChanges.filter((change) => !hasEffectIndex(change)),
394
411
  effectKeyframes: deleteChanges.filter((change) => hasEffectIndex(change)),
395
412
  setPropStatuses,
396
413
  clientId,
397
414
  });
415
+ if (mode === 'timeline' && easingSelection !== null) {
416
+ selectItems([easingSelection], { reveal: true });
417
+ }
398
418
  return;
399
419
  }
400
420
  const addChanges = keyframeToggleTargets.flatMap((target) => {
401
421
  const change = getAddChange(target);
402
- return change === null ? [] : [change];
422
+ return change === null ? [] : [{ target, change }];
403
423
  });
404
424
  if (addChanges.length === 0) {
405
425
  return;
406
426
  }
427
+ const addChangeValues = addChanges.map(({ change }) => change);
407
428
  await (0, call_add_keyframe_1.callAddKeyframes)({
408
- sequenceKeyframes: addChanges.filter((change) => !hasEffectIndex(change)),
409
- effectKeyframes: addChanges.filter((change) => hasEffectIndex(change)),
429
+ sequenceKeyframes: addChangeValues.filter((change) => !hasEffectIndex(change)),
430
+ effectKeyframes: addChangeValues.filter((change) => hasEffectIndex(change)),
410
431
  setPropStatuses,
411
432
  clientId,
412
433
  });
434
+ if (mode === 'timeline') {
435
+ selectItems(addChanges.map(({ target }) => ({
436
+ type: 'keyframe',
437
+ nodePathInfo: target.nodePathInfo,
438
+ frame: target.sourceFrame + target.keyframeDisplayOffset,
439
+ })), { reveal: true });
440
+ }
413
441
  }, [
414
442
  canToggleKeyframe,
415
443
  clientId,
416
444
  hasKeyframeAtCurrentFrame,
417
445
  keyframeToggleTargets,
446
+ mode,
447
+ selectItems,
418
448
  setPropStatuses,
449
+ timelinePosition,
419
450
  ]);
420
451
  const previousDisabled = previousDisplayFrame === null;
421
452
  const nextDisabled = nextDisplayFrame === null;
@@ -1,5 +1,9 @@
1
1
  import React from 'react';
2
2
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
3
+ export declare const getTimelineKeyframeEasingLineStyle: (selected: boolean) => React.CSSProperties;
4
+ export declare const TimelineKeyframeEasingLineVisual: React.FC<{
5
+ readonly selected: boolean;
6
+ }>;
3
7
  export declare const TimelineKeyframeEasingLine: React.NamedExoticComponent<{
4
8
  readonly fromFrame: number;
5
9
  readonly toFrame: number;
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.TimelineKeyframeEasingLine = void 0;
36
+ exports.TimelineKeyframeEasingLine = exports.TimelineKeyframeEasingLineVisual = exports.getTimelineKeyframeEasingLineStyle = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const studio_shared_1 = require("@remotion/studio-shared");
39
39
  const react_1 = __importStar(require("react"));
@@ -67,6 +67,16 @@ const easingLine = {
67
67
  top: '50%',
68
68
  transform: 'translateY(-50%)',
69
69
  };
70
+ const getTimelineKeyframeEasingLineStyle = (selected) => ({
71
+ ...easingLine,
72
+ outline: selected ? `1px solid ${colors_1.BLUE}` : undefined,
73
+ });
74
+ exports.getTimelineKeyframeEasingLineStyle = getTimelineKeyframeEasingLineStyle;
75
+ const TimelineKeyframeEasingLineVisual = ({ selected }) => {
76
+ const lineStyle = (0, react_1.useMemo)(() => (0, exports.getTimelineKeyframeEasingLineStyle)(selected), [selected]);
77
+ return jsx_runtime_1.jsx("div", { style: lineStyle });
78
+ };
79
+ exports.TimelineKeyframeEasingLineVisual = TimelineKeyframeEasingLineVisual;
70
80
  const TimelineKeyframeEasingLineUnmemoized = ({ fromFrame, toFrame, rowHeight, nodePathInfo, segmentIndex }) => {
71
81
  const buttonRef = (0, react_1.useRef)(null);
72
82
  const videoConfig = (0, remotion_1.useVideoConfig)();
@@ -176,10 +186,6 @@ const TimelineKeyframeEasingLineUnmemoized = ({ fromFrame, toFrame, rowHeight, n
176
186
  toFrame,
177
187
  videoConfig.durationInFrames,
178
188
  ]);
179
- const lineStyle = (0, react_1.useMemo)(() => ({
180
- ...easingLine,
181
- outline: selected ? `1px solid ${colors_1.BLUE}` : undefined,
182
- }), [selected]);
183
189
  const onPointerDown = (0, use_timeline_keyframe_drag_1.useTimelineEasingKeyframeDrag)({
184
190
  onSelect,
185
191
  selectable,
@@ -190,7 +196,7 @@ const TimelineKeyframeEasingLineUnmemoized = ({ fromFrame, toFrame, rowHeight, n
190
196
  return null;
191
197
  }
192
198
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
193
- jsx_runtime_1.jsx("button", { ref: buttonRef, [TimelineSelection_1.TIMELINE_MARQUEE_ITEM_ATTR]: true, type: "button", style: style, title: `Easing from frame ${fromFrame} to ${toFrame}`, "aria-label": `Select easing from frame ${fromFrame} to ${toFrame}`, onPointerDown: selectable ? onPointerDown : undefined, children: jsx_runtime_1.jsx("div", { style: lineStyle }) }), jsx_runtime_1.jsx(ContextMenu_1.ContextMenuForTarget, { triggerRef: buttonRef, values: contextMenuValues, onOpen: onOpenContextMenu })
199
+ jsx_runtime_1.jsx("button", { ref: buttonRef, [TimelineSelection_1.TIMELINE_MARQUEE_ITEM_ATTR]: true, type: "button", style: style, title: `Easing from frame ${fromFrame} to ${toFrame}`, "aria-label": `Select easing from frame ${fromFrame} to ${toFrame}`, onPointerDown: selectable ? onPointerDown : undefined, children: jsx_runtime_1.jsx(exports.TimelineKeyframeEasingLineVisual, { selected: selected }) }), jsx_runtime_1.jsx(ContextMenu_1.ContextMenuForTarget, { triggerRef: buttonRef, values: contextMenuValues, onOpen: onOpenContextMenu })
194
200
  ] }));
195
201
  };
196
202
  exports.TimelineKeyframeEasingLine = react_1.default.memo(TimelineKeyframeEasingLineUnmemoized);
@@ -8,6 +8,7 @@ const TimelineEnumField_1 = require("./TimelineEnumField");
8
8
  const TimelineNumberField_1 = require("./TimelineNumberField");
9
9
  const TimelineRotationField_1 = require("./TimelineRotationField");
10
10
  const TimelineScaleField_1 = require("./TimelineScaleField");
11
+ const TimelineTextContentField_1 = require("./TimelineTextContentField");
11
12
  const TimelineTransformOriginField_1 = require("./TimelineTransformOriginField");
12
13
  const TimelineTranslateField_1 = require("./TimelineTranslateField");
13
14
  const TimelineUvCoordinateField_1 = require("./TimelineUvCoordinateField");
@@ -52,6 +53,9 @@ const TimelinePrimitiveFieldValue = ({ field, onSave, onDragValueChange, onDragE
52
53
  if (field.typeName === 'enum') {
53
54
  return (jsx_runtime_1.jsx("span", { style: inlineWrapper, children: jsx_runtime_1.jsx(TimelineEnumField_1.TimelineEnumField, { effectiveValue: effectiveValue, field: field, onDragEnd: onDragEnd, onDragValueChange: onDragValueChange, onSave: onSave, propStatus: propStatus }) }));
54
55
  }
56
+ if (field.typeName === 'text-content') {
57
+ return (jsx_runtime_1.jsx("span", { style: inlineWrapper, children: jsx_runtime_1.jsx(TimelineTextContentField_1.TimelineTextContentField, { effectiveValue: effectiveValue, field: field, nodePath: scaleLockNodePath, onDragEnd: onDragEnd, onDragValueChange: onDragValueChange, onSave: onSave, propStatus: propStatus }) }));
58
+ }
55
59
  throw new Error(`Unsupported field type: ${field.typeName}`);
56
60
  };
57
61
  exports.TimelinePrimitiveFieldValue = TimelinePrimitiveFieldValue;
@@ -404,6 +404,7 @@ const getSelectableTimelineItems = ({ getDragOverrides, getEffectDragOverrides,
404
404
  getDragOverrides,
405
405
  getEffectDragOverrides,
406
406
  propStatuses,
407
+ includeTextContent: false,
407
408
  });
408
409
  const filteredTree = (0, timeline_expanded_filter_1.filterTimelineExpandedTree)({
409
410
  nodes: tree,