@remotion/studio 4.0.472 → 4.0.474

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 (165) hide show
  1. package/dist/api/rename-static-file.d.ts +6 -0
  2. package/dist/api/rename-static-file.js +18 -0
  3. package/dist/components/AssetSelector.js +45 -4
  4. package/dist/components/AssetSelectorItem.js +177 -27
  5. package/dist/components/Canvas.js +131 -11
  6. package/dist/components/ConfirmationDialog-types.d.ts +8 -0
  7. package/dist/components/ConfirmationDialog-types.js +2 -0
  8. package/dist/components/ConfirmationDialog.d.ts +7 -0
  9. package/dist/components/ConfirmationDialog.js +103 -0
  10. package/dist/components/ContextMenu.d.ts +9 -1
  11. package/dist/components/ContextMenu.js +49 -5
  12. package/dist/components/CurrentAsset.d.ts +1 -0
  13. package/dist/components/CurrentAsset.js +13 -2
  14. package/dist/components/EditorContent.js +15 -2
  15. package/dist/components/EditorContexts.js +2 -1
  16. package/dist/components/EditorRuler/Ruler.js +2 -0
  17. package/dist/components/ExplorerPanel.d.ts +0 -4
  18. package/dist/components/ExplorerPanel.js +8 -4
  19. package/dist/components/ExplorerPanelRef.d.ts +4 -0
  20. package/dist/components/ExplorerPanelRef.js +5 -0
  21. package/dist/components/FilePreview.d.ts +1 -1
  22. package/dist/components/InitialCompositionLoader.d.ts +0 -1
  23. package/dist/components/InitialCompositionLoader.js +5 -27
  24. package/dist/components/Menu/MenuItem.js +7 -1
  25. package/dist/components/Menu/SubMenu.js +5 -1
  26. package/dist/components/Menu/portals.js +17 -8
  27. package/dist/components/MenuToolbar.js +5 -1
  28. package/dist/components/ModalContainer.js +6 -1
  29. package/dist/components/Modals.js +5 -2
  30. package/dist/components/NewComposition/ComboBox.js +8 -2
  31. package/dist/components/NewComposition/InputDragger.d.ts +1 -0
  32. package/dist/components/NewComposition/InputDragger.js +9 -6
  33. package/dist/components/NewComposition/RenameStaticFile.d.ts +4 -0
  34. package/dist/components/NewComposition/RenameStaticFile.js +118 -0
  35. package/dist/components/OptionsPanel.js +5 -1
  36. package/dist/components/OutlineToggle.d.ts +2 -0
  37. package/dist/components/OutlineToggle.js +20 -0
  38. package/dist/components/Preview.d.ts +0 -2
  39. package/dist/components/Preview.js +23 -33
  40. package/dist/components/PreviewToolbar.js +19 -6
  41. package/dist/components/RenderButton.js +8 -2
  42. package/dist/components/RenderPreview.js +2 -2
  43. package/dist/components/SelectedOutlineOverlay.d.ts +29 -3
  44. package/dist/components/SelectedOutlineOverlay.js +259 -80
  45. package/dist/components/ShowOutlinesProvider.d.ts +4 -0
  46. package/dist/components/ShowOutlinesProvider.js +24 -0
  47. package/dist/components/SizeSelector.js +3 -3
  48. package/dist/components/Splitter/SplitterHandle.js +2 -0
  49. package/dist/components/StaticFilePreview.js +2 -2
  50. package/dist/components/Timeline/KeyframeSettingsModal.d.ts +15 -0
  51. package/dist/components/Timeline/KeyframeSettingsModal.js +150 -0
  52. package/dist/components/Timeline/SequencePropsObserver.js +3 -3
  53. package/dist/components/Timeline/Timeline.js +3 -13
  54. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +26 -3
  55. package/dist/components/Timeline/TimelineClipboardKeybindings.js +242 -25
  56. package/dist/components/Timeline/TimelineDeleteKeybindings.js +23 -11
  57. package/dist/components/Timeline/TimelineEffectItem.js +8 -7
  58. package/dist/components/Timeline/TimelineEffectPropItem.js +69 -19
  59. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +6 -1
  60. package/dist/components/Timeline/TimelineExpandedSection.js +5 -5
  61. package/dist/components/Timeline/TimelineKeyframeControls.js +13 -23
  62. package/dist/components/Timeline/TimelineKeyframeDiamond.js +24 -22
  63. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.d.ts +6 -0
  64. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.js +14 -0
  65. package/dist/components/Timeline/TimelineKeyframeDragState.d.ts +17 -0
  66. package/dist/components/Timeline/TimelineKeyframeDragState.js +39 -0
  67. package/dist/components/Timeline/TimelineKeyframeEasingLine.d.ts +9 -0
  68. package/dist/components/Timeline/TimelineKeyframeEasingLine.js +120 -0
  69. package/dist/components/Timeline/TimelineKeyframedValue.js +1 -1
  70. package/dist/components/Timeline/TimelineList.js +2 -2
  71. package/dist/components/Timeline/TimelineMediaInfo.d.ts +0 -13
  72. package/dist/components/Timeline/TimelineMediaInfo.js +8 -73
  73. package/dist/components/Timeline/TimelineNumberField.js +15 -7
  74. package/dist/components/Timeline/TimelineRotationField.js +17 -11
  75. package/dist/components/Timeline/TimelineScaleField.js +17 -13
  76. package/dist/components/Timeline/TimelineSelection.d.ts +15 -0
  77. package/dist/components/Timeline/TimelineSelection.js +26 -1
  78. package/dist/components/Timeline/TimelineSequence.js +6 -6
  79. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -0
  80. package/dist/components/Timeline/TimelineSequenceItem.js +297 -36
  81. package/dist/components/Timeline/TimelineSequencePropItem.js +113 -48
  82. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +5 -5
  83. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +69 -70
  84. package/dist/components/Timeline/TimelineTranslateField.js +24 -19
  85. package/dist/components/Timeline/TimelineUvCoordinateField.js +18 -12
  86. package/dist/components/Timeline/apply-effect-response-to-prop-statuses.d.ts +5 -0
  87. package/dist/components/Timeline/apply-effect-response-to-prop-statuses.js +19 -0
  88. package/dist/components/Timeline/call-add-keyframe.d.ts +5 -5
  89. package/dist/components/Timeline/call-add-keyframe.js +6 -4
  90. package/dist/components/Timeline/call-delete-keyframe.d.ts +7 -7
  91. package/dist/components/Timeline/call-delete-keyframe.js +7 -7
  92. package/dist/components/Timeline/call-move-keyframe.d.ts +19 -0
  93. package/dist/components/Timeline/call-move-keyframe.js +71 -0
  94. package/dist/components/Timeline/call-update-keyframe-settings.d.ts +22 -0
  95. package/dist/components/Timeline/call-update-keyframe-settings.js +52 -0
  96. package/dist/components/Timeline/delete-selected-keyframe.d.ts +5 -5
  97. package/dist/components/Timeline/delete-selected-keyframe.js +5 -5
  98. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +10 -7
  99. package/dist/components/Timeline/delete-selected-timeline-item.js +37 -23
  100. package/dist/components/Timeline/duplicate-selected-timeline-item.d.ts +4 -2
  101. package/dist/components/Timeline/duplicate-selected-timeline-item.js +39 -34
  102. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.d.ts +8 -0
  103. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.js +12 -0
  104. package/dist/components/Timeline/get-keyframe-navigation.d.ts +2 -2
  105. package/dist/components/Timeline/get-keyframe-navigation.js +14 -6
  106. package/dist/components/Timeline/get-node-keyframes.d.ts +3 -3
  107. package/dist/components/Timeline/get-node-keyframes.js +4 -4
  108. package/dist/components/Timeline/get-timeline-easing-segments.d.ts +9 -0
  109. package/dist/components/Timeline/get-timeline-easing-segments.js +19 -0
  110. package/dist/components/Timeline/reset-selected-timeline-props.d.ts +7 -7
  111. package/dist/components/Timeline/reset-selected-timeline-props.js +13 -12
  112. package/dist/components/Timeline/save-effect-prop.d.ts +16 -5
  113. package/dist/components/Timeline/save-effect-prop.js +37 -19
  114. package/dist/components/Timeline/save-prop-queue.d.ts +4 -3
  115. package/dist/components/Timeline/save-prop-queue.js +6 -3
  116. package/dist/components/Timeline/save-sequence-prop.d.ts +5 -10
  117. package/dist/components/Timeline/save-sequence-prop.js +35 -32
  118. package/dist/components/Timeline/should-clear-selection-on-pointer-down.d.ts +3 -0
  119. package/dist/components/Timeline/should-clear-selection-on-pointer-down.js +7 -0
  120. package/dist/components/Timeline/timeline-asset-link.d.ts +13 -0
  121. package/dist/components/Timeline/timeline-asset-link.js +37 -0
  122. package/dist/components/Timeline/timeline-field-utils.d.ts +10 -0
  123. package/dist/components/Timeline/timeline-field-utils.js +26 -5
  124. package/dist/components/Timeline/timeline-translate-utils.d.ts +1 -1
  125. package/dist/components/Timeline/timeline-translate-utils.js +6 -4
  126. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +7 -7
  127. package/dist/components/Timeline/use-sequence-props-subscription.js +3 -3
  128. package/dist/components/Timeline/use-timeline-height.js +3 -3
  129. package/dist/components/Timeline/use-timeline-keyframe-drag.d.ts +10 -0
  130. package/dist/components/Timeline/use-timeline-keyframe-drag.js +380 -0
  131. package/dist/components/import-assets.d.ts +31 -0
  132. package/dist/components/import-assets.js +216 -17
  133. package/dist/components/load-canvas-content-from-url.d.ts +1 -0
  134. package/dist/components/load-canvas-content-from-url.js +9 -3
  135. package/dist/components/use-select-asset.d.ts +1 -0
  136. package/dist/components/use-select-asset.js +30 -0
  137. package/dist/error-overlay/error-origin.d.ts +3 -0
  138. package/dist/error-overlay/error-origin.js +42 -0
  139. package/dist/error-overlay/react-overlay/listen-to-runtime-errors.js +6 -2
  140. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +38 -0
  141. package/dist/error-overlay/remotion-overlay/ShortcutHint.js +1 -1
  142. package/dist/error-overlay/remotion-overlay/log-studio-error.d.ts +3 -0
  143. package/dist/error-overlay/remotion-overlay/log-studio-error.js +27 -0
  144. package/dist/esm/{chunk-48grt472.js → chunk-xjvc8qen.js} +21838 -18862
  145. package/dist/esm/internals.mjs +21838 -18862
  146. package/dist/esm/previewEntry.mjs +21127 -18127
  147. package/dist/esm/renderEntry.mjs +1 -1
  148. package/dist/helpers/get-asset-metadata.js +2 -2
  149. package/dist/helpers/get-preview-file-type.d.ts +2 -0
  150. package/dist/helpers/get-preview-file-type.js +33 -0
  151. package/dist/helpers/install-required-package.d.ts +1 -0
  152. package/dist/helpers/install-required-package.js +39 -0
  153. package/dist/helpers/remote-asset-drag.d.ts +4 -0
  154. package/dist/helpers/remote-asset-drag.js +73 -0
  155. package/dist/helpers/timeline-layout.d.ts +6 -6
  156. package/dist/helpers/timeline-layout.js +5 -5
  157. package/dist/helpers/use-asset-drag-events.d.ts +5 -2
  158. package/dist/helpers/use-asset-drag-events.js +13 -2
  159. package/dist/hot-middleware-client/client.js +6 -0
  160. package/dist/state/editor-outlines.d.ts +8 -0
  161. package/dist/state/editor-outlines.js +18 -0
  162. package/dist/state/modals.d.ts +16 -2
  163. package/package.json +10 -10
  164. package/dist/helpers/detect-file-type.d.ts +0 -69
  165. package/dist/helpers/detect-file-type.js +0 -278
