@remotion/studio 4.0.506 → 4.0.508

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 (211) hide show
  1. package/dist/FastRefreshProvider.js +13 -9
  2. package/dist/api/copy-render-output-to-asset.d.ts +4 -0
  3. package/dist/api/copy-render-output-to-asset.js +11 -0
  4. package/dist/components/AssetSelector.js +19 -4
  5. package/dist/components/AssetSelectorItem.js +2 -2
  6. package/dist/components/CodingAgentIcon.d.ts +6 -0
  7. package/dist/components/CodingAgentIcon.js +12 -0
  8. package/dist/components/ConfigureDefaultEditorModal.d.ts +1 -3
  9. package/dist/components/ConfigureDefaultEditorModal.js +67 -77
  10. package/dist/components/ConfigureLicenseModal.d.ts +1 -4
  11. package/dist/components/ConfigureLicenseModal.js +89 -81
  12. package/dist/components/ContextMenu.d.ts +1 -0
  13. package/dist/components/ContextMenu.js +42 -13
  14. package/dist/components/EditorContent.js +4 -3
  15. package/dist/components/EditorContexts.js +6 -5
  16. package/dist/components/ExpandedTracksProvider.js +10 -53
  17. package/dist/components/InlineAction.d.ts +2 -1
  18. package/dist/components/InlineAction.js +3 -3
  19. package/dist/components/InspectorLocationCopy.js +8 -8
  20. package/dist/components/InspectorOpenInEditor.d.ts +2 -0
  21. package/dist/components/InspectorOpenInEditor.js +81 -50
  22. package/dist/components/InspectorPanel/AlignmentControls.js +2 -2
  23. package/dist/components/InspectorPanel/CompositionInspector.js +3 -1
  24. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +3 -0
  25. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +22 -4
  26. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +1 -1
  27. package/dist/components/InspectorPanel/styles.js +1 -1
  28. package/dist/components/InspectorSequenceSection.js +36 -4
  29. package/dist/components/Menu/MenuSectionHeader.d.ts +4 -0
  30. package/dist/components/Menu/MenuSectionHeader.js +20 -0
  31. package/dist/components/Menu/SubMenu.js +13 -2
  32. package/dist/components/Menu/menu-tree-context.d.ts +3 -0
  33. package/dist/components/Menu/menu-tree-context.js +13 -0
  34. package/dist/components/MenuBuildIndicator.js +1 -1
  35. package/dist/components/NewComposition/ComboBox.d.ts +6 -1
  36. package/dist/components/NewComposition/MenuContent.js +27 -19
  37. package/dist/components/NewComposition/menu-typeahead.js +2 -2
  38. package/dist/components/PlayPause.d.ts +1 -1
  39. package/dist/components/PlayPause.js +61 -12
  40. package/dist/components/Preview.js +29 -4
  41. package/dist/components/RenderButton.js +16 -12
  42. package/dist/components/RenderModal/GuiRenderStatus.js +23 -6
  43. package/dist/components/RenderModal/InfoBubble.d.ts +1 -0
  44. package/dist/components/RenderModal/InfoBubble.js +6 -4
  45. package/dist/components/RenderModal/InfoTooltip.d.ts +1 -0
  46. package/dist/components/RenderModal/InfoTooltip.js +12 -12
  47. package/dist/components/RenderModal/SchemaEditor/SchemaLabel.d.ts +5 -0
  48. package/dist/components/RenderModal/SchemaEditor/SchemaLabel.js +16 -3
  49. package/dist/components/RenderModal/SchemaEditor/ZodArrayEditor.js +1 -1
  50. package/dist/components/RenderModal/SchemaEditor/ZodBooleanEditor.d.ts +2 -0
  51. package/dist/components/RenderModal/SchemaEditor/ZodBooleanEditor.js +3 -2
  52. package/dist/components/RenderModal/SchemaEditor/ZodColorEditor.js +1 -1
  53. package/dist/components/RenderModal/SchemaEditor/ZodDateEditor.js +1 -1
  54. package/dist/components/RenderModal/SchemaEditor/ZodDiscriminatedUnionEditor.js +2 -1
  55. package/dist/components/RenderModal/SchemaEditor/ZodEnumEditor.d.ts +1 -0
  56. package/dist/components/RenderModal/SchemaEditor/ZodEnumEditor.js +3 -3
  57. package/dist/components/RenderModal/SchemaEditor/ZodMatrixEditor.js +1 -1
  58. package/dist/components/RenderModal/SchemaEditor/ZodNonEditableValue.js +1 -1
  59. package/dist/components/RenderModal/SchemaEditor/ZodNumberEditor.js +1 -1
  60. package/dist/components/RenderModal/SchemaEditor/ZodObjectEditor.js +1 -1
  61. package/dist/components/RenderModal/SchemaEditor/ZodOrNullishEditor.js +8 -3
  62. package/dist/components/RenderModal/SchemaEditor/ZodStaticFileEditor.js +1 -1
  63. package/dist/components/RenderModal/SchemaEditor/ZodStringEditor.js +1 -1
  64. package/dist/components/RenderModal/SchemaEditor/ZodSwitch.js +2 -2
  65. package/dist/components/RenderModal/SchemaEditor/ZodTextareaEditor.js +1 -1
  66. package/dist/components/RenderModal/SchemaEditor/ZodTupleEditor.js +1 -1
  67. package/dist/components/RenderModal/SchemaEditor/zod-schema-type.d.ts +1 -0
  68. package/dist/components/RenderModal/SchemaEditor/zod-schema-type.js +12 -1
  69. package/dist/components/RenderModal/ServerRenderModal.js +4 -0
  70. package/dist/components/RenderQueue/RenderQueueItem.js +8 -2
  71. package/dist/components/RenderQueue/actions.d.ts +4 -2
  72. package/dist/components/RenderQueue/actions.js +4 -2
  73. package/dist/components/RenderQueue/index.js +3 -4
  74. package/dist/components/RenderQueue/use-render-output-file-drag.d.ts +8 -0
  75. package/dist/components/RenderQueue/use-render-output-file-drag.js +121 -0
  76. package/dist/components/SegmentedControl.js +0 -1
  77. package/dist/components/SelectedOutlineCanvasRotation.d.ts +9 -0
  78. package/dist/components/SelectedOutlineCanvasRotation.js +237 -0
  79. package/dist/components/SelectedOutlineElement.d.ts +16 -18
  80. package/dist/components/SelectedOutlineElement.js +144 -931
  81. package/dist/components/SelectedOutlineKeyboardControls.d.ts +7 -0
  82. package/dist/components/SelectedOutlineKeyboardControls.js +261 -0
  83. package/dist/components/SelectedOutlineOverlay.d.ts +7 -14
  84. package/dist/components/SelectedOutlineOverlay.js +378 -864
  85. package/dist/components/SelectedOutlinePolygon.d.ts +26 -0
  86. package/dist/components/SelectedOutlinePolygon.js +360 -0
  87. package/dist/components/SelectedOutlineRenderer.d.ts +19 -0
  88. package/dist/components/SelectedOutlineRenderer.js +225 -0
  89. package/dist/components/SelectedOutlineRotationCornerHandle.d.ts +17 -0
  90. package/dist/components/SelectedOutlineRotationCornerHandle.js +271 -0
  91. package/dist/components/SelectedOutlineScaleEdgeLine.d.ts +17 -0
  92. package/dist/components/SelectedOutlineScaleEdgeLine.js +215 -0
  93. package/dist/components/SelectedOutlineSnapIndicators.d.ts +9 -0
  94. package/dist/components/SelectedOutlineSnapIndicators.js +29 -0
  95. package/dist/components/SelectedOutlineTransformOriginHandle.d.ts +9 -0
  96. package/dist/components/SelectedOutlineTransformOriginHandle.js +312 -0
  97. package/dist/components/SelectedOutlineUvControls.d.ts +3 -9
  98. package/dist/components/SelectedOutlineUvControls.js +57 -12
  99. package/dist/components/SequencePropsSubscriptionProvider.js +8 -0
  100. package/dist/components/SettingsContext.d.ts +15 -0
  101. package/dist/components/SettingsContext.js +116 -0
  102. package/dist/components/SettingsModal.js +10 -4
  103. package/dist/components/SettingsModalFooter.d.ts +1 -3
  104. package/dist/components/SettingsModalFooter.js +4 -6
  105. package/dist/components/ShowOutlinesProvider.js +2 -3
  106. package/dist/components/Timeline/EasingEditorModal.js +66 -22
  107. package/dist/components/Timeline/SequencePropsObserver.js +97 -1
  108. package/dist/components/Timeline/SubscribeToNodePaths.js +4 -2
  109. package/dist/components/Timeline/Timeline.js +22 -5
  110. package/dist/components/Timeline/TimelineDuplicateCount.d.ts +4 -0
  111. package/dist/components/Timeline/TimelineDuplicateCount.js +28 -0
  112. package/dist/components/Timeline/TimelineEffectItem.js +1 -4
  113. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +3 -23
  114. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.d.ts +4 -2
  115. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.js +11 -1
  116. package/dist/components/Timeline/TimelineFieldRowContent.js +10 -3
  117. package/dist/components/Timeline/TimelineRotationField.js +84 -12
  118. package/dist/components/Timeline/TimelineScaleField.js +58 -4
  119. package/dist/components/Timeline/TimelineSelection.d.ts +4 -0
  120. package/dist/components/Timeline/TimelineSelection.js +45 -2
  121. package/dist/components/Timeline/TimelineSequence.js +28 -25
  122. package/dist/components/Timeline/TimelineSequenceItem.js +91 -28
  123. package/dist/components/Timeline/TimelineSequencePropItem.js +5 -2
  124. package/dist/components/Timeline/TimelineTrack.js +2 -1
  125. package/dist/components/Timeline/TimelineTransformOriginField.js +78 -4
  126. package/dist/components/Timeline/TimelineTranslateField.js +55 -15
  127. package/dist/components/Timeline/Transform3DModeContext.d.ts +1 -0
  128. package/dist/components/Timeline/Transform3DModeContext.js +5 -0
  129. package/dist/components/Timeline/delete-selected-timeline-item.js +0 -6
  130. package/dist/components/Timeline/get-sequence-context-menu-items.d.ts +6 -3
  131. package/dist/components/Timeline/get-sequence-context-menu-items.js +69 -57
  132. package/dist/components/Timeline/sequence-props-subscription-store.d.ts +2 -1
  133. package/dist/components/Timeline/sequence-props-subscription-store.js +5 -2
  134. package/dist/components/Timeline/timeline-field-display-utils.js +2 -2
  135. package/dist/components/Timeline/timeline-field-row-layout.d.ts +6 -0
  136. package/dist/components/Timeline/timeline-field-row-layout.js +16 -1
  137. package/dist/components/Timeline/timeline-rotation-utils.d.ts +16 -0
  138. package/dist/components/Timeline/timeline-rotation-utils.js +145 -4
  139. package/dist/components/Timeline/timeline-translate-utils.d.ts +3 -2
  140. package/dist/components/Timeline/timeline-translate-utils.js +8 -4
  141. package/dist/components/Timeline/transform-3d-mode.d.ts +6 -0
  142. package/dist/components/Timeline/transform-3d-mode.js +36 -0
  143. package/dist/components/Timeline/transform-origin-utils.d.ts +4 -0
  144. package/dist/components/Timeline/transform-origin-utils.js +12 -6
  145. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +36 -4
  146. package/dist/components/Timeline/{use-open-sequence-in-editor.d.ts → use-open-sequence-in-apps.d.ts} +4 -1
  147. package/dist/components/Timeline/{use-open-sequence-in-editor.js → use-open-sequence-in-apps.js} +21 -5
  148. package/dist/components/Timeline/use-resolved-stack-react-to-change.d.ts +5 -1
  149. package/dist/components/Timeline/use-resolved-stack-react-to-change.js +45 -9
  150. package/dist/components/Timeline/use-sequence-props-subscription.d.ts +3 -1
  151. package/dist/components/Timeline/use-sequence-props-subscription.js +7 -2
  152. package/dist/components/Timeline/use-timeline-expanded-tree.d.ts +4 -0
  153. package/dist/components/Timeline/use-timeline-expanded-tree.js +45 -1
  154. package/dist/components/call-api.js +2 -0
  155. package/dist/components/canvas-rotation-cursor.d.ts +1 -0
  156. package/dist/components/canvas-rotation-cursor.js +14 -0
  157. package/dist/components/get-open-in-menu-items.d.ts +17 -0
  158. package/dist/components/get-open-in-menu-items.js +144 -0
  159. package/dist/components/selected-outline-drag.d.ts +11 -5
  160. package/dist/components/selected-outline-drag.js +80 -42
  161. package/dist/components/selected-outline-measurement.d.ts +7 -2
  162. package/dist/components/selected-outline-measurement.js +28 -1
  163. package/dist/components/selected-outline-order.d.ts +12 -0
  164. package/dist/components/selected-outline-order.js +251 -0
  165. package/dist/components/selected-outline-types.d.ts +15 -10
  166. package/dist/components/svg-point-to-client-point.d.ts +2 -0
  167. package/dist/components/svg-point-to-client-point.js +10 -0
  168. package/dist/components/use-auto-save-config.d.ts +8 -0
  169. package/dist/components/use-auto-save-config.js +74 -0
  170. package/dist/components/use-default-editor-info.d.ts +1 -0
  171. package/dist/components/use-default-editor-info.js +10 -30
  172. package/dist/esm/{chunk-jefhcs5z.js → chunk-fgedsvhb.js} +1 -2
  173. package/dist/esm/{chunk-b49ec3nz.js → chunk-zpn4m49r.js} +12924 -10139
  174. package/dist/esm/index.mjs +357 -2
  175. package/dist/esm/internals.mjs +12923 -10138
  176. package/dist/esm/previewEntry.mjs +12771 -9986
  177. package/dist/esm/renderEntry.mjs +2 -2
  178. package/dist/helpers/are-sequence-node-path-infos-equal.d.ts +2 -0
  179. package/dist/helpers/are-sequence-node-path-infos-equal.js +27 -0
  180. package/dist/helpers/calculate-timeline.js +3 -3
  181. package/dist/helpers/client-id.js +8 -1
  182. package/dist/helpers/format-file-location.d.ts +1 -1
  183. package/dist/helpers/format-file-location.js +3 -3
  184. package/dist/helpers/get-box-quads-polyfill-internals.js +10 -2
  185. package/dist/helpers/migrate-expanded-tracks-for-subscription-key.js +3 -3
  186. package/dist/helpers/open-in-editor.d.ts +4 -1
  187. package/dist/helpers/open-in-editor.js +9 -1
  188. package/dist/helpers/preview-server-events.js +4 -0
  189. package/dist/helpers/sequence-node-path-mutations.d.ts +4 -0
  190. package/dist/helpers/sequence-node-path-mutations.js +31 -0
  191. package/dist/helpers/studio-runtime-config.js +3 -0
  192. package/dist/helpers/timeline-node-path-key.d.ts +2 -0
  193. package/dist/helpers/timeline-node-path-key.js +3 -1
  194. package/dist/helpers/use-asset-drag-events.d.ts +2 -1
  195. package/dist/helpers/use-asset-drag-events.js +14 -6
  196. package/dist/helpers/use-menu-structure.js +2 -2
  197. package/dist/helpers/use-runtime-values.d.ts +1 -3
  198. package/dist/icons/cube.d.ts +4 -0
  199. package/dist/icons/cube.js +6 -0
  200. package/dist/icons/finder.d.ts +4 -0
  201. package/dist/icons/finder.js +8 -0
  202. package/dist/icons/terminal.d.ts +6 -0
  203. package/dist/icons/terminal.js +46 -0
  204. package/dist/index.d.ts +15 -0
  205. package/dist/index.js +8 -0
  206. package/dist/state/timeline-sequence-hover.d.ts +9 -3
  207. package/dist/state/timeline-sequence-hover.js +63 -12
  208. package/dist/state/transform-3d-mode.d.ts +10 -0
  209. package/dist/state/transform-3d-mode.js +27 -0
  210. package/dist/state/z-index.js +5 -8
  211. package/package.json +12 -12
