@remotion/studio 4.0.471 → 4.0.473

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 (192) 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 +55 -5
  4. package/dist/components/AssetSelectorItem.js +153 -27
  5. package/dist/components/Canvas.js +147 -0
  6. package/dist/components/CompositionSelectorItem.d.ts +1 -0
  7. package/dist/components/CompositionSelectorItem.js +12 -4
  8. package/dist/components/ConfirmationDialog-types.d.ts +8 -0
  9. package/dist/components/ConfirmationDialog-types.js +2 -0
  10. package/dist/components/ConfirmationDialog.d.ts +7 -0
  11. package/dist/components/ConfirmationDialog.js +103 -0
  12. package/dist/components/ContextMenu.d.ts +9 -1
  13. package/dist/components/ContextMenu.js +99 -47
  14. package/dist/components/CurrentAsset.d.ts +1 -0
  15. package/dist/components/CurrentAsset.js +13 -2
  16. package/dist/components/Editor.js +14 -6
  17. package/dist/components/EditorContent.js +15 -2
  18. package/dist/components/EditorContexts.js +2 -1
  19. package/dist/components/EditorRuler/Ruler.js +2 -0
  20. package/dist/components/ExplorerPanel.d.ts +0 -4
  21. package/dist/components/ExplorerPanel.js +8 -4
  22. package/dist/components/ExplorerPanelRef.d.ts +4 -0
  23. package/dist/components/ExplorerPanelRef.js +5 -0
  24. package/dist/components/FilePreview.d.ts +1 -1
  25. package/dist/components/InitialCompositionLoader.d.ts +0 -1
  26. package/dist/components/InitialCompositionLoader.js +5 -27
  27. package/dist/components/Menu/MenuItem.js +7 -1
  28. package/dist/components/Menu/SubMenu.js +5 -1
  29. package/dist/components/Menu/portals.js +17 -8
  30. package/dist/components/MenuToolbar.js +5 -1
  31. package/dist/components/ModalContainer.js +6 -1
  32. package/dist/components/Modals.js +8 -2
  33. package/dist/components/NewComposition/CodemodFooter.js +2 -2
  34. package/dist/components/NewComposition/ComboBox.js +8 -2
  35. package/dist/components/NewComposition/DeleteFolder.d.ts +6 -0
  36. package/dist/components/NewComposition/DeleteFolder.js +39 -0
  37. package/dist/components/NewComposition/DeleteStaticFile.d.ts +4 -0
  38. package/dist/components/NewComposition/DeleteStaticFile.js +44 -0
  39. package/dist/components/NewComposition/RenameFolder.d.ts +6 -0
  40. package/dist/components/NewComposition/RenameFolder.js +60 -0
  41. package/dist/components/NewComposition/RenameStaticFile.d.ts +4 -0
  42. package/dist/components/NewComposition/RenameStaticFile.js +118 -0
  43. package/dist/components/OptionsPanel.js +5 -1
  44. package/dist/components/OutlineToggle.d.ts +2 -0
  45. package/dist/components/OutlineToggle.js +20 -0
  46. package/dist/components/Preview.d.ts +0 -2
  47. package/dist/components/Preview.js +23 -33
  48. package/dist/components/PreviewToolbar.js +19 -6
  49. package/dist/components/RenderButton.js +8 -2
  50. package/dist/components/RenderPreview.js +2 -2
  51. package/dist/components/SelectedOutlineOverlay.d.ts +105 -4
  52. package/dist/components/SelectedOutlineOverlay.js +578 -59
  53. package/dist/components/ShowOutlinesProvider.d.ts +4 -0
  54. package/dist/components/ShowOutlinesProvider.js +24 -0
  55. package/dist/components/SizeSelector.js +3 -3
  56. package/dist/components/Splitter/SplitterContainer.js +9 -0
  57. package/dist/components/Splitter/SplitterHandle.js +65 -70
  58. package/dist/components/StaticFilePreview.js +2 -2
  59. package/dist/components/Timeline/KeyframeSettingsModal.d.ts +15 -0
  60. package/dist/components/Timeline/KeyframeSettingsModal.js +150 -0
  61. package/dist/components/Timeline/Timeline.js +50 -15
  62. package/dist/components/Timeline/TimelineArrayField.d.ts +9 -0
  63. package/dist/components/Timeline/TimelineArrayField.js +210 -0
  64. package/dist/components/Timeline/TimelineBooleanField.d.ts +2 -2
  65. package/dist/components/Timeline/TimelineBooleanField.js +2 -2
  66. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +43 -0
  67. package/dist/components/Timeline/TimelineClipboardKeybindings.js +479 -0
  68. package/dist/components/Timeline/TimelineColorField.d.ts +2 -2
  69. package/dist/components/Timeline/TimelineColorField.js +2 -8
  70. package/dist/components/Timeline/TimelineDeleteKeybindings.js +12 -2
  71. package/dist/components/Timeline/TimelineEffectItem.js +3 -2
  72. package/dist/components/Timeline/TimelineEffectPropItem.js +146 -26
  73. package/dist/components/Timeline/TimelineEnumField.d.ts +2 -2
  74. package/dist/components/Timeline/TimelineEnumField.js +3 -3
  75. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +4 -3
  76. package/dist/components/Timeline/TimelineKeyframeControls.js +41 -37
  77. package/dist/components/Timeline/TimelineKeyframeDiamond.js +24 -21
  78. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.d.ts +6 -0
  79. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.js +14 -0
  80. package/dist/components/Timeline/TimelineKeyframeDragState.d.ts +17 -0
  81. package/dist/components/Timeline/TimelineKeyframeDragState.js +39 -0
  82. package/dist/components/Timeline/TimelineKeyframedValue.d.ts +7 -2
  83. package/dist/components/Timeline/TimelineKeyframedValue.js +22 -8
  84. package/dist/components/Timeline/TimelineLayerEye.d.ts +1 -0
  85. package/dist/components/Timeline/TimelineLayerEye.js +8 -3
  86. package/dist/components/Timeline/TimelineList.js +2 -2
  87. package/dist/components/Timeline/TimelineMediaInfo.d.ts +0 -13
  88. package/dist/components/Timeline/TimelineMediaInfo.js +8 -73
  89. package/dist/components/Timeline/TimelineNumberField.d.ts +2 -2
  90. package/dist/components/Timeline/TimelineNumberField.js +7 -11
  91. package/dist/components/Timeline/TimelinePrimitiveFieldValue.d.ts +17 -0
  92. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +53 -0
  93. package/dist/components/Timeline/TimelineRotationField.d.ts +2 -2
  94. package/dist/components/Timeline/TimelineRotationField.js +41 -24
  95. package/dist/components/Timeline/TimelineRowChrome.js +8 -7
  96. package/dist/components/Timeline/TimelineScaleField.d.ts +20 -0
  97. package/dist/components/Timeline/TimelineScaleField.js +314 -0
  98. package/dist/components/Timeline/TimelineSchemaField.d.ts +3 -2
  99. package/dist/components/Timeline/TimelineSchemaField.js +8 -42
  100. package/dist/components/Timeline/TimelineSelection.js +3 -2
  101. package/dist/components/Timeline/TimelineSequence.d.ts +1 -0
  102. package/dist/components/Timeline/TimelineSequence.js +51 -10
  103. package/dist/components/Timeline/TimelineSequenceFrame.js +1 -0
  104. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -0
  105. package/dist/components/Timeline/TimelineSequenceItem.js +282 -28
  106. package/dist/components/Timeline/TimelineSequencePropItem.js +161 -35
  107. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +58 -0
  108. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +525 -0
  109. package/dist/components/Timeline/TimelineTrack.js +1 -1
  110. package/dist/components/Timeline/TimelineTranslateField.d.ts +2 -2
  111. package/dist/components/Timeline/TimelineTranslateField.js +21 -25
  112. package/dist/components/Timeline/TimelineUvCoordinateField.d.ts +2 -2
  113. package/dist/components/Timeline/TimelineUvCoordinateField.js +20 -26
  114. package/dist/components/Timeline/apply-effect-response-to-code-values.d.ts +5 -0
  115. package/dist/components/Timeline/apply-effect-response-to-code-values.js +19 -0
  116. package/dist/components/Timeline/call-add-keyframe.js +4 -0
  117. package/dist/components/Timeline/call-move-keyframe.d.ts +19 -0
  118. package/dist/components/Timeline/call-move-keyframe.js +71 -0
  119. package/dist/components/Timeline/call-update-keyframe-settings.d.ts +22 -0
  120. package/dist/components/Timeline/call-update-keyframe-settings.js +52 -0
  121. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +7 -4
  122. package/dist/components/Timeline/delete-selected-timeline-item.js +33 -21
  123. package/dist/components/Timeline/duplicate-selected-timeline-item.d.ts +4 -2
  124. package/dist/components/Timeline/duplicate-selected-timeline-item.js +39 -34
  125. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.d.ts +8 -0
  126. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.js +12 -0
  127. package/dist/components/Timeline/get-keyframe-navigation.d.ts +2 -2
  128. package/dist/components/Timeline/get-keyframe-navigation.js +14 -6
  129. package/dist/components/Timeline/get-node-keyframes.d.ts +5 -2
  130. package/dist/components/Timeline/get-node-keyframes.js +38 -5
  131. package/dist/components/Timeline/get-timeline-keyframes.js +4 -4
  132. package/dist/components/Timeline/reset-selected-timeline-props.js +22 -8
  133. package/dist/components/Timeline/save-effect-prop.d.ts +14 -3
  134. package/dist/components/Timeline/save-effect-prop.js +36 -18
  135. package/dist/components/Timeline/save-prop-queue.d.ts +2 -1
  136. package/dist/components/Timeline/save-prop-queue.js +5 -2
  137. package/dist/components/Timeline/save-sequence-prop.d.ts +2 -7
  138. package/dist/components/Timeline/save-sequence-prop.js +33 -30
  139. package/dist/components/Timeline/should-clear-selection-on-pointer-down.d.ts +3 -0
  140. package/dist/components/Timeline/should-clear-selection-on-pointer-down.js +7 -0
  141. package/dist/components/Timeline/timeline-asset-link.d.ts +13 -0
  142. package/dist/components/Timeline/timeline-asset-link.js +37 -0
  143. package/dist/components/Timeline/timeline-field-utils.d.ts +1 -0
  144. package/dist/components/Timeline/timeline-field-utils.js +5 -1
  145. package/dist/components/Timeline/timeline-translate-utils.js +9 -2
  146. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +7 -0
  147. package/dist/components/Timeline/use-timeline-keyframe-drag.d.ts +10 -0
  148. package/dist/components/Timeline/use-timeline-keyframe-drag.js +378 -0
  149. package/dist/components/TopPanel.d.ts +1 -1
  150. package/dist/components/folder-menu-items.d.ts +12 -0
  151. package/dist/components/folder-menu-items.js +147 -0
  152. package/dist/components/import-assets.d.ts +22 -0
  153. package/dist/components/import-assets.js +294 -0
  154. package/dist/components/load-canvas-content-from-url.d.ts +1 -0
  155. package/dist/components/load-canvas-content-from-url.js +9 -3
  156. package/dist/components/use-select-asset.d.ts +1 -0
  157. package/dist/components/use-select-asset.js +30 -0
  158. package/dist/error-overlay/error-origin.d.ts +3 -0
  159. package/dist/error-overlay/error-origin.js +42 -0
  160. package/dist/error-overlay/react-overlay/listen-to-runtime-errors.js +6 -2
  161. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +38 -0
  162. package/dist/error-overlay/remotion-overlay/ShortcutHint.js +1 -1
  163. package/dist/error-overlay/remotion-overlay/log-studio-error.d.ts +3 -0
  164. package/dist/error-overlay/remotion-overlay/log-studio-error.js +27 -0
  165. package/dist/esm/{chunk-z0z9d4r0.js → chunk-q0jkt0zq.js} +23062 -17350
  166. package/dist/esm/internals.mjs +23062 -17350
  167. package/dist/esm/previewEntry.mjs +22351 -16615
  168. package/dist/esm/renderEntry.mjs +1 -1
  169. package/dist/helpers/calculate-timeline.js +7 -3
  170. package/dist/helpers/create-folder-tree.js +1 -0
  171. package/dist/helpers/get-asset-metadata.js +2 -2
  172. package/dist/helpers/get-folder-id.d.ts +4 -0
  173. package/dist/helpers/get-folder-id.js +7 -0
  174. package/dist/helpers/get-preview-file-type.d.ts +2 -0
  175. package/dist/helpers/get-preview-file-type.js +33 -0
  176. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +2 -0
  177. package/dist/helpers/install-required-package.d.ts +1 -0
  178. package/dist/helpers/install-required-package.js +39 -0
  179. package/dist/helpers/remote-asset-drag.d.ts +4 -0
  180. package/dist/helpers/remote-asset-drag.js +73 -0
  181. package/dist/helpers/timeline-layout.js +5 -1
  182. package/dist/helpers/use-asset-drag-events.d.ts +5 -2
  183. package/dist/helpers/use-asset-drag-events.js +13 -2
  184. package/dist/helpers/validate-folder-rename.d.ts +6 -0
  185. package/dist/helpers/validate-folder-rename.js +19 -0
  186. package/dist/hot-middleware-client/client.js +6 -0
  187. package/dist/state/editor-outlines.d.ts +8 -0
  188. package/dist/state/editor-outlines.js +18 -0
  189. package/dist/state/modals.d.ts +29 -2
  190. package/dist/state/scale-lock.d.ts +18 -0
  191. package/dist/state/scale-lock.js +59 -0
  192. package/package.json +10 -10