@@ -4,27 +4,31 @@ exports.deleteSelectedTimelineItems = exports.deleteSelectedTimelineItem = void
4
4
  const call_api_1 = require("../call-api");
5
5
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
6
6
  const delete_selected_keyframe_1 = require("./delete-selected-keyframe");
7
- const confirmDeletingDuplicatedSequences = (nodePathInfos) => {
7
+ const confirmDeletingDuplicatedSequences = (nodePathInfos, confirm) => {
8
8
  const duplicatedNodePathInfos = nodePathInfos.filter((nodePathInfo) => nodePathInfo.numberOfSequencesWithThisNodePath > 1);
9
9
  if (duplicatedNodePathInfos.length === 0) {
10
- return true;
10
+ return Promise.resolve(true);
11
11
  }
12
12
  if (duplicatedNodePathInfos.length === 1) {
13
13
  const [nodePathInfo] = duplicatedNodePathInfos;
14
- const singleDuplicatedSequenceMessage = 'This sequence is programmatically duplicated ' +
15
- nodePathInfo.numberOfSequencesWithThisNodePath +
16
- ' times in the code. Deleting removes all instances. Continue?';
17
- // eslint-disable-next-line no-alert -- native confirm before deleting all instances of a duplicated sequence
18
- return window.confirm(singleDuplicatedSequenceMessage);
14
+ return confirm({
15
+ title: 'Delete sequence?',
16
+ message: 'This sequence is programmatically duplicated ' +
17
+ nodePathInfo.numberOfSequencesWithThisNodePath +
18
+ ' times in the code. Deleting removes all instances. Continue?',
19
+ confirmLabel: 'Delete',
20
+ });
19
21
  }
20
- const multipleDuplicatedSequencesMessage = duplicatedNodePathInfos.length +
21
- ' selected sequences are programmatically duplicated in the code. Deleting removes all instances. Continue?';
22
- // eslint-disable-next-line no-alert -- native confirm before deleting all instances of duplicated sequences
23
- return window.confirm(multipleDuplicatedSequencesMessage);
22
+ return confirm({
23
+ title: 'Delete sequences?',
24
+ message: duplicatedNodePathInfos.length +
25
+ ' selected sequences are programmatically duplicated in the code. Deleting removes all instances. Continue?',
26
+ confirmLabel: 'Delete',
27
+ });
24
28
  };
25
- const deleteSequences = (nodePathInfos) => {
26
- if (!confirmDeletingDuplicatedSequences(nodePathInfos)) {
27
- return Promise.resolve();
29
+ const deleteSequences = async (nodePathInfos, confirm) => {
30
+ if (!(await confirmDeletingDuplicatedSequences(nodePathInfos, confirm))) {
31
+ return false;
28
32
  }
29
33
  return (0, call_api_1.callApi)('/api/delete-jsx-node', {
30
34
  nodes: nodePathInfos.map((nodePathInfo) => {
@@ -44,14 +48,16 @@ const deleteSequences = (nodePathInfos) => {
44
48
  else {
45
49
  (0, NotificationCenter_1.showNotification)(result.reason, 4000);
46
50
  }
51
+ return true;
47
52
  })
48
53
  .catch((err) => {
49
54
  (0, NotificationCenter_1.showNotification)(err.message, 4000);
55
+ return true;
50
56
  });
51
57
  };
52
58
  const deleteEffects = (effects) => {
53
59
  if (effects.length === 0) {
54
- return Promise.resolve();
60
+ return Promise.resolve(false);
55
61
  }
56
62
  return (0, call_api_1.callApi)('/api/delete-effect', effects.map((effect) => {
57
63
  const nodePath = effect.nodePathInfo.sequenceSubscriptionKey;
@@ -80,25 +86,29 @@ const deleteEffects = (effects) => {
80
86
  else {
81
87
  (0, NotificationCenter_1.showNotification)(result.reason, 4000);
82
88
  }
89
+ return true;
83
90
  })
84
91
  .catch((err) => {
85
92
  (0, NotificationCenter_1.showNotification)(err.message, 4000);
93
+ return true;
86
94
  });
87
95
  };
88
- const deleteSelectedTimelineItem = ({ selection, sequences, overrideIdsToNodePaths, setCodeValues, clientId, }) => {
96
+ const deleteSelectedTimelineItem = ({ selection, sequences, overrideIdsToNodePaths, setPropStatuses, clientId, confirm, }) => {
97
+ var _a;
89
98
  if (selection.type === 'keyframe') {
90
- return (0, delete_selected_keyframe_1.deleteSelectedKeyframe)({
99
+ const promise = (0, delete_selected_keyframe_1.deleteSelectedKeyframe)({
91
100
  nodePathInfo: selection.nodePathInfo,
92
101
  frame: selection.frame,
93
102
  sequences,
94
103
  overrideIdsToNodePaths,
95
- setCodeValues,
104
+ setPropStatuses,
96
105
  clientId,
97
106
  });
107
+ return (_a = promise === null || promise === void 0 ? void 0 : promise.then(() => true)) !== null && _a !== void 0 ? _a : null;
98
108
  }
99
109
  switch (selection.type) {
100
110
  case 'sequence':
101
- return deleteSequences([selection.nodePathInfo]);
111
+ return deleteSequences([selection.nodePathInfo], confirm);
102
112
  case 'sequence-effect':
103
113
  return deleteEffects([
104
114
  {
@@ -109,6 +119,7 @@ const deleteSelectedTimelineItem = ({ selection, sequences, overrideIdsToNodePat
109
119
  ]);
110
120
  case 'sequence-prop':
111
121
  case 'sequence-effect-prop':
122
+ case 'easing':
112
123
  return null;
113
124
  case 'sequence-all-effects':
114
125
  return deleteEffects([
@@ -134,7 +145,8 @@ const assertTimelineSelectionsHaveSameType = (selections) => {
134
145
  }
135
146
  }
136
147
  };
137
- const deleteSelectedTimelineItems = ({ selections, sequences, overrideIdsToNodePaths, setCodeValues, clientId, }) => {
148
+ const deleteSelectedTimelineItems = ({ selections, sequences, overrideIdsToNodePaths, setPropStatuses, clientId, confirm, }) => {
149
+ var _a;
138
150
  const firstSelection = selections[0];
139
151
  if (!firstSelection) {
140
152
  return null;
@@ -144,7 +156,7 @@ const deleteSelectedTimelineItems = ({ selections, sequences, overrideIdsToNodeP
144
156
  case 'sequence':
145
157
  return deleteSequences(selections
146
158
  .filter(isSequenceRowSelection)
147
- .map((selection) => selection.nodePathInfo));
159
+ .map((selection) => selection.nodePathInfo), confirm);
148
160
  case 'sequence-effect':
149
161
  return deleteEffects(selections.filter(isSequenceEffectSelection).map((selection) => ({
150
162
  type: 'single-effect',
@@ -152,19 +164,21 @@ const deleteSelectedTimelineItems = ({ selections, sequences, overrideIdsToNodeP
152
164
  effectIndex: selection.i,
153
165
  })));
154
166
  case 'keyframe': {
155
- return (0, delete_selected_keyframe_1.deleteSelectedKeyframes)({
167
+ const promise = (0, delete_selected_keyframe_1.deleteSelectedKeyframes)({
156
168
  keyframes: selections.filter(isKeyframeSelection).map((selection) => ({
157
169
  nodePathInfo: selection.nodePathInfo,
158
170
  frame: selection.frame,
159
171
  })),
160
172
  sequences,
161
173
  overrideIdsToNodePaths,
162
- setCodeValues,
174
+ setPropStatuses,
163
175
  clientId,
164
176
  });
177
+ return (_a = promise === null || promise === void 0 ? void 0 : promise.then(() => true)) !== null && _a !== void 0 ? _a : null;
165
178
  }
166
179
  case 'sequence-prop':
167
180
  case 'sequence-effect-prop':
181
+ case 'easing':
168
182
  return null;
169
183
  case 'sequence-all-effects':
170
184
  return deleteEffects(selections.filter(isSequenceAllEffectsSelection).map((selection) => ({
@@ -1,6 +1,7 @@
1
1
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
2
+ import type { ConfirmationDialogFunction } from '../ConfirmationDialog-types';
2
3
  import type { TimelineSelection } from './TimelineSelection';
3
- export declare const duplicateSequencesFromSource: (nodePathInfos: readonly SequenceNodePathInfo[]) => Promise<void>;
4
+ export declare const duplicateSequencesFromSource: (nodePathInfos: readonly SequenceNodePathInfo[], confirm: ConfirmationDialogFunction) => Promise<void>;
4
5
  export declare const isDuplicatableSequenceRowSelection: (selection: TimelineSelection) => selection is {
5
6
  readonly nodePathInfo: SequenceNodePathInfo;
6
7
  } & {
@@ -8,6 +9,7 @@ export declare const isDuplicatableSequenceRowSelection: (selection: TimelineSel
8
9
  } & {
9
10
  type: "sequence";
10
11
  };
11
- export declare const duplicateSelectedTimelineItems: ({ selections, }: {
12
+ export declare const duplicateSelectedTimelineItems: ({ selections, confirm, }: {
12
13
  selections: readonly TimelineSelection[];
14
+ confirm: ConfirmationDialogFunction;
13
15
  }) => Promise<void> | null;
@@ -3,22 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.duplicateSelectedTimelineItems = exports.isDuplicatableSequenceRowSelection = exports.duplicateSequencesFromSource = void 0;
4
4
  const call_api_1 = require("../call-api");
5
5
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
6
- const confirmDuplicatingProgrammaticallyDuplicatedSequences = (nodePathInfos) => {
6
+ const confirmDuplicatingProgrammaticallyDuplicatedSequences = (nodePathInfos, confirm) => {
7
7
  if (nodePathInfos.length === 0) {
8
- return true;
8
+ return Promise.resolve(true);
9
9
  }
10
10
  if (nodePathInfos.length === 1) {
11
11
  const [nodePathInfo] = nodePathInfos;
12
- const singleDuplicatedSequenceMessage = 'This sequence is programmatically duplicated ' +
13
- nodePathInfo.numberOfSequencesWithThisNodePath +
14
- ' times in the code. Duplicating inserts another copy. Continue?';
15
- // eslint-disable-next-line no-alert -- native confirm before applying duplicate codemod in .map callbacks
16
- return window.confirm(singleDuplicatedSequenceMessage);
12
+ return confirm({
13
+ title: 'Duplicate sequence?',
14
+ message: 'This sequence is programmatically duplicated ' +
15
+ nodePathInfo.numberOfSequencesWithThisNodePath +
16
+ ' times in the code. Duplicating inserts another copy. Continue?',
17
+ confirmLabel: 'Duplicate',
18
+ });
17
19
  }
18
- const multipleDuplicatedSequencesMessage = nodePathInfos.length +
19
- ' selected sequences are programmatically duplicated in the code. Duplicating inserts another copy of each. Continue?';
20
- // eslint-disable-next-line no-alert -- native confirm before applying duplicate codemod in .map callbacks
21
- return window.confirm(multipleDuplicatedSequencesMessage);
20
+ return confirm({
21
+ title: 'Duplicate sequences?',
22
+ message: nodePathInfos.length +
23
+ ' selected sequences are programmatically duplicated in the code. Duplicating inserts another copy of each. Continue?',
24
+ confirmLabel: 'Duplicate',
25
+ });
22
26
  };
23
27
  const duplicateSequence = (nodePathInfo) => {
24
28
  const nodePath = nodePathInfo.sequenceSubscriptionKey;
@@ -27,40 +31,41 @@ const duplicateSequence = (nodePathInfo) => {
27
31
  nodePath: nodePath.nodePath,
28
32
  });
29
33
  };
30
- const duplicateSequencesFromSource = (nodePathInfos) => {
34
+ const duplicateSequencesFromSource = (nodePathInfos, confirm) => {
31
35
  const programmaticallyDuplicated = nodePathInfos.filter((nodePathInfo) => nodePathInfo.numberOfSequencesWithThisNodePath > 1);
32
36
  const regular = nodePathInfos.filter((nodePathInfo) => nodePathInfo.numberOfSequencesWithThisNodePath <= 1);
33
- const toDuplicate = [...regular];
34
- if (programmaticallyDuplicated.length === 0 ||
35
- confirmDuplicatingProgrammaticallyDuplicatedSequences(programmaticallyDuplicated)) {
36
- toDuplicate.push(...programmaticallyDuplicated);
37
- }
38
- if (toDuplicate.length === 0) {
39
- return Promise.resolve();
40
- }
41
- return Promise.all(toDuplicate.map(duplicateSequence))
42
- .then((results) => {
43
- const failedResult = results.find((result) => !result.success);
44
- if (failedResult && !failedResult.success) {
45
- (0, NotificationCenter_1.showNotification)(failedResult.reason, 4000);
46
- return;
37
+ return confirmDuplicatingProgrammaticallyDuplicatedSequences(programmaticallyDuplicated, confirm).then((shouldDuplicateProgrammaticSequences) => {
38
+ const toDuplicate = [...regular];
39
+ if (shouldDuplicateProgrammaticSequences) {
40
+ toDuplicate.push(...programmaticallyDuplicated);
41
+ }
42
+ if (toDuplicate.length === 0) {
43
+ return Promise.resolve();
47
44
  }
48
- (0, NotificationCenter_1.showNotification)(toDuplicate.length === 1
49
- ? 'Duplicated sequence in source file'
50
- : 'Duplicated sequences in source files', 2000);
51
- })
52
- .catch((err) => {
53
- (0, NotificationCenter_1.showNotification)(err.message, 4000);
45
+ return Promise.all(toDuplicate.map(duplicateSequence))
46
+ .then((results) => {
47
+ const failedResult = results.find((result) => !result.success);
48
+ if (failedResult && !failedResult.success) {
49
+ (0, NotificationCenter_1.showNotification)(failedResult.reason, 4000);
50
+ return;
51
+ }
52
+ (0, NotificationCenter_1.showNotification)(toDuplicate.length === 1
53
+ ? 'Duplicated sequence in source file'
54
+ : 'Duplicated sequences in source files', 2000);
55
+ })
56
+ .catch((err) => {
57
+ (0, NotificationCenter_1.showNotification)(err.message, 4000);
58
+ });
54
59
  });
55
60
  };
56
61
  exports.duplicateSequencesFromSource = duplicateSequencesFromSource;
57
62
  const isDuplicatableSequenceRowSelection = (selection) => selection.type === 'sequence';
58
63
  exports.isDuplicatableSequenceRowSelection = isDuplicatableSequenceRowSelection;
59
- const duplicateSelectedTimelineItems = ({ selections, }) => {
64
+ const duplicateSelectedTimelineItems = ({ selections, confirm, }) => {
60
65
  const sequenceSelections = selections.filter(exports.isDuplicatableSequenceRowSelection);
61
66
  if (sequenceSelections.length === 0) {
62
67
  return null;
63
68
  }
64
- return (0, exports.duplicateSequencesFromSource)(sequenceSelections.map((selection) => selection.nodePathInfo));
69
+ return (0, exports.duplicateSequencesFromSource)(sequenceSelections.map((selection) => selection.nodePathInfo), confirm);
65
70
  };
66
71
  exports.duplicateSelectedTimelineItems = duplicateSelectedTimelineItems;
@@ -0,0 +1,8 @@
1
+ export type TimelineKeyframeDragBoundsTarget = {
2
+ readonly displayFrame: number;
3
+ };
4
+ export declare const getBoundedKeyframeDragDelta: ({ delta, durationInFrames, targets, }: {
5
+ readonly delta: number;
6
+ readonly durationInFrames: number;
7
+ readonly targets: readonly TimelineKeyframeDragBoundsTarget[];
8
+ }) => number;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getBoundedKeyframeDragDelta = void 0;
4
+ const getBoundedKeyframeDragDelta = ({ delta, durationInFrames, targets, }) => {
5
+ if (targets.length === 0 || durationInFrames <= 0) {
6
+ return 0;
7
+ }
8
+ const minDelta = Math.max(...targets.map((target) => -target.displayFrame));
9
+ const maxDelta = Math.min(...targets.map((target) => durationInFrames - 1 - target.displayFrame));
10
+ return Math.min(Math.max(delta, minDelta), maxDelta);
11
+ };
12
+ exports.getBoundedKeyframeDragDelta = getBoundedKeyframeDragDelta;
@@ -1,9 +1,9 @@
1
1
  export declare const getPreviousKeyframeDisplayFrame: (keyframes: readonly {
2
2
  frame: number;
3
- }[], currentDisplayFrame: number) => number | null;
3
+ }[], currentDisplayFrame: number, durationInFrames: number) => number | null;
4
4
  export declare const getNextKeyframeDisplayFrame: (keyframes: readonly {
5
5
  frame: number;
6
- }[], currentDisplayFrame: number) => number | null;
6
+ }[], currentDisplayFrame: number, durationInFrames: number) => number | null;
7
7
  export declare const hasKeyframeAtSourceFrame: (keyframes: readonly {
8
8
  frame: number;
9
9
  }[], sourceFrame: number) => boolean;
@@ -1,23 +1,31 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.hasKeyframeAtSourceFrame = exports.getNextKeyframeDisplayFrame = exports.getPreviousKeyframeDisplayFrame = void 0;
4
- const getPreviousKeyframeDisplayFrame = (keyframes, currentDisplayFrame) => {
4
+ const isKeyframeInTimelineRange = (frame, durationInFrames) => {
5
+ return frame >= 0 && frame < durationInFrames;
6
+ };
7
+ const getPreviousKeyframeDisplayFrame = (keyframes, currentDisplayFrame, durationInFrames) => {
5
8
  let previous = null;
6
9
  for (const keyframe of keyframes) {
7
- if (keyframe.frame < currentDisplayFrame) {
10
+ if (isKeyframeInTimelineRange(keyframe.frame, durationInFrames) &&
11
+ keyframe.frame < currentDisplayFrame &&
12
+ (previous === null || keyframe.frame > previous)) {
8
13
  previous = keyframe.frame;
9
14
  }
10
15
  }
11
16
  return previous;
12
17
  };
13
18
  exports.getPreviousKeyframeDisplayFrame = getPreviousKeyframeDisplayFrame;
14
- const getNextKeyframeDisplayFrame = (keyframes, currentDisplayFrame) => {
19
+ const getNextKeyframeDisplayFrame = (keyframes, currentDisplayFrame, durationInFrames) => {
20
+ let next = null;
15
21
  for (const keyframe of keyframes) {
16
- if (keyframe.frame > currentDisplayFrame) {
17
- return keyframe.frame;
22
+ if (isKeyframeInTimelineRange(keyframe.frame, durationInFrames) &&
23
+ keyframe.frame > currentDisplayFrame &&
24
+ (next === null || keyframe.frame < next)) {
25
+ next = keyframe.frame;
18
26
  }
19
27
  }
20
- return null;
28
+ return next;
21
29
  };
22
30
  exports.getNextKeyframeDisplayFrame = getNextKeyframeDisplayFrame;
23
31
  const hasKeyframeAtSourceFrame = (keyframes, sourceFrame) => {
@@ -1,9 +1,9 @@
1
- import { type CodeValues, type GetDragOverrides, type GetEffectDragOverrides, type SequencePropsSubscriptionKey } from 'remotion';
1
+ import { type GetDragOverrides, type GetEffectDragOverrides, type PropStatuses, type SequencePropsSubscriptionKey } from 'remotion';
2
2
  import type { TimelineTreeNode } from '../../helpers/timeline-layout';
3
- export declare const getNodeKeyframes: ({ node, nodePath, codeValues, keyframeDisplayOffset, getDragOverrides, getEffectDragOverrides, timelinePosition, }: {
3
+ export declare const getNodeKeyframes: ({ node, nodePath, propStatuses, keyframeDisplayOffset, getDragOverrides, getEffectDragOverrides, timelinePosition, }: {
4
4
  node: TimelineTreeNode;
5
5
  nodePath: SequencePropsSubscriptionKey;
6
- codeValues: CodeValues;
6
+ propStatuses: PropStatuses;
7
7
  keyframeDisplayOffset: number;
8
8
  getDragOverrides: GetDragOverrides;
9
9
  getEffectDragOverrides: GetEffectDragOverrides;
@@ -22,7 +22,7 @@ const withDragOverrideKeyframe = ({ propStatus, keyframeDisplayOffset, timelineP
22
22
  }
23
23
  return [...keyframes, dragKeyframe].sort((first, second) => first.frame - second.frame);
24
24
  };
25
- const getNodeKeyframes = ({ node, nodePath, codeValues, keyframeDisplayOffset, getDragOverrides, getEffectDragOverrides, timelinePosition, }) => {
25
+ const getNodeKeyframes = ({ node, nodePath, propStatuses, keyframeDisplayOffset, getDragOverrides, getEffectDragOverrides, timelinePosition, }) => {
26
26
  var _a, _b;
27
27
  if (node.kind !== 'field' || node.field === null) {
28
28
  return [];
@@ -30,15 +30,15 @@ const getNodeKeyframes = ({ node, nodePath, codeValues, keyframeDisplayOffset, g
30
30
  if (node.field.kind === 'sequence-field') {
31
31
  const dragOverrides = getDragOverrides(nodePath);
32
32
  return withDragOverrideKeyframe({
33
- propStatus: (_a = remotion_1.Internals.getCodeValuesCtx(codeValues, nodePath)) === null || _a === void 0 ? void 0 : _a[node.field.key],
33
+ propStatus: (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a[node.field.key],
34
34
  keyframeDisplayOffset,
35
35
  timelinePosition,
36
36
  dragOverrideValue: dragOverrides[node.field.key],
37
37
  hasDragOverride: hasOverride(dragOverrides, node.field.key),
38
38
  });
39
39
  }
40
- const effectStatus = remotion_1.Internals.getEffectCodeValuesCtx({
41
- codeValues,
40
+ const effectStatus = remotion_1.Internals.getEffectPropStatusesCtx({
41
+ propStatuses,
42
42
  nodePath,
43
43
  effectIndex: node.field.effectIndex,
44
44
  });
@@ -0,0 +1,9 @@
1
+ export type TimelineEasingSegment = {
2
+ readonly fromFrame: number;
3
+ readonly toFrame: number;
4
+ readonly segmentIndex: number;
5
+ };
6
+ export declare const getTimelineEasingSegments: (keyframes: {
7
+ frame: number;
8
+ value: unknown;
9
+ }[]) => TimelineEasingSegment[];
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTimelineEasingSegments = void 0;
4
+ const getTimelineEasingSegments = (keyframes) => {
5
+ return keyframes.flatMap((keyframe, index) => {
6
+ const nextKeyframe = keyframes[index + 1];
7
+ if (!nextKeyframe) {
8
+ return [];
9
+ }
10
+ return [
11
+ {
12
+ fromFrame: keyframe.frame,
13
+ toFrame: nextKeyframe.frame,
14
+ segmentIndex: index,
15
+ },
16
+ ];
17
+ });
18
+ };
19
+ exports.getTimelineEasingSegments = getTimelineEasingSegments;
@@ -1,5 +1,5 @@
1
- import type { CodeValues, OverrideIdToNodePaths, SequencePropsSubscriptionKey, SequenceSchema, TSequence } from 'remotion';
2
- import type { SetCodeValues } from './save-sequence-prop';
1
+ import type { OverrideIdToNodePaths, PropStatuses, SequencePropsSubscriptionKey, SequenceSchema, TSequence } from 'remotion';
2
+ import type { SetPropStatuses } from './save-sequence-prop';
3
3
  import type { TimelineSelection } from './TimelineSelection';
4
4
  type SequencePropResetTarget = {
5
5
  readonly type: 'sequence-prop';
@@ -21,18 +21,18 @@ type EffectPropResetTarget = {
21
21
  readonly schema: SequenceSchema;
22
22
  };
23
23
  type TimelinePropResetTarget = SequencePropResetTarget | EffectPropResetTarget;
24
- export declare const getTimelinePropResetTargets: ({ selections, sequences, overrideIdsToNodePaths, codeValues, }: {
24
+ export declare const getTimelinePropResetTargets: ({ selections, sequences, overrideIdsToNodePaths, propStatuses, }: {
25
25
  readonly selections: readonly TimelineSelection[];
26
26
  readonly sequences: TSequence[];
27
27
  readonly overrideIdsToNodePaths: OverrideIdToNodePaths;
28
- readonly codeValues: CodeValues;
28
+ readonly propStatuses: PropStatuses;
29
29
  }) => TimelinePropResetTarget[] | null;
30
- export declare const resetSelectedTimelineProps: ({ selections, sequences, overrideIdsToNodePaths, codeValues, setCodeValues, clientId, }: {
30
+ export declare const resetSelectedTimelineProps: ({ selections, sequences, overrideIdsToNodePaths, propStatuses, setPropStatuses, clientId, }: {
31
31
  readonly selections: readonly TimelineSelection[];
32
32
  readonly sequences: TSequence[];
33
33
  readonly overrideIdsToNodePaths: OverrideIdToNodePaths;
34
- readonly codeValues: CodeValues;
35
- readonly setCodeValues: SetCodeValues;
34
+ readonly propStatuses: PropStatuses;
35
+ readonly setPropStatuses: SetPropStatuses;
36
36
  readonly clientId: string;
37
37
  }) => Promise<void> | null;
38
38
  export {};
@@ -8,7 +8,7 @@ const save_sequence_prop_1 = require("./save-sequence-prop");
8
8
  const isPropResetSelection = (selection) => selection.type === 'sequence-prop' ||
9
9
  selection.type === 'sequence-effect-prop';
10
10
  const isVisibleFieldSchema = (fieldSchema) => fieldSchema !== undefined && fieldSchema.type !== 'hidden';
11
- const isNonDefaultCodeValue = ({ codeValue, defaultValue, }) => JSON.stringify(codeValue !== null && codeValue !== void 0 ? codeValue : defaultValue) !== JSON.stringify(defaultValue);
11
+ const isNonDefaultCodeValue = ({ propStatus, defaultValue, }) => JSON.stringify(propStatus !== null && propStatus !== void 0 ? propStatus : defaultValue) !== JSON.stringify(defaultValue);
12
12
  const isResettablePropStatus = ({ propStatus, defaultValue, }) => {
13
13
  if (!propStatus || propStatus.status === 'computed') {
14
14
  return false;
@@ -20,14 +20,14 @@ const isResettablePropStatus = ({ propStatus, defaultValue, }) => {
20
20
  return true;
21
21
  }
22
22
  return isNonDefaultCodeValue({
23
- codeValue: propStatus.codeValue,
23
+ propStatus: propStatus.codeValue,
24
24
  defaultValue,
25
25
  });
26
26
  };
27
27
  const getDefaultValue = (fieldSchema) => fieldSchema.default !== undefined
28
28
  ? JSON.stringify(fieldSchema.default)
29
29
  : null;
30
- const getTimelinePropResetTargets = ({ selections, sequences, overrideIdsToNodePaths, codeValues, }) => {
30
+ const getTimelinePropResetTargets = ({ selections, sequences, overrideIdsToNodePaths, propStatuses, }) => {
31
31
  var _a;
32
32
  var _b;
33
33
  const firstSelection = selections[0];
@@ -54,7 +54,7 @@ const getTimelinePropResetTargets = ({ selections, sequences, overrideIdsToNodeP
54
54
  continue;
55
55
  }
56
56
  const sequenceFieldSchema = sequence.controls.schema[selection.key];
57
- const sequencePropStatus = (_a = remotion_1.Internals.getCodeValuesCtx(codeValues, nodePath)) === null || _a === void 0 ? void 0 : _a[selection.key];
57
+ const sequencePropStatus = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a[selection.key];
58
58
  if (!isVisibleFieldSchema(sequenceFieldSchema) ||
59
59
  !isResettablePropStatus({
60
60
  propStatus: sequencePropStatus,
@@ -75,8 +75,8 @@ const getTimelinePropResetTargets = ({ selections, sequences, overrideIdsToNodeP
75
75
  }
76
76
  const effect = sequence.effects[selection.i];
77
77
  const fieldSchema = effect === null || effect === void 0 ? void 0 : effect.schema[selection.key];
78
- const effectStatus = remotion_1.Internals.getEffectCodeValuesCtx({
79
- codeValues,
78
+ const effectStatus = remotion_1.Internals.getEffectPropStatusesCtx({
79
+ propStatuses,
80
80
  nodePath,
81
81
  effectIndex: selection.i,
82
82
  });
@@ -105,12 +105,12 @@ const getTimelinePropResetTargets = ({ selections, sequences, overrideIdsToNodeP
105
105
  return resetTargets;
106
106
  };
107
107
  exports.getTimelinePropResetTargets = getTimelinePropResetTargets;
108
- const resetSelectedTimelineProps = ({ selections, sequences, overrideIdsToNodePaths, codeValues, setCodeValues, clientId, }) => {
108
+ const resetSelectedTimelineProps = ({ selections, sequences, overrideIdsToNodePaths, propStatuses, setPropStatuses, clientId, }) => {
109
109
  const resetTargets = (0, exports.getTimelinePropResetTargets)({
110
110
  selections,
111
111
  sequences,
112
112
  overrideIdsToNodePaths,
113
- codeValues,
113
+ propStatuses,
114
114
  });
115
115
  if (resetTargets === null || resetTargets.length === 0) {
116
116
  return null;
@@ -128,18 +128,19 @@ const resetSelectedTimelineProps = ({ selections, sequences, overrideIdsToNodePa
128
128
  defaultValue: target.defaultValue,
129
129
  schema: target.schema,
130
130
  })),
131
- setCodeValues,
131
+ setPropStatuses,
132
132
  clientId,
133
133
  undoLabel: sequencePropTargets.length > 1
134
134
  ? 'Reset selected sequence props'
135
- : null,
135
+ : 'Reset sequence prop',
136
136
  redoLabel: sequencePropTargets.length > 1
137
137
  ? 'Reapply selected sequence props'
138
- : null,
138
+ : 'Reapply sequence prop',
139
139
  }));
140
140
  }
141
141
  for (const target of effectPropTargets) {
142
142
  resetPromises.push((0, save_effect_prop_1.saveEffectProp)({
143
+ type: 'value',
143
144
  fileName: target.fileName,
144
145
  nodePath: target.nodePath,
145
146
  effectIndex: target.effectIndex,
@@ -147,7 +148,7 @@ const resetSelectedTimelineProps = ({ selections, sequences, overrideIdsToNodePa
147
148
  value: target.value,
148
149
  defaultValue: target.defaultValue,
149
150
  schema: target.schema,
150
- setCodeValues,
151
+ setPropStatuses,
151
152
  clientId,
152
153
  }));
153
154
  }
@@ -1,13 +1,24 @@
1
+ import { type EffectClipboardParam } from '@remotion/studio-shared';
1
2
  import type { SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
2
- import type { SetCodeValues } from './save-sequence-prop';
3
- export declare const saveEffectProp: ({ fileName, nodePath, effectIndex, fieldKey, value, defaultValue, schema, setCodeValues, clientId, }: {
3
+ import type { SetPropStatuses } from './save-sequence-prop';
4
+ type SaveEffectPropBase = {
4
5
  fileName: string;
5
6
  nodePath: SequencePropsSubscriptionKey;
6
7
  effectIndex: number;
7
8
  fieldKey: string;
8
- value: unknown;
9
9
  defaultValue: string | null;
10
10
  schema: SequenceSchema;
11
- setCodeValues: SetCodeValues;
11
+ setPropStatuses: SetPropStatuses;
12
12
  clientId: string;
13
- }) => Promise<void>;
13
+ };
14
+ type SaveEffectPropValue = SaveEffectPropBase & {
15
+ type: 'value';
16
+ value: unknown;
17
+ };
18
+ type SaveEffectPropEffectParam = SaveEffectPropBase & {
19
+ type: 'effect-param';
20
+ effectParam: EffectClipboardParam;
21
+ };
22
+ type SaveEffectPropInput = SaveEffectPropValue | SaveEffectPropEffectParam;
23
+ export declare const saveEffectProp: (input: SaveEffectPropInput) => Promise<void>;
24
+ export {};
@@ -3,28 +3,46 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.saveEffectProp = void 0;
4
4
  const studio_shared_1 = require("@remotion/studio-shared");
5
5
  const call_api_1 = require("../call-api");
6
+ const apply_effect_response_to_prop_statuses_1 = require("./apply-effect-response-to-prop-statuses");
6
7
  const save_prop_queue_1 = require("./save-prop-queue");
7
- const saveEffectProp = ({ fileName, nodePath, effectIndex, fieldKey, value, defaultValue, schema, setCodeValues, clientId, }) => {
8
+ const saveEffectProp = (input) => {
9
+ const { fileName, nodePath, effectIndex, fieldKey, defaultValue, schema, setPropStatuses, clientId, } = input;
8
10
  return (0, save_prop_queue_1.enqueueSavePropChange)({
9
11
  nodePath,
10
- setCodeValues,
11
- applyOptimistic: (prev) => (0, studio_shared_1.optimisticUpdateForEffectCodeValues)({
12
- previous: prev,
13
- effectIndex,
14
- fieldKey,
15
- value,
16
- schema,
17
- }),
18
- apiCall: () => (0, call_api_1.callApi)('/api/save-effect-props', {
19
- fileName,
20
- sequenceNodePath: nodePath,
21
- effectIndex,
22
- key: fieldKey,
23
- value: JSON.stringify(value),
24
- defaultValue,
25
- schema,
26
- clientId,
27
- }),
12
+ setPropStatuses,
13
+ applyOptimistic: (prev) => input.type === 'effect-param'
14
+ ? prev
15
+ : (0, studio_shared_1.optimisticUpdateForEffectPropStatuses)({
16
+ previous: prev,
17
+ effectIndex,
18
+ fieldKey,
19
+ value: input.value,
20
+ schema,
21
+ }),
22
+ applyServerResponse: (prev, response) => (0, apply_effect_response_to_prop_statuses_1.applyEffectResponseToPropStatuses)({ previous: prev, response }),
23
+ apiCall: () => (0, call_api_1.callApi)('/api/save-effect-props', input.type === 'effect-param'
24
+ ? {
25
+ type: 'effect-param',
26
+ fileName,
27
+ sequenceNodePath: nodePath,
28
+ effectIndex,
29
+ key: fieldKey,
30
+ effectParam: input.effectParam,
31
+ defaultValue,
32
+ schema,
33
+ clientId,
34
+ }
35
+ : {
36
+ type: 'value',
37
+ fileName,
38
+ sequenceNodePath: nodePath,
39
+ effectIndex,
40
+ key: fieldKey,
41
+ value: JSON.stringify(input.value),
42
+ defaultValue,
43
+ schema,
44
+ clientId,
45
+ }),
28
46
  errorLabel: 'Could not save effect prop',
29
47
  });
30
48
  };