@@ -12,7 +12,6 @@ const footer = {
12
12
  const footerRow = {
13
13
  alignItems: 'center',
14
14
  display: 'flex',
15
- justifyContent: 'space-between',
16
15
  };
17
16
  const configFileHint = {
18
17
  alignItems: 'center',
@@ -30,7 +29,7 @@ const configFileName = {
30
29
  fontWeight: 'bold',
31
30
  lineHeight: '20px',
32
31
  };
33
- const SettingsModalFooter = ({ children }) => {
32
+ const SettingsModalFooter = () => {
34
33
  const configFileLocation = (0, react_1.useMemo)(() => {
35
34
  return {
36
35
  source: 'remotion.config.ts',
@@ -38,9 +37,8 @@ const SettingsModalFooter = ({ children }) => {
38
37
  column: 1,
39
38
  };
40
39
  }, []);
41
- return (jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { style: footer, noBorder: true, children: jsx_runtime_1.jsxs("div", { style: footerRow, children: [
42
- jsx_runtime_1.jsxs("div", { style: configFileHint, children: ["Changes save to",
43
- jsx_runtime_1.jsx(InspectorOpenInEditor_1.InspectorOpenInEditor, { location: configFileLocation, label: jsx_runtime_1.jsx("strong", { style: configFileName, children: "remotion.config.ts" }) })
44
- ] }), children] }) }));
40
+ return (jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { style: footer, noBorder: true, children: jsx_runtime_1.jsx("div", { style: footerRow, children: jsx_runtime_1.jsxs("div", { style: configFileHint, children: ["Changes save to",
41
+ jsx_runtime_1.jsx(InspectorOpenInEditor_1.InspectorOpenInEditor, { locationType: null, location: configFileLocation, label: jsx_runtime_1.jsx("strong", { style: configFileName, children: "remotion.config.ts" }) })
42
+ ] }) }) }));
45
43
  };
46
44
  exports.SettingsModalFooter = SettingsModalFooter;
@@ -7,7 +7,7 @@ const editor_outlines_1 = require("../state/editor-outlines");
7
7
  const timeline_sequence_hover_1 = require("../state/timeline-sequence-hover");
8
8
  const ShowOutlinesProvider = ({ children }) => {
9
9
  const [editorShowOutlines, setEditorShowOutlinesState] = (0, react_1.useState)(() => (0, editor_outlines_1.loadEditorShowOutlinesOption)());
10
- const [hoveredSequence, setHoveredSequence] = (0, react_1.useState)(null);
10
+ const timelineSequenceHoverStore = (0, react_1.useMemo)(() => (0, timeline_sequence_hover_1.createTimelineSequenceHoverStore)(), []);
11
11
  const setEditorShowOutlines = (0, react_1.useCallback)((newValue) => {
12
12
  setEditorShowOutlinesState((prevState) => {
13
13
  const newVal = newValue(prevState);
@@ -21,7 +21,6 @@ const ShowOutlinesProvider = ({ children }) => {
21
21
  setEditorShowOutlines,
22
22
  };
23
23
  }, [editorShowOutlines, setEditorShowOutlines]);
24
- const timelineSequenceHoverCtx = (0, react_1.useMemo)(() => ({ hoveredSequence, setHoveredSequence }), [hoveredSequence]);
25
- return (jsx_runtime_1.jsx(editor_outlines_1.EditorShowOutlinesContext.Provider, { value: editorShowOutlinesCtx, children: jsx_runtime_1.jsx(timeline_sequence_hover_1.TimelineSequenceHoverContext.Provider, { value: timelineSequenceHoverCtx, children: children }) }));
24
+ return (jsx_runtime_1.jsx(editor_outlines_1.EditorShowOutlinesContext.Provider, { value: editorShowOutlinesCtx, children: jsx_runtime_1.jsx(timeline_sequence_hover_1.TimelineSequenceHoverContext.Provider, { value: timelineSequenceHoverStore, children: children }) }));
26
25
  };
27
26
  exports.ShowOutlinesProvider = ShowOutlinesProvider;
@@ -75,8 +75,9 @@ const SPRING_FALLBACKS = {
75
75
  stiffness: DEFAULT_SPRING_EASING.stiffness,
76
76
  };
77
77
  const inlineContainer = {
78
- width: '100%',
79
78
  minWidth: 0,
79
+ paddingBottom: 12,
80
+ width: '100%',
80
81
  };
81
82
  const segmentedControlWrapper = {
82
83
  display: 'flex',
@@ -85,27 +86,27 @@ const segmentedControlWrapper = {
85
86
  padding: `0 ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px`,
86
87
  };
87
88
  const presetButtonsWrapper = {
88
- display: 'flex',
89
- flexWrap: 'wrap',
90
- gap: 6,
91
- justifyContent: 'flex-start',
92
- marginBottom: 8,
93
- padding: `0 ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px`,
89
+ border: `1px solid ${colors_1.BLACK_ALPHA_60}`,
90
+ borderRadius: 4,
91
+ boxSizing: 'border-box',
92
+ display: 'grid',
93
+ gridTemplateColumns: 'repeat(4, minmax(0, 1fr))',
94
+ margin: `0 ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px 8px`,
95
+ overflow: 'hidden',
94
96
  };
95
97
  const inspectorPresetButtonsWrapper = {
96
98
  ...presetButtonsWrapper,
97
- padding: `8px ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px 0`,
99
+ margin: `8px ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px 0`,
98
100
  };
99
101
  const presetButtonBase = {
100
102
  alignItems: 'center',
101
- backgroundColor: colors_1.INPUT_BACKGROUND,
102
- border: `1px solid ${colors_1.WHITE_ALPHA_05}`,
103
- borderRadius: 4,
103
+ backgroundColor: colors_1.TRANSPARENT,
104
+ border: 'none',
104
105
  display: 'inline-flex',
105
106
  height: 34,
106
107
  justifyContent: 'center',
107
108
  padding: 0,
108
- width: 52,
109
+ width: '100%',
109
110
  };
110
111
  const presetPreviewSvgStyle = {
111
112
  display: 'block',
@@ -172,7 +173,10 @@ const easingToSpring = (easing) => {
172
173
  : DEFAULT_SPRING_EASING;
173
174
  };
174
175
  const easingToMode = (easing) => {
175
- return isSpringEasing(easing) ? 'spring' : 'bezier';
176
+ if (isSpringEasing(easing)) {
177
+ return 'spring';
178
+ }
179
+ return easing.type === 'step1' ? 'hold' : 'bezier';
176
180
  };
177
181
  const roundToDecimalPlaces = (value, decimalPlaces) => {
178
182
  const factor = 10 ** decimalPlaces;
@@ -243,6 +247,7 @@ const areEasingsEqual = (first, second) => {
243
247
  }
244
248
  switch (first.type) {
245
249
  case 'linear':
250
+ case 'step1':
246
251
  return true;
247
252
  case 'spring':
248
253
  return (second.type === 'spring' &&
@@ -322,6 +327,8 @@ const getEasingFunction = (easing) => {
322
327
  switch (easing.type) {
323
328
  case 'linear':
324
329
  return remotion_1.Easing.linear;
330
+ case 'step1':
331
+ return remotion_1.Easing.step1;
325
332
  case 'bezier':
326
333
  return remotion_1.Easing.bezier(easing.x1, easing.y1, easing.x2, easing.y2);
327
334
  case 'spring':
@@ -338,6 +345,13 @@ const getEasingFunction = (easing) => {
338
345
  }
339
346
  };
340
347
  const getPresetPreviewPath = (easing) => {
348
+ if (easing.type === 'step1') {
349
+ const startX = presetPreviewXToSvg(0);
350
+ const endX = presetPreviewXToSvg(1);
351
+ const startY = presetPreviewYToSvg(0);
352
+ const endY = presetPreviewYToSvg(1);
353
+ return `M ${startX} ${startY} L ${endX} ${startY} L ${endX} ${endY}`;
354
+ }
341
355
  const easingFunction = getEasingFunction(easing);
342
356
  const samples = 36;
343
357
  const points = [];
@@ -386,18 +400,24 @@ const EasingGraphScaffold = ({ labels }) => {
386
400
  };
387
401
  const EasingPresetButton = ({ currentEasing, disabled, onClick, preset }) => {
388
402
  const selected = areEasingsEqual(currentEasing, preset.easing);
403
+ const [hovered, setHovered] = (0, react_1.useState)(false);
389
404
  const path = (0, react_1.useMemo)(() => getPresetPreviewPath(preset.easing), [preset.easing]);
405
+ const onPointerEnter = (0, react_1.useCallback)(() => {
406
+ setHovered(true);
407
+ }, []);
408
+ const onPointerLeave = (0, react_1.useCallback)(() => {
409
+ setHovered(false);
410
+ }, []);
390
411
  const style = (0, react_1.useMemo)(() => ({
391
412
  ...presetButtonBase,
392
- backgroundColor: selected ? colors_1.EASING_SELECTED_BACKGROUND : colors_1.INPUT_BACKGROUND,
393
- borderColor: selected ? colors_1.BLUE : colors_1.WHITE_ALPHA_05,
394
- cursor: disabled ? 'not-allowed' : 'pointer',
413
+ backgroundColor: selected ? colors_1.INPUT_BACKGROUND : colors_1.TRANSPARENT,
414
+ cursor: disabled ? 'not-allowed' : undefined,
395
415
  opacity: disabled ? 0.45 : 1,
396
416
  }), [disabled, selected]);
397
417
  const handleClick = (0, react_1.useCallback)(() => {
398
418
  onClick(preset.easing);
399
419
  }, [onClick, preset.easing]);
400
- 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: colors_1.WHITE, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
420
+ return (jsx_runtime_1.jsx("button", { type: "button", style: style, title: preset.label, "aria-label": `Apply ${preset.label} easing`, disabled: disabled, onClick: handleClick, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, 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: selected || hovered ? colors_1.WHITE : colors_1.LIGHT_TEXT, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
401
421
  };
402
422
  const EasingEditor = ({ state, renderHeader }) => {
403
423
  var _a, _b;
@@ -590,7 +610,9 @@ const EasingEditor = ({ state, renderHeader }) => {
590
610
  }
591
611
  const easing = nextMode === 'spring'
592
612
  ? serializeSpring(springRef.current)
593
- : serializeBezier(bezierRef.current);
613
+ : nextMode === 'hold'
614
+ ? studio_shared_1.HOLD_KEYFRAME_EASING
615
+ : serializeBezier(bezierRef.current);
594
616
  const version = applyLiveEasing(easing);
595
617
  commitEasing(easing, version);
596
618
  }, [applyLiveEasing, commitEasing, mode, previewServerState.type]);
@@ -605,11 +627,18 @@ const EasingEditor = ({ state, renderHeader }) => {
605
627
  commitEasing(serializeSpring(nextSpring), springVersion);
606
628
  return;
607
629
  }
630
+ if (easing.type === 'step1') {
631
+ setMode('hold');
632
+ const holdVersion = applyLiveEasing(studio_shared_1.HOLD_KEYFRAME_EASING);
633
+ commitEasing(studio_shared_1.HOLD_KEYFRAME_EASING, holdVersion);
634
+ return;
635
+ }
608
636
  const nextBezier = easingToBezier(easing);
609
637
  setMode('bezier');
610
638
  const bezierVersion = setBezierAndPreview(nextBezier);
611
639
  commitEasing(serializeBezier(nextBezier), bezierVersion);
612
640
  }, [
641
+ applyLiveEasing,
613
642
  commitEasing,
614
643
  previewServerState.type,
615
644
  setBezierAndPreview,
@@ -709,9 +738,15 @@ const EasingEditor = ({ state, renderHeader }) => {
709
738
  }
710
739
  return points.join(' ');
711
740
  }, [spring]);
741
+ const holdPath = (0, react_1.useMemo)(() => `M ${startPoint.x} ${startPoint.y} L ${endPoint.x} ${startPoint.y} L ${endPoint.x} ${endPoint.y}`, [endPoint, startPoint]);
712
742
  const disabled = previewServerState.type !== 'connected';
713
743
  const graphLabels = getEasingGraphLabels(getCurrentEasingUpdates());
714
- const currentEasing = (0, react_1.useMemo)(() => mode === 'spring' ? serializeSpring(spring) : serializeBezier(bezier), [bezier, mode, spring]);
744
+ const currentEasing = (0, react_1.useMemo)(() => {
745
+ if (mode === 'spring') {
746
+ return serializeSpring(spring);
747
+ }
748
+ return mode === 'hold' ? studio_shared_1.HOLD_KEYFRAME_EASING : serializeBezier(bezier);
749
+ }, [bezier, mode, spring]);
715
750
  const modeItems = (0, react_1.useMemo)(() => {
716
751
  return [
717
752
  {
@@ -726,12 +761,18 @@ const EasingEditor = ({ state, renderHeader }) => {
726
761
  onClick: () => switchMode('spring'),
727
762
  selected: mode === 'spring',
728
763
  },
764
+ {
765
+ key: 'hold',
766
+ label: 'Hold',
767
+ onClick: () => switchMode('hold'),
768
+ selected: mode === 'hold',
769
+ },
729
770
  ];
730
771
  }, [mode, switchMode]);
731
772
  const coordinatesGrid = (0, react_1.useMemo)(() => ({
732
773
  ...coordinatesGridBase,
733
774
  gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
734
- padding: '0 12px 12px',
775
+ padding: '0 12px',
735
776
  }), []);
736
777
  const modeSwitcher = (jsx_runtime_1.jsx("div", { style: segmentedControlWrapper, children: jsx_runtime_1.jsx(SegmentedControl_1.SegmentedControl, { items: modeItems, needsWrapping: false }) }));
737
778
  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: [
@@ -748,7 +789,7 @@ const EasingEditor = ({ state, renderHeader }) => {
748
789
  jsx_runtime_1.jsx("div", { style: coordinateLabel, children: "Y2" }), jsx_runtime_1.jsx("div", { style: coordinateInputWrapper, children: jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: bezier[3], status: "ok", onValueChange: (value) => setCoordinate(1, 'y', value, false), onValueChangeEnd: (value) => setCoordinate(1, 'y', value, true), onTextChange: () => undefined, min: Y_MIN, max: Y_MAX, step: 0.01, formatter: formatNumber, rightAlign: false, style: numberInputStyle, snapToStep: false, disabled: disabled }) })
749
790
  ] })
750
791
  ] })
751
- ] })) : (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
792
+ ] })) : mode === 'spring' ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
752
793
  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: [
753
794
  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: colors_1.WHITE }), jsx_runtime_1.jsx("circle", { cx: xToSvg(1), cy: yToSvg(1), r: 4, fill: colors_1.WHITE })