@@ -0,0 +1,479 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelineClipboardKeybindings = exports.getPasteEffectPropTarget = exports.getEffectPropClipboardDataFromSelection = exports.getSnapshotsFromSelection = exports.getPasteEffectsTarget = void 0;
4
+ const studio_shared_1 = require("@remotion/studio-shared");
5
+ const react_1 = require("react");
6
+ const remotion_1 = require("remotion");
7
+ const client_id_1 = require("../../helpers/client-id");
8
+ const use_keybinding_1 = require("../../helpers/use-keybinding");
9
+ const call_api_1 = require("../call-api");
10
+ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
11
+ const find_track_for_node_path_info_1 = require("./find-track-for-node-path-info");
12
+ const save_effect_prop_1 = require("./save-effect-prop");
13
+ const TimelineSelection_1 = require("./TimelineSelection");
14
+ const makeClipboardText = (payload) => JSON.stringify(payload);
15
+ const makeTargetKey = (nodePath) => {
16
+ return JSON.stringify({
17
+ absolutePath: nodePath.absolutePath,
18
+ nodePath: nodePath.nodePath,
19
+ sequenceKeys: nodePath.sequenceKeys,
20
+ });
21
+ };
22
+ const isVisibleFieldSchema = (fieldSchema) => fieldSchema !== undefined && fieldSchema.type !== 'hidden';
23
+ const getDefaultValue = (fieldSchema) => fieldSchema.default !== undefined
24
+ ? JSON.stringify(fieldSchema.default)
25
+ : null;
26
+ const getTargetSequenceNodePathInfo = (selection) => {
27
+ if (selection.type === 'sequence' ||
28
+ selection.type === 'sequence-effect' ||
29
+ selection.type === 'sequence-all-effects') {
30
+ return selection.nodePathInfo;
31
+ }
32
+ return null;
33
+ };
34
+ const getCopyType = (selection) => {
35
+ if (selection.type === 'sequence-effect') {
36
+ return 'effects-additive';
37
+ }
38
+ if (selection.type === 'sequence-all-effects') {
39
+ return 'effects-replacing';
40
+ }
41
+ return null;
42
+ };
43
+ const getPasteEffectsTarget = (selectedItems) => {
44
+ const targetNodePathInfos = selectedItems
45
+ .map(getTargetSequenceNodePathInfo)
46
+ .filter((targetNodePathInfo) => targetNodePathInfo !== null);
47
+ const uniqueTargetKeys = new Set(targetNodePathInfos.map((targetNodePathInfo) => makeTargetKey(targetNodePathInfo.sequenceSubscriptionKey)));
48
+ if (uniqueTargetKeys.size === 0) {
49
+ return { type: 'none' };
50
+ }
51
+ if (uniqueTargetKeys.size !== 1) {
52
+ return { type: 'multiple' };
53
+ }
54
+ const [nodePathInfo] = targetNodePathInfos;
55
+ if (!nodePathInfo) {
56
+ return { type: 'none' };
57
+ }
58
+ if (!nodePathInfo.supportsEffects) {
59
+ return { type: 'unsupported' };
60
+ }
61
+ return {
62
+ type: 'valid',
63
+ nodePathInfo,
64
+ };
65
+ };
66
+ exports.getPasteEffectsTarget = getPasteEffectsTarget;
67
+ const isClipboardInterpolationFunction = (value) => {
68
+ return (0, studio_shared_1.isKeyframeInterpolationFunction)(value);
69
+ };
70
+ const effectPropStatusToClipboardParam = (prop) => {
71
+ if (prop.status === 'computed') {
72
+ return null;
73
+ }
74
+ if (prop.status === 'static') {
75
+ if (prop.codeValue === undefined) {
76
+ return null;
77
+ }
78
+ return {
79
+ type: 'static',
80
+ value: prop.codeValue,
81
+ };
82
+ }
83
+ if (!isClipboardInterpolationFunction(prop.interpolationFunction)) {
84
+ return null;
85
+ }
86
+ return {
87
+ type: 'keyframed',
88
+ interpolationFunction: prop.interpolationFunction,
89
+ keyframes: prop.keyframes,
90
+ easing: prop.easing,
91
+ clamping: prop.clamping,
92
+ ...(prop.posterize === undefined ? {} : { posterize: prop.posterize }),
93
+ };
94
+ };
95
+ const effectStatusToSnapshot = (effect) => {
96
+ if (effect.importPath === null) {
97
+ return null;
98
+ }
99
+ const params = {};
100
+ for (const [key, prop] of Object.entries(effect.props)) {
101
+ if (prop.status === 'static' && prop.codeValue === undefined) {
102
+ continue;
103
+ }
104
+ const param = effectPropStatusToClipboardParam(prop);
105
+ if (param === null) {
106
+ return null;
107
+ }
108
+ params[key] = param;
109
+ }
110
+ return {
111
+ callee: effect.callee,
112
+ importPath: effect.importPath,
113
+ params,
114
+ };
115
+ };
116
+ const getSnapshotsFromSelection = ({ selection, codeValues, }) => {
117
+ if (selection.type !== 'sequence-effect' &&
118
+ selection.type !== 'sequence-all-effects') {
119
+ return null;
120
+ }
121
+ const { sequenceSubscriptionKey } = selection.nodePathInfo;
122
+ const sequenceStatus = codeValues[remotion_1.Internals.makeSequencePropsSubscriptionKey(sequenceSubscriptionKey)];
123
+ if (!sequenceStatus || !sequenceStatus.canUpdate) {
124
+ return null;
125
+ }
126
+ const effects = selection.type === 'sequence-effect'
127
+ ? sequenceStatus.effects.filter((effect) => effect.effectIndex === selection.i)
128
+ : sequenceStatus.effects;
129
+ if (selection.type === 'sequence-effect' && effects.length !== 1) {
130
+ return null;
131
+ }
132
+ const snapshots = [];
133
+ for (const effect of effects) {
134
+ if (!effect.canUpdate) {
135
+ return null;
136
+ }
137
+ const snapshot = effectStatusToSnapshot(effect);
138
+ if (snapshot === null) {
139
+ return null;
140
+ }
141
+ snapshots.push(snapshot);
142
+ }
143
+ return snapshots;
144
+ };
145
+ exports.getSnapshotsFromSelection = getSnapshotsFromSelection;
146
+ const getEffectPropClipboardDataFromSelection = ({ selection, codeValues, }) => {
147
+ if (selection.type !== 'sequence-effect-prop') {
148
+ return null;
149
+ }
150
+ const sequenceStatus = codeValues[remotion_1.Internals.makeSequencePropsSubscriptionKey(selection.nodePathInfo.sequenceSubscriptionKey)];
151
+ if (!sequenceStatus || !sequenceStatus.canUpdate) {
152
+ return null;
153
+ }
154
+ const effect = sequenceStatus.effects.find((item) => item.effectIndex === selection.i);
155
+ if (!(effect === null || effect === void 0 ? void 0 : effect.canUpdate) || effect.importPath === null) {
156
+ return null;
157
+ }
158
+ const prop = effect.props[selection.key];
159
+ if (!prop) {
160
+ return null;
161
+ }
162
+ const param = effectPropStatusToClipboardParam(prop);
163
+ if (param === null) {
164
+ return null;
165
+ }
166
+ return {
167
+ type: 'effect-prop',
168
+ version: 1,
169
+ remotionClipboard: 'effect-prop',
170
+ effect: {
171
+ callee: effect.callee,
172
+ importPath: effect.importPath,
173
+ },
174
+ key: selection.key,
175
+ param,
176
+ };
177
+ };
178
+ exports.getEffectPropClipboardDataFromSelection = getEffectPropClipboardDataFromSelection;
179
+ const getPasteEffectPropTarget = ({ selectedItems, payload, codeValues, sequences, overrideIdsToNodePaths, }) => {
180
+ var _a;
181
+ if (selectedItems.length === 0) {
182
+ return { type: 'none' };
183
+ }
184
+ if (selectedItems.length !== 1) {
185
+ return { type: 'multiple' };
186
+ }
187
+ const [selection] = selectedItems;
188
+ if (!selection) {
189
+ return { type: 'none' };
190
+ }
191
+ if (!selection.nodePathInfo.supportsEffects) {
192
+ return { type: 'unsupported' };
193
+ }
194
+ const target = selection.type === 'sequence-effect-prop'
195
+ ? {
196
+ effectIndex: selection.i,
197
+ fieldKey: selection.key,
198
+ }
199
+ : selection.type === 'sequence-effect'
200
+ ? {
201
+ effectIndex: selection.i,
202
+ fieldKey: payload.key,
203
+ }
204
+ : null;
205
+ if (target === null) {
206
+ return { type: 'none' };
207
+ }
208
+ if (selection.type === 'sequence-effect-prop' &&
209
+ selection.key !== payload.key) {
210
+ return { type: 'prop-mismatch' };
211
+ }
212
+ const track = (0, find_track_for_node_path_info_1.findTrackForNodePathInfo)({
213
+ sequences,
214
+ overrideIdsToNodePaths,
215
+ nodePathInfo: selection.nodePathInfo,
216
+ });
217
+ const sequence = (_a = track === null || track === void 0 ? void 0 : track.sequence) !== null && _a !== void 0 ? _a : null;
218
+ if (!sequence) {
219
+ return { type: 'none' };
220
+ }
221
+ const effect = sequence.effects[target.effectIndex];
222
+ const fieldSchema = effect === null || effect === void 0 ? void 0 : effect.schema[target.fieldKey];
223
+ if (!effect || !isVisibleFieldSchema(fieldSchema)) {
224
+ return { type: 'prop-mismatch' };
225
+ }
226
+ const sequenceStatus = codeValues[remotion_1.Internals.makeSequencePropsSubscriptionKey(selection.nodePathInfo.sequenceSubscriptionKey)];
227
+ if (!(sequenceStatus === null || sequenceStatus === void 0 ? void 0 : sequenceStatus.canUpdate)) {
228
+ return { type: 'uncopyable' };
229
+ }
230
+ const effectStatus = sequenceStatus.effects.find((item) => item.effectIndex === target.effectIndex);
231
+ if (!(effectStatus === null || effectStatus === void 0 ? void 0 : effectStatus.canUpdate)) {
232
+ return { type: 'uncopyable' };
233
+ }
234
+ if (effectStatus.importPath !== payload.effect.importPath) {
235
+ return { type: 'effect-type-mismatch' };
236
+ }
237
+ const propStatus = effectStatus.props[target.fieldKey];
238
+ if (!propStatus || propStatus.status === 'computed') {
239
+ return { type: 'uncopyable' };
240
+ }
241
+ return {
242
+ type: 'valid',
243
+ fileName: selection.nodePathInfo.sequenceSubscriptionKey.absolutePath,
244
+ nodePath: selection.nodePathInfo.sequenceSubscriptionKey,
245
+ effectIndex: target.effectIndex,
246
+ fieldKey: target.fieldKey,
247
+ defaultValue: getDefaultValue(fieldSchema),
248
+ schema: effect.schema,
249
+ };
250
+ };
251
+ exports.getPasteEffectPropTarget = getPasteEffectPropTarget;
252
+ const TimelineClipboardKeybindings = () => {
253
+ const keybindings = (0, use_keybinding_1.useKeybinding)();
254
+ const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
255
+ const { canSelect } = (0, TimelineSelection_1.useTimelineSelection)();
256
+ const currentSelection = (0, TimelineSelection_1.useCurrentTimelineSelectionStateAsRef)();
257
+ const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
258
+ const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
259
+ const { sequences } = (0, react_1.useContext)(remotion_1.Internals.SequenceManager);
260
+ const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
261
+ (0, react_1.useEffect)(() => {
262
+ if (!canSelect || previewServerState.type !== 'connected') {
263
+ return;
264
+ }
265
+ const { clientId } = previewServerState;
266
+ const copy = keybindings.registerKeybinding({
267
+ event: 'keydown',
268
+ key: 'c',
269
+ callback: (e) => {
270
+ var _a;
271
+ const { selectedItems } = currentSelection.current;
272
+ if (selectedItems.length === 0) {
273
+ return;
274
+ }
275
+ if (selectedItems.some((selection) => selection.type === 'sequence-effect-prop')) {
276
+ e.preventDefault();
277
+ if (selectedItems.length !== 1 ||
278
+ ((_a = selectedItems[0]) === null || _a === void 0 ? void 0 : _a.type) !== 'sequence-effect-prop') {
279
+ (0, NotificationCenter_1.showNotification)('Select one effect prop to copy its value', 3000);
280
+ return;
281
+ }
282
+ const payload = (0, exports.getEffectPropClipboardDataFromSelection)({
283
+ selection: selectedItems[0],
284
+ codeValues,
285
+ });
286
+ if (payload === null) {
287
+ (0, NotificationCenter_1.showNotification)('Cannot copy effect prop because its value cannot be copied', 3000);
288
+ return;
289
+ }
290
+ navigator.clipboard
291
+ .writeText(makeClipboardText(payload))
292
+ .then(() => {
293
+ (0, NotificationCenter_1.showNotification)('Copied effect prop to clipboard', 1000);
294
+ })
295
+ .catch((err) => {
296
+ (0, NotificationCenter_1.showNotification)(`Could not copy effect prop: ${err.message}`, 2000);
297
+ });
298
+ return;
299
+ }
300
+ const firstSelection = selectedItems[0];
301
+ const type = firstSelection ? getCopyType(firstSelection) : null;
302
+ if (type === null) {
303
+ return;
304
+ }
305
+ if (selectedItems.some((selection) => getCopyType(selection) !== type)) {
306
+ e.preventDefault();
307
+ (0, NotificationCenter_1.showNotification)('Cannot copy individual effects together with all effects', 3000);
308
+ return;
309
+ }
310
+ const snapshots = selectedItems.flatMap((selection) => {
311
+ const itemSnapshots = (0, exports.getSnapshotsFromSelection)({
312
+ selection,
313
+ codeValues,
314
+ });
315
+ return itemSnapshots !== null && itemSnapshots !== void 0 ? itemSnapshots : [null];
316
+ });
317
+ if (snapshots.some((snapshot) => snapshot === null)) {
318
+ e.preventDefault();
319
+ (0, NotificationCenter_1.showNotification)('Cannot copy effects because one of them contains values that cannot be copied', 3000);
320
+ return;
321
+ }
322
+ e.preventDefault();
323
+ navigator.clipboard
324
+ .writeText(makeClipboardText({
325
+ type,
326
+ version: 3,
327
+ remotionClipboard: 'effects',
328
+ effects: snapshots,
329
+ }))
330
+ .then(() => {
331
+ (0, NotificationCenter_1.showNotification)(snapshots.length === 1
332
+ ? 'Copied effect to clipboard'
333
+ : 'Copied effects to clipboard', 1000);
334
+ })
335
+ .catch((err) => {
336
+ (0, NotificationCenter_1.showNotification)(`Could not copy effects: ${err.message}`, 2000);
337
+ });
338
+ },
339
+ commandCtrlKey: true,
340
+ preventDefault: false,
341
+ triggerIfInputFieldFocused: false,
342
+ keepRegisteredWhenNotHighestContext: false,
343
+ });
344
+ const paste = keybindings.registerKeybinding({
345
+ event: 'keydown',
346
+ key: 'v',
347
+ callback: (e) => {
348
+ const { selectedItems } = currentSelection.current;
349
+ if (selectedItems.length === 0) {
350
+ return;
351
+ }
352
+ navigator.clipboard
353
+ .readText()
354
+ .then((text) => {
355
+ const effectPropResult = (0, studio_shared_1.parseEffectPropClipboardDataResult)(text);
356
+ if (effectPropResult.status !== 'invalid') {
357
+ e.preventDefault();
358
+ if (effectPropResult.status === 'unsupported-version') {
359
+ (0, NotificationCenter_1.showNotification)('Cannot paste effect prop copied from a different Remotion Studio version', 4000);
360
+ return;
361
+ }
362
+ const effectPropTarget = (0, exports.getPasteEffectPropTarget)({
363
+ selectedItems,
364
+ payload: effectPropResult.data,
365
+ codeValues,
366
+ sequences,
367
+ overrideIdsToNodePaths: overrideIdToNodePathMappings,
368
+ });
369
+ if (effectPropTarget.type !== 'valid') {
370
+ switch (effectPropTarget.type) {
371
+ case 'multiple':
372
+ (0, NotificationCenter_1.showNotification)('Select one target effect prop or effect to paste onto', 3000);
373
+ return;
374
+ case 'none':
375
+ (0, NotificationCenter_1.showNotification)('Select a matching effect prop or effect to paste onto', 3000);
376
+ return;
377
+ case 'unsupported':
378
+ (0, NotificationCenter_1.showNotification)('This sequence does not support effects', 3000);
379
+ return;
380
+ case 'effect-type-mismatch':
381
+ (0, NotificationCenter_1.showNotification)('Select an effect of the same type to paste this prop', 3000);
382
+ return;
383
+ case 'prop-mismatch':
384
+ (0, NotificationCenter_1.showNotification)('Select the same effect prop, or an effect with that prop', 3000);
385
+ return;
386
+ case 'uncopyable':
387
+ (0, NotificationCenter_1.showNotification)('Cannot paste onto an effect prop that cannot be updated', 3000);
388
+ return;
389
+ default:
390
+ throw new Error(`Unexpected paste target: ${effectPropTarget}`);
391
+ }
392
+ }
393
+ return (0, save_effect_prop_1.saveEffectProp)({
394
+ fileName: effectPropTarget.fileName,
395
+ nodePath: effectPropTarget.nodePath,
396
+ effectIndex: effectPropTarget.effectIndex,
397
+ fieldKey: effectPropTarget.fieldKey,
398
+ ...(effectPropResult.data.param.type === 'static'
399
+ ? {
400
+ type: 'value',
401
+ value: effectPropResult.data.param.value,
402
+ }
403
+ : {
404
+ type: 'effect-param',
405
+ effectParam: effectPropResult.data.param,
406
+ }),
407
+ defaultValue: effectPropTarget.defaultValue,
408
+ schema: effectPropTarget.schema,
409
+ setCodeValues,
410
+ clientId,
411
+ }).then(() => {
412
+ (0, NotificationCenter_1.showNotification)('Pasted effect prop', 2000);
413
+ });
414
+ }
415
+ const result = (0, studio_shared_1.parseEffectClipboardDataResult)(text);
416
+ if (result.status === 'invalid') {
417
+ return;
418
+ }
419
+ e.preventDefault();
420
+ if (result.status === 'unsupported-version') {
421
+ (0, NotificationCenter_1.showNotification)('Cannot paste effects copied from a different Remotion Studio version', 4000);
422
+ return;
423
+ }
424
+ const { data: payload } = result;
425
+ const target = (0, exports.getPasteEffectsTarget)(selectedItems);
426
+ if (target.type === 'multiple') {
427
+ (0, NotificationCenter_1.showNotification)('Select one target sequence to paste effects', 3000);
428
+ return;
429
+ }
430
+ if (target.type === 'none') {
431
+ (0, NotificationCenter_1.showNotification)('Select a sequence to paste effects onto', 3000);
432
+ return;
433
+ }
434
+ if (target.type === 'unsupported') {
435
+ (0, NotificationCenter_1.showNotification)('This sequence does not support effects', 3000);
436
+ return;
437
+ }
438
+ const { sequenceSubscriptionKey: targetSequenceNodePath } = target.nodePathInfo;
439
+ return (0, call_api_1.callApi)('/api/paste-effects', {
440
+ targetFileName: targetSequenceNodePath.absolutePath,
441
+ targetSequenceNodePath,
442
+ type: payload.type,
443
+ effects: payload.effects,
444
+ clientId,
445
+ }).then((pasteResult) => {
446
+ if (pasteResult.success) {
447
+ (0, NotificationCenter_1.showNotification)('Pasted effects', 2000);
448
+ }
449
+ else {
450
+ (0, NotificationCenter_1.showNotification)(pasteResult.reason, 4000);
451
+ }
452
+ });
453
+ })
454
+ .catch((err) => {
455
+ (0, NotificationCenter_1.showNotification)(`Could not paste effects: ${err.message}`, 3000);
456
+ });
457
+ },
458
+ commandCtrlKey: true,
459
+ preventDefault: false,
460
+ triggerIfInputFieldFocused: false,
461
+ keepRegisteredWhenNotHighestContext: false,
462
+ });
463
+ return () => {
464
+ copy.unregister();
465
+ paste.unregister();
466
+ };
467
+ }, [
468
+ canSelect,
469
+ codeValues,
470
+ currentSelection,
471
+ keybindings,
472
+ overrideIdToNodePathMappings,
473
+ previewServerState,
474
+ sequences,
475
+ setCodeValues,
476
+ ]);
477
+ return null;
478
+ };
479
+ exports.TimelineClipboardKeybindings = TimelineClipboardKeybindings;
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
- import type { CanUpdateSequencePropStatus } from 'remotion';
2
+ import type { CanUpdateSequencePropStatusStatic } from 'remotion';
3
3
  import type { SchemaFieldInfo, TimelineFieldOnDragValueChange, TimelineFieldOnSave } from '../../helpers/timeline-layout';