754
795
  ] }), modeSwitcher, jsx_runtime_1.jsxs("div", { style: coordinatesGrid, children: [
@@ -766,6 +807,9 @@ const EasingEditor = ({ state, renderHeader }) => {
766
807
  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" }) })
767
808
  ] })
768
809
  ] })
769
- ] }))] }));
810
+ ] })) : (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
811
+ jsx_runtime_1.jsxs("svg", { width: SVG_WIDTH, height: SVG_HEIGHT, viewBox: `0 0 ${SVG_WIDTH} ${SVG_HEIGHT}`, style: svgStyle, "aria-label": "Hold easing curve", children: [
812
+ jsx_runtime_1.jsx(EasingGraphScaffold, { labels: graphLabels }), jsx_runtime_1.jsx("path", { d: holdPath, fill: "none", stroke: colors_1.BLUE, strokeWidth: 3 }), jsx_runtime_1.jsx("circle", { cx: startPoint.x, cy: startPoint.y, r: 4, fill: colors_1.WHITE }), jsx_runtime_1.jsx("circle", { cx: endPoint.x, cy: endPoint.y, r: 4, fill: colors_1.WHITE })
813
+ ] }), modeSwitcher] }))] }));
770
814
  };
771
815
  exports.EasingEditor = EasingEditor;
@@ -3,10 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SequencePropsObserver = void 0;
4
4
  const react_1 = require("react");
5
5
  const remotion_1 = require("remotion");
6
+ const fast_refresh_context_1 = require("../../fast-refresh-context");
6
7
  const client_id_1 = require("../../helpers/client-id");
8
+ const sequence_node_path_mutations_1 = require("../../helpers/sequence-node-path-mutations");
9
+ const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
7
10
  const SequencePropsObserver = () => {
8
11
  const { subscribeToEvent } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
9
- const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
12
+ const { remapPropStatuses, setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
13
+ const propStatusesRef = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesRefContext);
14
+ const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
15
+ const overrideIdToNodePathMappingsRef = (0, react_1.useRef)(overrideIdToNodePathMappings);
16
+ overrideIdToNodePathMappingsRef.current = overrideIdToNodePathMappings;
17
+ const { setOverrideIdToNodePath } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsSettersContext);
18
+ const { fastRefreshes } = (0, react_1.useContext)(fast_refresh_context_1.FastRefreshContext);
19
+ const { migrateExpandedTracksForSubscriptionKey } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksSetterContext);
10
20
  (0, react_1.useEffect)(() => {
11
21
  const handleEvent = (event) => {
12
22
  if (event.type !== 'sequence-props-updated') {
@@ -19,6 +29,92 @@ const SequencePropsObserver = () => {
19
29
  unsubscribe();
20
30
  };
21
31
  }, [setPropStatuses, subscribeToEvent]);
32
+ (0, react_1.useLayoutEffect)(() => {
33
+ var _a;
34
+ const mutations = (0, sequence_node_path_mutations_1.takePendingSequenceNodePathMutations)();
35
+ if (mutations.length === 0) {
36
+ return;
37
+ }
38
+ const statusRemappings = [];
39
+ const overrideUpdates = [];
40
+ for (const [overrideId, previousNodePath] of Object.entries(overrideIdToNodePathMappingsRef.current)) {
41
+ let { nodePath } = previousNodePath;
42
+ let wasRemapped = false;
43
+ let wasDeleted = false;
44
+ let runtimeNodePathExists = true;
45
+ const previousNodePathString = JSON.stringify(previousNodePath.nodePath);
46
+ for (const mutation of mutations) {
47
+ for (const file of mutation.files) {
48
+ if (file.absolutePath !== previousNodePath.absolutePath) {
49
+ continue;
50
+ }
51
+ // Prop statuses follow source nodes to their new paths. Override IDs,
52
+ // however, follow React's runtime instances. After deleting an unkeyed
53
+ // sibling, React reuses the instance already at the destination path.
54
+ // Keep that mapping in place and only remove mappings for vacated paths.
55
+ const runtimeNodePathIsSource = file.remappings.some((item) => JSON.stringify(item.oldNodePath) === previousNodePathString);
56
+ const runtimeNodePathIsDestination = file.remappings.some((item) => item.newNodePath !== null &&
57
+ JSON.stringify(item.newNodePath) === previousNodePathString);
58
+ const runtimeNodePathWasRestored = file.restoredNodePaths.some((item) => JSON.stringify(item) === previousNodePathString);
59
+ if (runtimeNodePathIsSource) {
60
+ runtimeNodePathExists =
61
+ runtimeNodePathIsDestination || runtimeNodePathWasRestored;
62
+ }
63
+ else if (runtimeNodePathIsDestination ||
64
+ runtimeNodePathWasRestored) {
65
+ runtimeNodePathExists = true;
66
+ }
67
+ if (wasDeleted) {
68
+ const wasRestored = file.restoredNodePaths.some((restoredNodePath) => JSON.stringify(restoredNodePath) === JSON.stringify(nodePath));
69
+ if (wasRestored) {
70
+ wasDeleted = false;
71
+ }
72
+ continue;
73
+ }
74
+ const remapping = file.remappings.find((item) => JSON.stringify(item.oldNodePath) === JSON.stringify(nodePath));
75
+ if (!remapping) {
76
+ continue;
77
+ }
78
+ wasRemapped = true;
79
+ if (remapping.newNodePath === null) {
80
+ wasDeleted = true;
81
+ continue;
82
+ }
83
+ nodePath = remapping.newNodePath;
84
+ }
85
+ }
86
+ if (!wasRemapped) {
87
+ continue;
88
+ }
89
+ const nextNodePath = wasDeleted ? null : { ...previousNodePath, nodePath };
90
+ const previousStatusKey = remotion_1.Internals.makeSequencePropsSubscriptionKey(previousNodePath);
91
+ statusRemappings.push({
92
+ previousNodePath,
93
+ nodePath: nextNodePath,
94
+ result: (_a = propStatusesRef.current[previousStatusKey]) !== null && _a !== void 0 ? _a : null,
95
+ });
96
+ overrideUpdates.push({
97
+ overrideId,
98
+ nodePath: runtimeNodePathExists ? previousNodePath : null,
99
+ });
100
+ }
101
+ remapPropStatuses(statusRemappings);
102
+ for (const event of overrideUpdates) {
103
+ setOverrideIdToNodePath(event.overrideId, event.nodePath);
104
+ }
105
+ for (const event of statusRemappings) {
106
+ if (event.nodePath === null) {
107
+ continue;
108
+ }
109
+ migrateExpandedTracksForSubscriptionKey(event.previousNodePath, event.nodePath);
110
+ }
111
+ }, [
112
+ fastRefreshes,
113
+ migrateExpandedTracksForSubscriptionKey,
114
+ propStatusesRef,
115
+ remapPropStatuses,
116
+ setOverrideIdToNodePath,
117
+ ]);
22
118
  return null;
23
119
  };
24
120
  exports.SequencePropsObserver = SequencePropsObserver;
@@ -6,7 +6,7 @@ const no_react_1 = require("remotion/no-react");
6
6
  const use_resolved_stack_react_to_change_1 = require("./use-resolved-stack-react-to-change");
7
7
  const use_sequence_props_subscription_1 = require("./use-sequence-props-subscription");
8
8
  const SubscribeToNodePaths = ({ overrideId, componentIdentity, schema, getStack, effects }) => {
9
- const originalLocation = (0, use_resolved_stack_react_to_change_1.useResolveStackAndReactToChange)(getStack);
9
+ const { resolvedLocation, stack, preferMappedNodePath } = (0, use_resolved_stack_react_to_change_1.useResolveStackAndReactToChange)(getStack);
10
10
  const effectSubscriptions = (0, react_1.useMemo)(() => {
11
11
  return effects
12
12
  .map((effect) => {
@@ -19,7 +19,9 @@ const SubscribeToNodePaths = ({ overrideId, componentIdentity, schema, getStack,
19
19
  componentIdentity,
20
20
  schema,
21
21
  effects: effectSubscriptions,
22
- originalLocation,
22
+ originalLocation: resolvedLocation,
23
+ preferMappedNodePath,
24
+ stack,
23
25
  });
24
26
  return null;
25
27
  };
@@ -45,6 +45,7 @@ const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
45
45
  const is_current_selected_still_1 = require("../../helpers/is-current-selected-still");
46
46
  const open_in_editor_1 = require("../../helpers/open-in-editor");
47
47
  const studio_runtime_config_1 = require("../../helpers/studio-runtime-config");
48
+ const timeline_node_path_key_1 = require("../../helpers/timeline-node-path-key");
48
49
  const call_api_1 = require("../call-api");
49
50
  const ContextMenu_1 = require("../ContextMenu");
50
51
  const import_assets_1 = require("../import-assets");
@@ -256,13 +257,29 @@ const TimelineInner = () => {
256
257
  const filtered = (0, react_1.useMemo)(() => {
257
258
  return timeline.filter((t) => (0, should_show_track_in_timeline_1.shouldShowTrackInTimeline)(t, durationInFrames));
258
259
  }, [durationInFrames, timeline]);
260
+ // Keep `filtered` complete so a future toggle can show every programmatic
261
+ // instance without recalculating the timeline or losing its instance index.
262
+ const collapsed = (0, react_1.useMemo)(() => {
263
+ const seenNodePaths = new Set();
264
+ return filtered.filter((track) => {
265
+ if (track.nodePathInfo === null) {
266
+ return true;
267
+ }
268
+ const key = (0, timeline_node_path_key_1.timelineSequenceNodePathToKey)(track.nodePathInfo.sequenceSubscriptionKey);
269
+ if (seenNodePaths.has(key)) {
270
+ return false;
271
+ }
272
+ seenNodePaths.add(key);
273
+ return true;
274
+ });
275
+ }, [filtered]);
259
276
  const maxTimelineTracks = (0, studio_runtime_config_1.getStudioMaxTimelineTracks)();
260
277
  const shown = (0, react_1.useMemo)(() => {
261
- return filtered.length > maxTimelineTracks
262
- ? filtered.slice(0, maxTimelineTracks)
263
- : filtered;
264
- }, [filtered, maxTimelineTracks]);
265
- const hasBeenCut = filtered.length > shown.length;
278
+ return collapsed.length > maxTimelineTracks
279
+ ? collapsed.slice(0, maxTimelineTracks)
280
+ : collapsed;
281
+ }, [collapsed, maxTimelineTracks]);
282
+ const hasBeenCut = collapsed.length > shown.length;
266
283
  return (jsx_runtime_1.jsxs(TimelineContextMenuArea, { children: [sequences.map((sequence) => {
267
284
  if (!(0, should_subscribe_to_sequence_props_1.shouldSubscribeToSequenceProps)(sequence, previewInteractive)) {
268
285
  return null;
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const TimelineDuplicateCount: React.FC<{
3
+ readonly count: number;
4
+ }>;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelineDuplicateCount = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const colors_1 = require("../../helpers/colors");
6
+ const badgeStyle = {
7
+ alignItems: 'center',
8
+ border: `1px solid ${colors_1.WHITE_ALPHA_20}`,
9
+ borderRadius: 4,
10
+ boxSizing: 'border-box',
11
+ color: colors_1.WHITE_ALPHA_60,
12
+ display: 'inline-flex',
13
+ flexShrink: 0,
14
+ fontSize: 10,
15
+ fontWeight: 300,
16
+ height: 14,
17
+ justifyContent: 'center',
18
+ lineHeight: '12px',
19
+ minWidth: 18,
20
+ padding: '0 3px',
21
+ userSelect: 'none',
22
+ WebkitUserSelect: 'none',
23
+ };
24
+ const TimelineDuplicateCount = ({ count }) => {
25
+ const label = `${count} other programmatically duplicated ${count === 1 ? 'instance is' : 'instances are'} hidden`;
26
+ return (jsx_runtime_1.jsxs("span", { style: badgeStyle, title: label, "aria-label": label, children: ["+", count] }));
27
+ };
28
+ exports.TimelineDuplicateCount = TimelineDuplicateCount;
@@ -109,10 +109,7 @@ const TimelineEffectItem = ({ label, nodePathInfo, effectIndex, effectSchema, do
109
109
  effectIndex,
110
110
  },
111
111
  ]);
112
- if (result.success) {
113
- (0, NotificationCenter_1.showNotification)('Removed effect from source file', 2000);
114
- }
115
- else {
112
+ if (!result.success) {
116
113
  (0, NotificationCenter_1.showNotification)(result.reason, 4000);
117
114
  }
118
115
  }
@@ -35,8 +35,8 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.TimelineExpandedKeyframeRow = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
- const studio_shared_1 = require("@remotion/studio-shared");
39
38
  const react_1 = __importStar(require("react"));
39
+ const are_sequence_node_path_infos_equal_1 = require("../../helpers/are-sequence-node-path-infos-equal");
40
40
  const timeline_layout_1 = require("../../helpers/timeline-layout");
41
41
  const get_timeline_easing_segments_1 = require("./get-timeline-easing-segments");
42
42
  const TimelineKeyframeDiamond_1 = require("./TimelineKeyframeDiamond");
@@ -71,29 +71,9 @@ const areTimelineExpandedKeyframeRowPropsEqual = (prevProps, nextProps) => {
71
71
  prevProps.canEditEasing !== nextProps.canEditEasing ||
72
72
  prevProps.showSeparator !== nextProps.showSeparator ||
73
73
  prevProps.keyframes.length !== nextProps.keyframes.length ||
74
- prevProps.nodePathInfo.index !== nextProps.nodePathInfo.index ||
75
- prevProps.nodePathInfo.numberOfSequencesWithThisNodePath !==
76
- nextProps.nodePathInfo.numberOfSequencesWithThisNodePath ||
77
- prevProps.nodePathInfo.supportsEffects !==
78
- nextProps.nodePathInfo.supportsEffects ||
79
- (0, studio_shared_1.stringifySequenceSubscriptionKey)(prevProps.nodePathInfo.sequenceSubscriptionKey) !==
80
- (0, studio_shared_1.stringifySequenceSubscriptionKey)(nextProps.nodePathInfo.sequenceSubscriptionKey) ||
81
- prevProps.nodePathInfo.auxiliaryKeys.length !==
82
- nextProps.nodePathInfo.auxiliaryKeys.length) {
74
+ !(0, are_sequence_node_path_infos_equal_1.areSequenceNodePathInfosEqual)(prevProps.nodePathInfo, nextProps.nodePathInfo)) {
83
75
  return false;
84
76
  }
85
- const prevVideoConfig = prevProps.nodePathInfo.sequenceSubscriptionKey.videoConfigValues;
86
- const nextVideoConfig = nextProps.nodePathInfo.sequenceSubscriptionKey.videoConfigValues;
87
- if (prevVideoConfig !== nextVideoConfig &&
88
- (prevVideoConfig === null ||
89
- nextVideoConfig === null ||
90
- prevVideoConfig.durationInFrames !== nextVideoConfig.durationInFrames ||
91
- prevVideoConfig.fps !== nextVideoConfig.fps ||
92
- prevVideoConfig.height !== nextVideoConfig.height ||
93
- prevVideoConfig.width !== nextVideoConfig.width)) {
94
- return false;
95
- }
96
- return (prevProps.keyframes.every((keyframe, index) => keyframe.frame === nextProps.keyframes[index].frame) &&
97
- prevProps.nodePathInfo.auxiliaryKeys.every((key, index) => key === nextProps.nodePathInfo.auxiliaryKeys[index]));
77
+ return prevProps.keyframes.every((keyframe, index) => keyframe.frame === nextProps.keyframes[index].frame);
98
78
  };
99
79
  exports.TimelineExpandedKeyframeRow = react_1.default.memo(TimelineExpandedKeyframeRowUnmemoized, areTimelineExpandedKeyframeRowPropsEqual);
@@ -1,8 +1,10 @@
1
1
  import React from 'react';
2
2
  import type { TSequence } from 'remotion';
3
3
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
4
- export declare const TimelineExpandedTrackKeyframes: React.NamedExoticComponent<{
4
+ type TimelineExpandedTrackKeyframesProps = {
5
5
  readonly sequence: TSequence;
6
6
  readonly nodePathInfo: SequenceNodePathInfo;
7
7
  readonly keyframeDisplayOffset: number;
8
- }>;
8
+ };
9
+ export declare const TimelineExpandedTrackKeyframes: React.NamedExoticComponent<TimelineExpandedTrackKeyframesProps>;
10
+ export {};
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.TimelineExpandedTrackKeyframes = void 0;
7
7
  const jsx_runtime_1 = require("react/jsx-runtime");
8
8
  const react_1 = __importDefault(require("react"));
9
+ const are_sequence_node_path_infos_equal_1 = require("../../helpers/are-sequence-node-path-infos-equal");
9
10
  const TimelineExpandedKeyframeRow_1 = require("./TimelineExpandedKeyframeRow");
10
11
  const use_expanded_track_keyframe_rows_1 = require("./use-expanded-track-keyframe-rows");
11
12
  const TimelineExpandedTrackKeyframesInner = ({ nodePathInfo, sequence, keyframeDisplayOffset }) => {
@@ -16,4 +17,13 @@ const TimelineExpandedTrackKeyframesInner = ({ nodePathInfo, sequence, keyframeD
16
17
  });
17
18
  return (jsx_runtime_1.jsx("div", { style: { height: expandedHeight }, children: rows.map((row, index) => (jsx_runtime_1.jsx(TimelineExpandedKeyframeRow_1.TimelineExpandedKeyframeRow, { height: row.height, keyframes: row.keyframes, canEditEasing: row.canEditEasing, nodePathInfo: row.nodePathInfo, showSeparator: index > 0 }, row.rowKey))) }));
18
19
  };
19
- exports.TimelineExpandedTrackKeyframes = react_1.default.memo(TimelineExpandedTrackKeyframesInner);
20
+ const areTimelineExpandedTrackKeyframesPropsEqual = (first, second) => {
21
+ var _a, _b, _c, _d;
22
+ return (first.keyframeDisplayOffset === second.keyframeDisplayOffset &&
23
+ ((_a = first.sequence.controls) === null || _a === void 0 ? void 0 : _a.schema) === ((_b = second.sequence.controls) === null || _b === void 0 ? void 0 : _b.schema) &&
24
+ ((_c = first.sequence.controls) === null || _c === void 0 ? void 0 : _c.runtimeValues) ===
25
+ ((_d = second.sequence.controls) === null || _d === void 0 ? void 0 : _d.runtimeValues) &&
26
+ first.sequence.effects === second.sequence.effects &&
27
+ (0, are_sequence_node_path_infos_equal_1.areSequenceNodePathInfosEqual)(first.nodePathInfo, second.nodePathInfo));
28
+ };
29
+ exports.TimelineExpandedTrackKeyframes = react_1.default.memo(TimelineExpandedTrackKeyframesInner, areTimelineExpandedTrackKeyframesPropsEqual);
@@ -2,13 +2,20 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TimelineFieldRowContent = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
5
6
  const timeline_field_row_layout_1 = require("./timeline-field-row-layout");
6
7
  const TimelineFieldLabel_1 = require("./TimelineFieldLabel");
8
+ const Transform3DModeContext_1 = require("./Transform3DModeContext");
7
9
  const TimelineFieldRowContent = ({ field, rowDepth, selected, children }) => {
8
10
  var _a;
9
- const label = (jsx_runtime_1.jsx(TimelineFieldLabel_1.TimelineFieldLabel, { rowDepth: rowDepth, selected: selected, label: (_a = field.description) !== null && _a !== void 0 ? _a : field.key, stacked: field.typeName === 'text-content' }));
10
- const value = jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: children });
11
- if (field.typeName === 'text-content') {
11
+ const transform3DMode = (0, react_1.useContext)(Transform3DModeContext_1.Transform3DModeContext);
12
+ const stacked = (0, timeline_field_row_layout_1.isTimelineFieldStacked)({ field, transform3DMode });
13
+ const compactStacked = stacked && field.typeName !== 'text-content';
14
+ const label = (jsx_runtime_1.jsx(TimelineFieldLabel_1.TimelineFieldLabel, { rowDepth: rowDepth, selected: selected, label: (_a = field.description) !== null && _a !== void 0 ? _a : field.key, stacked: stacked }));
15
+ const value = (jsx_runtime_1.jsx("div", { style: compactStacked
16
+ ? timeline_field_row_layout_1.timelineCompactStackedFieldValueColumnStyle
17
+ : timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: children }));
18
+ if (stacked) {
12
19
  return (jsx_runtime_1.jsxs("div", { style: timeline_field_row_layout_1.timelineStackedFieldContentStyle, children: [label, value] }));
13
20
  }
14
21
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [label, value] }));