4
4
  export declare const TimelineColorField: React.FC<{
5
5
  readonly field: SchemaFieldInfo;
6
6
  readonly effectiveValue: unknown;
7
- readonly propStatus: CanUpdateSequencePropStatus;
7
+ readonly propStatus: CanUpdateSequencePropStatusStatic;
8
8
  readonly onSave: TimelineFieldOnSave;
9
9
  readonly onDragValueChange: TimelineFieldOnDragValueChange;
10
10
  readonly onDragEnd: () => void;
@@ -19,15 +19,9 @@ const TimelineColorField = ({ field, effectiveValue, propStatus, onSave, onDragV
19
19
  ? ((_a = field.fieldSchema.default) !== null && _a !== void 0 ? _a : '#000')
20
20
  : '';
21
21
  const onChange = (0, react_1.useCallback)((next) => {
22
- if (!propStatus.canUpdate) {
23
- return;
24
- }
25
22
  onDragValueChange(next);
26
- }, [onDragValueChange, propStatus.canUpdate]);
23
+ }, [onDragValueChange]);
27
24
  const onChangeComplete = (0, react_1.useCallback)((next) => {
28
- if (!propStatus.canUpdate) {
29
- return;
30
- }
31
25
  if (next !== propStatus.codeValue) {
32
26
  onSave(next);
33
27
  }
@@ -38,6 +32,6 @@ const TimelineColorField = ({ field, effectiveValue, propStatus, onSave, onDragV
38
32
  marginLeft: 5,
39
33
  };
40
34
  }, []);
41
- return (jsx_runtime_1.jsx("span", { style: containerStyle, children: jsx_runtime_1.jsx(ColorPicker_1.ColorPicker, { value: currentValue, status: "ok", onChange: onChange, onChangeComplete: onChangeComplete, width: SWATCH_WIDTH, height: SWATCH_HEIGHT, disabled: !propStatus.canUpdate, name: field.key, title: currentValue, style: swatchStyle }) }));
35
+ return (jsx_runtime_1.jsx("span", { style: containerStyle, children: jsx_runtime_1.jsx(ColorPicker_1.ColorPicker, { value: currentValue, status: "ok", onChange: onChange, onChangeComplete: onChangeComplete, width: SWATCH_WIDTH, height: SWATCH_HEIGHT, disabled: false, name: field.key, title: currentValue, style: swatchStyle }) }));
42
36
  };
43
37
  exports.TimelineColorField = TimelineColorField;
@@ -5,6 +5,7 @@ const react_1 = require("react");
5
5
  const remotion_1 = require("remotion");
6
6
  const client_id_1 = require("../../helpers/client-id");
7
7
  const use_keybinding_1 = require("../../helpers/use-keybinding");
8
+ const ConfirmationDialog_1 = require("../ConfirmationDialog");
8
9
  const delete_selected_timeline_item_1 = require("./delete-selected-timeline-item");
9
10
  const duplicate_selected_timeline_item_1 = require("./duplicate-selected-timeline-item");
10
11
  const reset_selected_timeline_props_1 = require("./reset-selected-timeline-props");
@@ -18,6 +19,7 @@ const TimelineDeleteKeybindings = () => {
18
19
  const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
19
20
  const { canSelect } = (0, TimelineSelection_1.useTimelineSelection)();
20
21
  const currentSelection = (0, TimelineSelection_1.useCurrentTimelineSelectionStateAsRef)();
22
+ const confirm = (0, ConfirmationDialog_1.useConfirmationDialog)();
21
23
  (0, react_1.useEffect)(() => {
22
24
  if (!canSelect || previewServerState.type !== 'connected') {
23
25
  return;
@@ -49,12 +51,18 @@ const TimelineDeleteKeybindings = () => {
49
51
  overrideIdsToNodePaths: overrideIdToNodePathMappings,
50
52
  setCodeValues,
51
53
  clientId,
54
+ confirm,
52
55
  });
53
56
  if (deletePromise === null) {
54
57
  return;
55
58
  }
56
- clearSelection();
57
- deletePromise.catch(() => undefined);
59
+ deletePromise
60
+ .then((deleted) => {
61
+ if (deleted) {
62
+ clearSelection();
63
+ }
64
+ })
65
+ .catch(() => undefined);
58
66
  },
59
67
  commandCtrlKey: false,
60
68
  preventDefault: true,
@@ -71,6 +79,7 @@ const TimelineDeleteKeybindings = () => {
71
79
  }
72
80
  const duplicatePromise = (0, duplicate_selected_timeline_item_1.duplicateSelectedTimelineItems)({
73
81
  selections: selectedItems,
82
+ confirm,
74
83
  });
75
84
  if (duplicatePromise === null) {
76
85
  return;
@@ -89,6 +98,7 @@ const TimelineDeleteKeybindings = () => {
89
98
  }, [
90
99
  canSelect,
91
100
  codeValues,
101
+ confirm,
92
102
  currentSelection,
93
103
  keybindings,
94
104
  overrideIdToNodePathMappings,
@@ -81,12 +81,12 @@ const TimelineEffectItem = ({ label, nodePathInfo, effectIndex, effectSchema, do
81
81
  ? ((_b = (_a = effectStatus.props) === null || _a === void 0 ? void 0 : _a.disabled) !== null && _b !== void 0 ? _b : null)
82
82
  : null;
83
83
  const isDisabled = (0, react_1.useMemo)(() => {
84
- if (disabledStatus && disabledStatus.canUpdate) {
84
+ if ((disabledStatus === null || disabledStatus === void 0 ? void 0 : disabledStatus.status) === 'static') {
85
85
  return Boolean(disabledStatus.codeValue);
86
86
  }
87
87
  return false;
88
88
  }, [disabledStatus]);
89
- const canToggle = previewConnected && disabledStatus !== null && disabledStatus.canUpdate;
89
+ const canToggle = previewConnected && (disabledStatus === null || disabledStatus === void 0 ? void 0 : disabledStatus.status) === 'static';
90
90
  const deleteDisabled = !previewConnected ||
91
91
  effectStatus.type !== 'can-update-effect' ||
92
92
  !validatedLocation.source;
@@ -178,6 +178,7 @@ const TimelineEffectItem = ({ label, nodePathInfo, effectIndex, effectSchema, do
178
178
  ? JSON.stringify(fieldSchema.default)
179
179
  : null;
180
180
  (0, save_effect_prop_1.saveEffectProp)({
181
+ type: 'value',
181
182
  fileName: validatedLocation.source,
182
183
  nodePath,
183
184
  effectIndex,