@remotion/studio 4.0.469 → 4.0.471

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 (101) hide show
  1. package/dist/Studio.js +1 -1
  2. package/dist/api/save-render-output.js +3 -12
  3. package/dist/components/AudioWaveform.js +19 -2
  4. package/dist/components/ContextMenu.d.ts +7 -2
  5. package/dist/components/ContextMenu.js +53 -9
  6. package/dist/components/EditorContent.js +5 -4
  7. package/dist/components/Menu/MenuItem.d.ts +1 -1
  8. package/dist/components/MenuBuildIndicator.js +0 -1
  9. package/dist/components/NewComposition/InputDragger.js +1 -0
  10. package/dist/components/Preview.js +6 -2
  11. package/dist/components/SelectedOutlineOverlay.d.ts +49 -0
  12. package/dist/components/SelectedOutlineOverlay.js +710 -0
  13. package/dist/components/Timeline/Timeline.js +102 -13
  14. package/dist/components/Timeline/TimelineDeleteKeybindings.d.ts +2 -0
  15. package/dist/components/Timeline/TimelineDeleteKeybindings.js +101 -0
  16. package/dist/components/Timeline/TimelineDragHandler.js +20 -244
  17. package/dist/components/Timeline/{TimelineEffectGroupRow.d.ts → TimelineEffectItem.d.ts} +1 -1
  18. package/dist/components/Timeline/TimelineEffectItem.js +323 -0
  19. package/dist/components/Timeline/{TimelineEffectFieldRow.d.ts → TimelineEffectPropItem.d.ts} +2 -1
  20. package/dist/components/Timeline/{TimelineEffectFieldRow.js → TimelineEffectPropItem.js} +97 -8
  21. package/dist/components/Timeline/TimelineExpandArrowButton.js +5 -1
  22. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +37 -5
  23. package/dist/components/Timeline/TimelineExpandedRow.d.ts +1 -0
  24. package/dist/components/Timeline/TimelineExpandedRow.js +9 -7
  25. package/dist/components/Timeline/TimelineExpandedSection.d.ts +1 -0
  26. package/dist/components/Timeline/TimelineExpandedSection.js +2 -2
  27. package/dist/components/Timeline/TimelineInOutDragHandler.d.ts +2 -0
  28. package/dist/components/Timeline/TimelineInOutDragHandler.js +324 -0
  29. package/dist/components/Timeline/TimelineInOutPointer.js +3 -1
  30. package/dist/components/Timeline/TimelineInOutPointerHandle.d.ts +1 -0
  31. package/dist/components/Timeline/TimelineInOutPointerHandle.js +5 -4
  32. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +17 -0
  33. package/dist/components/Timeline/TimelineKeyframeControls.js +222 -0
  34. package/dist/components/Timeline/TimelineKeyframeDiamond.js +7 -6
  35. package/dist/components/Timeline/TimelineKeyframedValue.d.ts +8 -0
  36. package/dist/components/Timeline/TimelineKeyframedValue.js +36 -0
  37. package/dist/components/Timeline/TimelineList.js +3 -15
  38. package/dist/components/Timeline/TimelineRowChrome.d.ts +6 -1
  39. package/dist/components/Timeline/TimelineRowChrome.js +25 -7
  40. package/dist/components/Timeline/TimelineSelection.d.ts +53 -9
  41. package/dist/components/Timeline/TimelineSelection.js +305 -48
  42. package/dist/components/Timeline/TimelineSequence.d.ts +2 -0
  43. package/dist/components/Timeline/TimelineSequence.js +18 -6
  44. package/dist/components/Timeline/TimelineSequenceFrame.js +1 -0
  45. package/dist/components/Timeline/{TimelineListItem.d.ts → TimelineSequenceItem.d.ts} +2 -1
  46. package/dist/components/Timeline/{TimelineListItem.js → TimelineSequenceItem.js} +140 -34
  47. package/dist/components/Timeline/{TimelineFieldRow.d.ts → TimelineSequencePropItem.d.ts} +2 -1
  48. package/dist/components/Timeline/{TimelineFieldRow.js → TimelineSequencePropItem.js} +81 -5
  49. package/dist/components/Timeline/TimelineTimeIndicators.js +0 -1
  50. package/dist/components/Timeline/TimelineTrack.js +3 -1
  51. package/dist/components/Timeline/TimelineTranslateField.js +14 -22
  52. package/dist/components/Timeline/call-add-keyframe.d.ts +23 -0
  53. package/dist/components/Timeline/call-add-keyframe.js +54 -0
  54. package/dist/components/Timeline/call-delete-keyframe.d.ts +37 -0
  55. package/dist/components/Timeline/call-delete-keyframe.js +122 -0
  56. package/dist/components/Timeline/delete-selected-keyframe.d.ts +21 -0
  57. package/dist/components/Timeline/delete-selected-keyframe.js +92 -0
  58. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +17 -0
  59. package/dist/components/Timeline/delete-selected-timeline-item.js +178 -0
  60. package/dist/components/Timeline/duplicate-selected-timeline-item.d.ts +13 -0
  61. package/dist/components/Timeline/duplicate-selected-timeline-item.js +66 -0
  62. package/dist/components/Timeline/find-track-for-node-path-info.d.ts +7 -0
  63. package/dist/components/Timeline/find-track-for-node-path-info.js +13 -0
  64. package/dist/components/Timeline/get-keyframe-navigation.d.ts +9 -0
  65. package/dist/components/Timeline/get-keyframe-navigation.js +26 -0
  66. package/dist/components/Timeline/parse-keyframe-field-from-node-path.d.ts +8 -0
  67. package/dist/components/Timeline/parse-keyframe-field-from-node-path.js +26 -0
  68. package/dist/components/Timeline/reset-selected-timeline-props.d.ts +38 -0
  69. package/dist/components/Timeline/reset-selected-timeline-props.js +143 -0
  70. package/dist/components/Timeline/save-sequence-prop.d.ts +14 -2
  71. package/dist/components/Timeline/save-sequence-prop.js +42 -7
  72. package/dist/components/Timeline/sequence-props-subscription-store.d.ts +3 -2
  73. package/dist/components/Timeline/sequence-props-subscription-store.js +2 -1
  74. package/dist/components/Timeline/timeline-row-layout.d.ts +1 -0
  75. package/dist/components/Timeline/timeline-row-layout.js +2 -1
  76. package/dist/components/Timeline/timeline-scroll-logic.js +3 -3
  77. package/dist/components/Timeline/timeline-translate-utils.d.ts +2 -0
  78. package/dist/components/Timeline/timeline-translate-utils.js +20 -0
  79. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +10 -3
  80. package/dist/components/Timeline/use-sequence-props-subscription.js +2 -1
  81. package/dist/components/composition-menu-items.js +32 -1
  82. package/dist/error-overlay/remotion-overlay/OpenInEditor.js +0 -1
  83. package/dist/esm/{chunk-1mp51e0w.js → chunk-z0z9d4r0.js} +10422 -5958
  84. package/dist/esm/internals.mjs +10422 -5958
  85. package/dist/esm/previewEntry.mjs +10419 -5953
  86. package/dist/esm/renderEntry.mjs +3 -1
  87. package/dist/helpers/format-file-location.d.ts +9 -0
  88. package/dist/helpers/format-file-location.js +27 -0
  89. package/dist/helpers/get-box-quads-polyfill-internals.d.ts +82 -0
  90. package/dist/helpers/get-box-quads-polyfill-internals.js +2395 -0
  91. package/dist/helpers/get-box-quads-ponyfill.d.ts +10 -0
  92. package/dist/helpers/get-box-quads-ponyfill.js +23 -0
  93. package/dist/helpers/get-left-of-timeline-slider.js +1 -1
  94. package/dist/helpers/get-timeline-sequence-layout.js +10 -11
  95. package/dist/helpers/open-in-editor.d.ts +20 -2
  96. package/dist/helpers/open-in-editor.js +53 -30
  97. package/dist/helpers/use-menu-structure.js +8 -17
  98. package/dist/renderEntry.js +2 -2
  99. package/dist/state/z-index.js +5 -2
  100. package/package.json +10 -10
  101. package/dist/components/Timeline/TimelineEffectGroupRow.js +0 -153
@@ -1,16 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TimelineListItem = void 0;
3
+ exports.TimelineSequenceItem = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const studio_shared_1 = require("@remotion/studio-shared");
5
6
  const react_1 = require("react");
6
7
  const remotion_1 = require("remotion");
7
8
  const no_react_1 = require("remotion/no-react");
8
9
  const client_id_1 = require("../../helpers/client-id");
10
+ const format_file_location_1 = require("../../helpers/format-file-location");
9
11
  const timeline_layout_1 = require("../../helpers/timeline-layout");
10
12
  const call_api_1 = require("../call-api");
11
13
  const ContextMenu_1 = require("../ContextMenu");
12
14
  const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
13
15
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
16
+ const duplicate_selected_timeline_item_1 = require("./duplicate-selected-timeline-item");
14
17
  const save_sequence_prop_1 = require("./save-sequence-prop");
15
18
  const TimelineExpandArrowButton_1 = require("./TimelineExpandArrowButton");
16
19
  const TimelineExpandedSection_1 = require("./TimelineExpandedSection");
@@ -29,7 +32,34 @@ const labelContainerStyle = {
29
32
  minWidth: 0,
30
33
  gap: 4,
31
34
  };
32
- const TimelineListItem = ({ nestedDepth, sequence, nodePathInfo }) => {
35
+ const effectDropHighlight = {
36
+ backgroundColor: 'rgba(0, 155, 255, 0.16)',
37
+ outline: '1px solid rgba(0, 155, 255, 0.75)',
38
+ outlineOffset: -1,
39
+ };
40
+ const hasEffectDragType = (dataTransfer) => {
41
+ return Array.from(dataTransfer.types).some((type) => type === studio_shared_1.EFFECT_DRAG_MIME_TYPE ||
42
+ type === 'application/json' ||
43
+ type === 'text/plain');
44
+ };
45
+ const getEffectDragData = (dataTransfer) => {
46
+ for (const type of [
47
+ studio_shared_1.EFFECT_DRAG_MIME_TYPE,
48
+ 'application/json',
49
+ 'text/plain',
50
+ ]) {
51
+ const value = dataTransfer.getData(type);
52
+ if (!value) {
53
+ continue;
54
+ }
55
+ const parsed = (0, studio_shared_1.parseEffectDragData)(value);
56
+ if (parsed) {
57
+ return parsed;
58
+ }
59
+ }
60
+ return null;
61
+ };
62
+ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDisplayOffset }) => {
33
63
  var _a;
34
64
  var _b;
35
65
  const nodePath = (_b = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _b !== void 0 ? _b : null;
@@ -42,7 +72,12 @@ const TimelineListItem = ({ nestedDepth, sequence, nodePathInfo }) => {
42
72
  const { setCanvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionSetters);
43
73
  const { onSelect, selectable, selected } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
44
74
  const containsSelection = (0, TimelineSelection_1.useTimelineRowContainsSelection)(nodePathInfo);
75
+ const [effectDropHovered, setEffectDropHovered] = (0, react_1.useState)(false);
45
76
  const { canOpenInEditor, openInEditor, originalLocation } = (0, use_open_sequence_in_editor_1.useOpenSequenceInEditor)(sequence);
77
+ const fileLocation = (0, react_1.useMemo)(() => (0, format_file_location_1.formatFileLocation)({
78
+ location: originalLocation,
79
+ root: window.remotion_cwd,
80
+ }), [originalLocation]);
46
81
  const validatedLocation = (0, react_1.useMemo)(() => {
47
82
  var _a;
48
83
  if (!originalLocation ||
@@ -59,35 +94,12 @@ const TimelineListItem = ({ nestedDepth, sequence, nodePathInfo }) => {
59
94
  const canDeleteFromSource = Boolean(nodePath && (validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source));
60
95
  const deleteDisabled = (0, react_1.useMemo)(() => !previewConnected || !sequence.controls || !canDeleteFromSource, [previewConnected, sequence.controls, canDeleteFromSource]);
61
96
  const duplicateDisabled = deleteDisabled;
62
- const onDuplicateSequenceFromSource = (0, react_1.useCallback)(async () => {
63
- if (!(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) || !nodePath) {
97
+ const onDuplicateSequenceFromSource = (0, react_1.useCallback)(() => {
98
+ if (!(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) || !nodePathInfo) {
64
99
  return;
65
100
  }
66
- if (nodePathInfo && nodePathInfo.numberOfSequencesWithThisNodePath > 1) {
67
- const message = 'This sequence is programmatically duplicated ' +
68
- nodePathInfo.numberOfSequencesWithThisNodePath +
69
- ' times in the code. Duplicating inserts another copy. Continue?';
70
- // eslint-disable-next-line no-alert -- native confirm before applying duplicate codemod in .map callbacks
71
- if (!window.confirm(message)) {
72
- return;
73
- }
74
- }
75
- try {
76
- const result = await (0, call_api_1.callApi)('/api/duplicate-jsx-node', {
77
- fileName: validatedLocation.source,
78
- nodePath: nodePath.nodePath,
79
- });
80
- if (result.success) {
81
- (0, NotificationCenter_1.showNotification)('Duplicated sequence in source file', 2000);
82
- }
83
- else {
84
- (0, NotificationCenter_1.showNotification)(result.reason, 4000);
85
- }
86
- }
87
- catch (err) {
88
- (0, NotificationCenter_1.showNotification)(err.message, 4000);
89
- }
90
- }, [nodePath, validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source, nodePathInfo]);
101
+ (0, duplicate_selected_timeline_item_1.duplicateSequencesFromSource)([nodePathInfo]).catch(() => undefined);
102
+ }, [nodePathInfo, validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source]);
91
103
  const onDeleteSequenceFromSource = (0, react_1.useCallback)(async () => {
92
104
  if (!(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) || !nodePath) {
93
105
  return;
@@ -103,8 +115,12 @@ const TimelineListItem = ({ nestedDepth, sequence, nodePathInfo }) => {
103
115
  }
104
116
  try {
105
117
  const result = await (0, call_api_1.callApi)('/api/delete-jsx-node', {
106
- fileName: validatedLocation.source,
107
- nodePath: nodePath.nodePath,
118
+ nodes: [
119
+ {
120
+ fileName: validatedLocation.source,
121
+ nodePath: nodePath.nodePath,
122
+ },
123
+ ],
108
124
  });
109
125
  if (result.success) {
110
126
  (0, NotificationCenter_1.showNotification)('Removed sequence from source file', 2000);
@@ -146,6 +162,30 @@ const TimelineListItem = ({ nestedDepth, sequence, nodePathInfo }) => {
146
162
  value: 'show-in-editor',
147
163
  }
148
164
  : null,
165
+ {
166
+ type: 'item',
167
+ id: 'copy-file-location',
168
+ keyHint: null,
169
+ label: 'Copy file location',
170
+ leftItem: null,
171
+ disabled: !fileLocation,
172
+ onClick: () => {
173
+ if (!fileLocation) {
174
+ return;
175
+ }
176
+ navigator.clipboard
177
+ .writeText(fileLocation)
178
+ .then(() => {
179
+ (0, NotificationCenter_1.showNotification)('Copied file location to clipboard', 1000);
180
+ })
181
+ .catch((err) => {
182
+ (0, NotificationCenter_1.showNotification)(`Could not copy to clipboard: ${err.message}`, 1000);
183
+ });
184
+ },
185
+ quickSwitcherLabel: null,
186
+ subMenu: null,
187
+ value: 'copy-file-location',
188
+ },
149
189
  documentationLink
150
190
  ? {
151
191
  type: 'item',
@@ -223,6 +263,7 @@ const TimelineListItem = ({ nestedDepth, sequence, nodePathInfo }) => {
223
263
  assetLinkInfo,
224
264
  deleteDisabled,
225
265
  duplicateDisabled,
266
+ fileLocation,
226
267
  onDeleteSequenceFromSource,
227
268
  onDuplicateSequenceFromSource,
228
269
  canOpenInEditor,
@@ -242,6 +283,10 @@ const TimelineListItem = ({ nestedDepth, sequence, nodePathInfo }) => {
242
283
  if (!TimelineSelection_1.SELECTION_ENABLED || !canOpenInEditor) {
243
284
  return;
244
285
  }
286
+ if ((0, TimelineSelection_1.isTimelineSelectionModifierEvent)(e)) {
287
+ e.stopPropagation();
288
+ return;
289
+ }
245
290
  e.stopPropagation();
246
291
  openInEditor();
247
292
  }, [canOpenInEditor, openInEditor]);
@@ -306,6 +351,14 @@ const TimelineListItem = ({ nestedDepth, sequence, nodePathInfo }) => {
306
351
  flexShrink: 0,
307
352
  };
308
353
  }, []);
354
+ const rowStyle = (0, react_1.useMemo)(() => {
355
+ return effectDropHovered
356
+ ? {
357
+ ...inner,
358
+ ...effectDropHighlight,
359
+ }
360
+ : inner;
361
+ }, [effectDropHovered, inner]);
309
362
  const hasExpandableContent = Boolean(sequence.controls) || sequence.effects.length > 0;
310
363
  const canToggleVisibility = previewConnected &&
311
364
  Boolean(sequence.controls) &&
@@ -314,7 +367,60 @@ const TimelineListItem = ({ nestedDepth, sequence, nodePathInfo }) => {
314
367
  codeHiddenStatus !== undefined &&
315
368
  codeHiddenStatus !== null &&
316
369
  codeHiddenStatus.canUpdate;
317
- const trackRow = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: nestedDepth, eye: canToggleVisibility ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: hasExpandableContent ? (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: onToggleExpand, label: "track properties", disabled: !previewConnected || nodePathInfo === null })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {})), style: inner, selected: selected, selectable: selectable, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, outerHeight: outerHeight, onDoubleClick: TimelineSelection_1.SELECTION_ENABLED && canOpenInEditor
370
+ const canDropEffect = previewServerState.type === 'connected' &&
371
+ nodePath !== null &&
372
+ validatedLocation !== null &&
373
+ sequence.type !== 'audio';
374
+ const onEffectDragOver = (0, react_1.useCallback)((e) => {
375
+ if (!canDropEffect || !hasEffectDragType(e.dataTransfer)) {
376
+ return;
377
+ }
378
+ e.preventDefault();
379
+ e.dataTransfer.dropEffect = 'copy';
380
+ setEffectDropHovered(true);
381
+ }, [canDropEffect]);
382
+ const onEffectDragLeave = (0, react_1.useCallback)((e) => {
383
+ if (e.currentTarget.contains(e.relatedTarget)) {
384
+ return;
385
+ }
386
+ setEffectDropHovered(false);
387
+ }, []);
388
+ const onEffectDrop = (0, react_1.useCallback)(async (e) => {
389
+ if (!canDropEffect ||
390
+ previewServerState.type !== 'connected' ||
391
+ nodePath === null ||
392
+ validatedLocation === null) {
393
+ return;
394
+ }
395
+ e.preventDefault();
396
+ e.stopPropagation();
397
+ setEffectDropHovered(false);
398
+ const dragData = getEffectDragData(e.dataTransfer);
399
+ if (!dragData) {
400
+ (0, NotificationCenter_1.showNotification)('Could not read effect drag data', 3000);
401
+ return;
402
+ }
403
+ try {
404
+ const result = await (0, call_api_1.callApi)('/api/add-effect', {
405
+ fileName: validatedLocation.source,
406
+ sequenceNodePath: nodePath,
407
+ effectName: dragData.effect.name,
408
+ effectImportPath: dragData.effect.importPath,
409
+ effectConfig: dragData.effect.config,
410
+ clientId: previewServerState.clientId,
411
+ });
412
+ if (result.success) {
413
+ (0, NotificationCenter_1.showNotification)(`Added ${dragData.effect.name}()`, 2000);
414
+ }
415
+ else {
416
+ (0, NotificationCenter_1.showNotification)(result.reason, 4000);
417
+ }
418
+ }
419
+ catch (err) {
420
+ (0, NotificationCenter_1.showNotification)(err.message, 4000);
421
+ }
422
+ }, [canDropEffect, nodePath, previewServerState, validatedLocation]);
423
+ const trackRow = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: nestedDepth, eye: canToggleVisibility ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: hasExpandableContent ? (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: onToggleExpand, label: "track properties", disabled: !previewConnected || nodePathInfo === null })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {})), style: rowStyle, selected: selected, selectable: selectable, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, outerHeight: outerHeight, onDragLeave: canDropEffect ? onEffectDragLeave : undefined, onDragOver: canDropEffect ? onEffectDragOver : undefined, onDrop: canDropEffect ? onEffectDrop : undefined, onDoubleClick: TimelineSelection_1.SELECTION_ENABLED && canOpenInEditor
318
424
  ? onShowInEditorDoubleClick
319
425
  : undefined, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [
320
426
  jsx_runtime_1.jsx(TimelineSequenceName_1.TimelineSequenceName, { sequence: sequence, selected: selected, containsSelection: containsSelection }), mediaSrc ? jsx_runtime_1.jsx(TimelineMediaInfo_1.TimelineMediaInfo, { src: mediaSrc }) : null, jsx_runtime_1.jsx(TimelineItemStack_1.TimelineItemStack, { originalLocation: originalLocation })
@@ -323,6 +429,6 @@ const TimelineListItem = ({ nestedDepth, sequence, nodePathInfo }) => {
323
429
  isExpanded &&
324
430
  hasExpandableContent &&
325
431
  nodePathInfo &&
326
- validatedLocation ? (jsx_runtime_1.jsx(TimelineExpandedSection_1.TimelineExpandedSection, { sequence: sequence, validatedLocation: validatedLocation, nodePathInfo: nodePathInfo, nestedDepth: nestedDepth })) : null] }));
432
+ validatedLocation ? (jsx_runtime_1.jsx(TimelineExpandedSection_1.TimelineExpandedSection, { sequence: sequence, validatedLocation: validatedLocation, nodePathInfo: nodePathInfo, nestedDepth: nestedDepth, keyframeDisplayOffset: keyframeDisplayOffset })) : null] }));
327
433
  };
328
- exports.TimelineListItem = TimelineListItem;
434
+ exports.TimelineSequenceItem = TimelineSequenceItem;
@@ -3,11 +3,12 @@ import type { SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
3
3
  import type { CodePosition } from '../../error-overlay/react-overlay/utils/get-source-map';
4
4
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
5
5
  import type { SchemaFieldInfo } from '../../helpers/timeline-layout';
6
- export declare const TimelineFieldRow: React.FC<{
6
+ export declare const TimelineSequencePropItem: React.FC<{
7
7
  readonly field: SchemaFieldInfo;
8
8
  readonly validatedLocation: CodePosition;
9
9
  readonly rowDepth: number;
10
10
  readonly nodePath: SequencePropsSubscriptionKey;
11
11
  readonly nodePathInfo: SequenceNodePathInfo;
12
12
  readonly schema: SequenceSchema;
13
+ readonly keyframeDisplayOffset: number;
13
14
  }>;
@@ -1,14 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TimelineFieldRow = void 0;
3
+ exports.TimelineSequencePropItem = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
7
  const client_id_1 = require("../../helpers/client-id");
8
+ const ContextMenu_1 = require("../ContextMenu");
8
9
  const save_sequence_prop_1 = require("./save-sequence-prop");
9
10
  const timeline_field_row_layout_1 = require("./timeline-field-row-layout");
10
11
  const TimelineExpandArrowButton_1 = require("./TimelineExpandArrowButton");
11
12
  const TimelineFieldLabel_1 = require("./TimelineFieldLabel");
13
+ const TimelineKeyframeControls_1 = require("./TimelineKeyframeControls");
14
+ const TimelineKeyframedValue_1 = require("./TimelineKeyframedValue");
12
15
  const TimelineLayerEye_1 = require("./TimelineLayerEye");
13
16
  const TimelineRowChrome_1 = require("./TimelineRowChrome");
14
17
  const TimelineSchemaField_1 = require("./TimelineSchemaField");
@@ -86,22 +89,95 @@ const Value = ({ field, nodePath, validatedLocation, schema, codeValue }) => {
86
89
  }, [clearDragOverrides, nodePath]);
87
90
  return (jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineFieldValue, { field: field, propStatus: codeValue, onSave: onSave, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd, effectiveValue: effectiveValue }));
88
91
  };
89
- const TimelineFieldRow = ({ field, validatedLocation, rowDepth, nodePath, nodePathInfo, schema }) => {
92
+ const TimelineSequencePropItem = ({ field, validatedLocation, rowDepth, nodePath, nodePathInfo, schema, keyframeDisplayOffset, }) => {
90
93
  var _a, _b;
91
94
  const { codeValues: visualModeCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
95
+ const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
96
+ const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
97
+ const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
92
98
  const selection = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
93
99
  const codeValuesForOverride = remotion_1.Internals.getCodeValuesCtx(visualModeCodeValues, nodePath);
94
100
  const codeValue = (_a = codeValuesForOverride === null || codeValuesForOverride === void 0 ? void 0 : codeValuesForOverride[field.key]) !== null && _a !== void 0 ? _a : null;
101
+ const dragOverrideValue = (0, react_1.useMemo)(() => {
102
+ var _a;
103
+ return ((_a = getDragOverrides(nodePath)) !== null && _a !== void 0 ? _a : {})[field.key];
104
+ }, [getDragOverrides, nodePath, field.key]);
105
+ const keyframeControls = codeValue !== null &&
106
+ (0, TimelineKeyframeControls_1.shouldShowTimelineKeyframeControls)({
107
+ propStatus: codeValue,
108
+ selected: selection.selected,
109
+ }) ? (jsx_runtime_1.jsx(TimelineKeyframeControls_1.TimelineKeyframeControls, { fieldKey: field.key, propStatus: codeValue, nodePath: nodePath, fileName: validatedLocation.source, keyframeDisplayOffset: keyframeDisplayOffset, defaultValue: field.fieldSchema.default, dragOverrideValue: dragOverrideValue, schema: schema, effectIndex: null })) : null;
95
110
  const style = (0, react_1.useMemo)(() => {
96
111
  return {
97
112
  ...fieldRowBase,
98
113
  height: field.rowHeight,
99
114
  };
100
115
  }, [field.rowHeight]);
116
+ const isNonDefault = (0, react_1.useMemo)(() => {
117
+ var _a;
118
+ if (!codeValue || !codeValue.canUpdate) {
119
+ return false;
120
+ }
121
+ const effectiveCodeValue = (_a = codeValue.codeValue) !== null && _a !== void 0 ? _a : field.fieldSchema.default;
122
+ return (JSON.stringify(effectiveCodeValue) !==
123
+ JSON.stringify(field.fieldSchema.default));
124
+ }, [codeValue, field.fieldSchema.default]);
125
+ const canPerformReset = previewServerState.type === 'connected' &&
126
+ codeValue !== null &&
127
+ codeValue.canUpdate;
128
+ const onReset = (0, react_1.useCallback)(() => {
129
+ if (!canPerformReset ||
130
+ previewServerState.type !== 'connected' ||
131
+ codeValue === null ||
132
+ !isNonDefault) {
133
+ return;
134
+ }
135
+ const defaultValue = field.fieldSchema.default !== undefined
136
+ ? JSON.stringify(field.fieldSchema.default)
137
+ : null;
138
+ (0, save_sequence_prop_1.saveSequenceProp)({
139
+ fileName: validatedLocation.source,
140
+ nodePath,
141
+ fieldKey: field.key,
142
+ value: field.fieldSchema.default,
143
+ defaultValue,
144
+ schema,
145
+ setCodeValues,
146
+ clientId: previewServerState.clientId,
147
+ });
148
+ }, [
149
+ canPerformReset,
150
+ field.fieldSchema.default,
151
+ field.key,
152
+ isNonDefault,
153
+ nodePath,
154
+ previewServerState,
155
+ schema,
156
+ setCodeValues,
157
+ validatedLocation.source,
158
+ codeValue,
159
+ ]);
160
+ const contextMenuValues = (0, react_1.useMemo)(() => {
161
+ return [
162
+ {
163
+ type: 'item',
164
+ id: 'reset-sequence-field',
165
+ keyHint: null,
166
+ label: 'Reset',
167
+ leftItem: null,
168
+ disabled: !canPerformReset,
169
+ onClick: onReset,
170
+ quickSwitcherLabel: null,
171
+ subMenu: null,
172
+ value: 'reset-sequence-field',
173
+ },
174
+ ];
175
+ }, [canPerformReset, onReset]);
101
176
  if (codeValue === null) {
102
177
  return null;
103
178
  }
104
- return (jsx_runtime_1.jsxs(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {}), arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {}), style: style, selected: selection.selected, selectable: selection.selectable, onSelect: selection.onSelect, showSelectedBackground: true, containsSelection: false, outerHeight: null, children: [
105
- jsx_runtime_1.jsx(TimelineFieldLabel_1.TimelineFieldLabel, { rowDepth: rowDepth, selected: selection.selected, label: (_b = field.description) !== null && _b !== void 0 ? _b : field.key }), codeValue.canUpdate ? (jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(Value, { field: field, nodePath: nodePath, validatedLocation: validatedLocation, schema: schema, codeValue: codeValue }) })) : (jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineNonEditableStatus, { propStatus: codeValue }) }))] }));
179
+ const row = (jsx_runtime_1.jsxs(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {}), keyframeControls: keyframeControls, arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {}), style: style, selected: selection.selected, selectable: selection.selectable, onSelect: selection.onSelect, showSelectedBackground: true, containsSelection: false, outerHeight: null, children: [
180
+ jsx_runtime_1.jsx(TimelineFieldLabel_1.TimelineFieldLabel, { rowDepth: rowDepth, selected: selection.selected, label: (_b = field.description) !== null && _b !== void 0 ? _b : field.key }), codeValue.canUpdate ? (jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(Value, { field: field, nodePath: nodePath, validatedLocation: validatedLocation, schema: schema, codeValue: codeValue }) })) : codeValue.reason === 'keyframed' ? (jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(TimelineKeyframedValue_1.TimelineKeyframedValue, { field: field, propStatus: codeValue, keyframeDisplayOffset: keyframeDisplayOffset }) })) : (jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineNonEditableStatus, { propStatus: codeValue }) }))] }));
181
+ return (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: selection.selectable ? selection.onSelect : null, children: row }));
106
182
  };
107
- exports.TimelineFieldRow = TimelineFieldRow;
183
+ exports.TimelineSequencePropItem = TimelineSequencePropItem;
@@ -14,7 +14,6 @@ const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
14
14
  exports.TIMELINE_TIME_INDICATOR_HEIGHT = 39;
15
15
  const container = {
16
16
  height: exports.TIMELINE_TIME_INDICATOR_HEIGHT,
17
- boxShadow: `0 0 4px ${colors_1.TIMELINE_BACKGROUND}`,
18
17
  position: 'absolute',
19
18
  backgroundColor: colors_1.TIMELINE_BACKGROUND,
20
19
  top: 0,
@@ -42,10 +42,12 @@ const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
42
42
  const TimelineExpandedTrackKeyframes_1 = require("./TimelineExpandedTrackKeyframes");
43
43
  const TimelineSelection_1 = require("./TimelineSelection");
44
44
  const TimelineSequence_1 = require("./TimelineSequence");
45
+ const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
45
46
  const TimelineTrackUnmemoized = ({ track }) => {
46
47
  const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
47
48
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
48
49
  const previewServerConnected = previewServerState.type === 'connected';
50
+ const timelineWidth = (0, react_1.useContext)(TimelineWidthProvider_1.TimelineWidthContext);
49
51
  const { selected: rowSelected } = (0, TimelineSelection_1.useTimelineRowSelection)(track.nodePathInfo);
50
52
  const containsSelection = (0, TimelineSelection_1.useTimelineRowContainsSelection)(track.nodePathInfo);
51
53
  const layerStyle = (0, react_1.useMemo)(() => ({
@@ -58,7 +60,7 @@ const TimelineTrackUnmemoized = ({ track }) => {
58
60
  getIsExpanded(track.nodePathInfo);
59
61
  const showRowHighlight = track.nodePathInfo !== null && (rowSelected || containsSelection);
60
62
  return (jsx_runtime_1.jsxs("div", { children: [
61
- jsx_runtime_1.jsxs("div", { style: layerStyle, children: [showRowHighlight ? (jsx_runtime_1.jsx("div", { style: TimelineSelection_1.TIMELINE_SELECTED_TRACK_HIGHLIGHT_STYLE })) : null, jsx_runtime_1.jsx(TimelineSequence_1.TimelineSequence, { s: track.sequence })
63
+ jsx_runtime_1.jsxs("div", { style: layerStyle, children: [showRowHighlight && timelineWidth !== null ? (jsx_runtime_1.jsx("div", { style: (0, TimelineSelection_1.getTimelineSelectedTrackHighlightStyle)(timelineWidth) })) : null, jsx_runtime_1.jsx(TimelineSequence_1.TimelineSequence, { s: track.sequence, nodePathInfo: track.nodePathInfo })
62
64
  ] }), showExpandedKeyframes && track.nodePathInfo ? (jsx_runtime_1.jsx(TimelineExpandedTrackKeyframes_1.TimelineExpandedTrackKeyframes, { sequence: track.sequence, nodePathInfo: track.nodePathInfo, keyframeDisplayOffset: track.keyframeDisplayOffset })) : null] }));
63
65
  };
64
66
  exports.TimelineTrack = react_1.default.memo(TimelineTrackUnmemoized);
@@ -5,20 +5,13 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const InputDragger_1 = require("../NewComposition/InputDragger");
7
7
  const timeline_field_utils_1 = require("./timeline-field-utils");
8
+ const timeline_translate_utils_1 = require("./timeline-translate-utils");
8
9
  const leftDraggerStyle = {
9
10
  paddingLeft: 0,
10
11
  };
11
12
  const rightDraggerStyle = {
12
13
  paddingRight: 0,
13
14
  };
14
- const PIXEL_PATTERN = /^(-?\d+(?:\.\d+)?)px(?:\s+(-?\d+(?:\.\d+)?)px)?$/;
15
- const parseTranslate = (value) => {
16
- const m = value.match(PIXEL_PATTERN);
17
- if (!m) {
18
- return [0, 0];
19
- }
20
- return [Number(m[1]), m[2] !== undefined ? Number(m[2]) : 0];
21
- };
22
15
  const containerStyle = {
23
16
  display: 'flex',
24
17
  gap: 4,
@@ -27,8 +20,7 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
27
20
  var _a;
28
21
  const [dragX, setDragX] = (0, react_1.useState)(null);
29
22
  const [dragY, setDragY] = (0, react_1.useState)(null);
30
- const [codeX, codeY] = (0, react_1.useMemo)(() => parseTranslate(String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : '0px 0px')), [effectiveValue]);
31
- const makeString = (0, react_1.useCallback)((x, y) => `${x}px ${y}px`, []);
23
+ const [codeX, codeY] = (0, react_1.useMemo)(() => (0, timeline_translate_utils_1.parseTranslate)(String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : '0px 0px')), [effectiveValue]);
32
24
  const step = field.fieldSchema.type === 'translate' ? ((_a = field.fieldSchema.step) !== null && _a !== void 0 ? _a : 1) : 1;
33
25
  const stepDecimals = (0, react_1.useMemo)(() => (0, timeline_field_utils_1.getDecimalPlaces)(step), [step]);
34
26
  const formatter = (0, react_1.useCallback)((v) => {
@@ -41,11 +33,11 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
41
33
  const onXChange = (0, react_1.useCallback)((newVal) => {
42
34
  setDragX(newVal);
43
35
  const currentY = dragY !== null && dragY !== void 0 ? dragY : codeY;
44
- onDragValueChange(makeString(newVal, currentY));
45
- }, [onDragValueChange, dragY, codeY, makeString]);
36
+ onDragValueChange((0, timeline_translate_utils_1.serializeTranslate)(newVal, currentY));
37
+ }, [onDragValueChange, dragY, codeY]);
46
38
  const onXChangeEnd = (0, react_1.useCallback)((newVal) => {
47
39
  const currentY = dragY !== null && dragY !== void 0 ? dragY : codeY;
48
- const newStr = makeString(newVal, currentY);
40
+ const newStr = (0, timeline_translate_utils_1.serializeTranslate)(newVal, currentY);
49
41
  if (propStatus.canUpdate && newStr !== propStatus.codeValue) {
50
42
  onSave(newStr).finally(() => {
51
43
  setDragX(null);
@@ -56,13 +48,13 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
56
48
  setDragX(null);
57
49
  onDragEnd();
58
50
  }
59
- }, [dragY, codeY, makeString, propStatus, onSave, onDragEnd]);
51
+ }, [dragY, codeY, propStatus, onSave, onDragEnd]);
60
52
  const onXTextChange = (0, react_1.useCallback)((newVal) => {
61
53
  if (propStatus.canUpdate) {
62
54
  const parsed = Number(newVal);
63
55
  if (!Number.isNaN(parsed)) {
64
56
  const currentY = dragY !== null && dragY !== void 0 ? dragY : codeY;
65
- const newStr = makeString(parsed, currentY);
57
+ const newStr = (0, timeline_translate_utils_1.serializeTranslate)(parsed, currentY);
66
58
  if (newStr !== propStatus.codeValue) {
67
59
  setDragX(parsed);
68
60
  onSave(newStr).finally(() => {
@@ -71,16 +63,16 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
71
63
  }
72
64
  }
73
65
  }
74
- }, [propStatus, dragY, codeY, makeString, onSave]);
66
+ }, [propStatus, dragY, codeY, onSave]);
75
67
  // --- Y callbacks ---
76
68
  const onYChange = (0, react_1.useCallback)((newVal) => {
77
69
  setDragY(newVal);
78
70
  const currentX = dragX !== null && dragX !== void 0 ? dragX : codeX;
79
- onDragValueChange(makeString(currentX, newVal));
80
- }, [onDragValueChange, dragX, codeX, makeString]);
71
+ onDragValueChange((0, timeline_translate_utils_1.serializeTranslate)(currentX, newVal));
72
+ }, [onDragValueChange, dragX, codeX]);
81
73
  const onYChangeEnd = (0, react_1.useCallback)((newVal) => {
82
74
  const currentX = dragX !== null && dragX !== void 0 ? dragX : codeX;
83
- const newStr = makeString(currentX, newVal);
75
+ const newStr = (0, timeline_translate_utils_1.serializeTranslate)(currentX, newVal);
84
76
  if (propStatus.canUpdate && newStr !== propStatus.codeValue) {
85
77
  onSave(newStr).finally(() => {
86
78
  setDragY(null);
@@ -91,13 +83,13 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
91
83
  setDragY(null);
92
84
  onDragEnd();
93
85
  }
94
- }, [dragX, codeX, makeString, propStatus, onSave, onDragEnd]);
86
+ }, [dragX, codeX, propStatus, onSave, onDragEnd]);
95
87
  const onYTextChange = (0, react_1.useCallback)((newVal) => {
96
88
  if (propStatus.canUpdate) {
97
89
  const parsed = Number(newVal);
98
90
  if (!Number.isNaN(parsed)) {
99
91
  const currentX = dragX !== null && dragX !== void 0 ? dragX : codeX;
100
- const newStr = makeString(currentX, parsed);
92
+ const newStr = (0, timeline_translate_utils_1.serializeTranslate)(currentX, parsed);
101
93
  if (newStr !== propStatus.codeValue) {
102
94
  setDragY(parsed);
103
95
  onSave(newStr).finally(() => {
@@ -106,7 +98,7 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
106
98
  }
107
99
  }
108
100
  }
109
- }, [propStatus, onSave, dragX, codeX, makeString]);
101
+ }, [propStatus, onSave, dragX, codeX]);
110
102
  return (jsx_runtime_1.jsxs("span", { style: containerStyle, children: [
111
103
  jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragX !== null && dragX !== void 0 ? dragX : codeX, style: leftDraggerStyle, status: "ok", small: true, onValueChange: onXChange, onValueChangeEnd: onXChangeEnd, onTextChange: onXTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false }), jsx_runtime_1.jsx("div", { style: { marginLeft: -6, marginRight: -6 } }), jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragY !== null && dragY !== void 0 ? dragY : codeY, style: rightDraggerStyle, status: "ok", small: true, onValueChange: onYChange, onValueChangeEnd: onYChangeEnd, onTextChange: onYTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false })
112
104
  ] }));
@@ -0,0 +1,23 @@
1
+ import type { SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
2
+ import type { SetCodeValues } from './save-sequence-prop';
3
+ export declare const callAddSequenceKeyframe: ({ fileName, nodePath, fieldKey, sourceFrame, value, schema, setCodeValues, clientId, }: {
4
+ fileName: string;
5
+ nodePath: SequencePropsSubscriptionKey;
6
+ fieldKey: string;
7
+ sourceFrame: number;
8
+ value: unknown;
9
+ schema: SequenceSchema;
10
+ setCodeValues: SetCodeValues;
11
+ clientId: string;
12
+ }) => Promise<void>;
13
+ export declare const callAddEffectKeyframe: ({ fileName, nodePath, effectIndex, fieldKey, sourceFrame, value, schema, setCodeValues, clientId, }: {
14
+ fileName: string;
15
+ nodePath: SequencePropsSubscriptionKey;
16
+ effectIndex: number;
17
+ fieldKey: string;
18
+ sourceFrame: number;
19
+ value: unknown;
20
+ schema: SequenceSchema;
21
+ setCodeValues: SetCodeValues;
22
+ clientId: string;
23
+ }) => Promise<void>;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.callAddEffectKeyframe = exports.callAddSequenceKeyframe = void 0;
4
+ const studio_shared_1 = require("@remotion/studio-shared");
5
+ const call_api_1 = require("../call-api");
6
+ const save_prop_queue_1 = require("./save-prop-queue");
7
+ const callAddSequenceKeyframe = ({ fileName, nodePath, fieldKey, sourceFrame, value, schema, setCodeValues, clientId, }) => {
8
+ return (0, save_prop_queue_1.enqueueSavePropChange)({
9
+ nodePath,
10
+ setCodeValues,
11
+ applyOptimistic: (prev) => (0, studio_shared_1.optimisticAddSequenceKeyframe)({
12
+ previous: prev,
13
+ fieldKey,
14
+ frame: sourceFrame,
15
+ value,
16
+ }),
17
+ apiCall: () => (0, call_api_1.callApi)('/api/add-sequence-keyframe', {
18
+ fileName,
19
+ nodePath,
20
+ key: fieldKey,
21
+ frame: sourceFrame,
22
+ value: JSON.stringify(value),
23
+ schema,
24
+ clientId,
25
+ }),
26
+ errorLabel: 'Could not add keyframe',
27
+ });
28
+ };
29
+ exports.callAddSequenceKeyframe = callAddSequenceKeyframe;
30
+ const callAddEffectKeyframe = ({ fileName, nodePath, effectIndex, fieldKey, sourceFrame, value, schema, setCodeValues, clientId, }) => {
31
+ return (0, save_prop_queue_1.enqueueSavePropChange)({
32
+ nodePath,
33
+ setCodeValues,
34
+ applyOptimistic: (prev) => (0, studio_shared_1.optimisticAddEffectKeyframe)({
35
+ previous: prev,
36
+ effectIndex,
37
+ fieldKey,
38
+ frame: sourceFrame,
39
+ value,
40
+ }),
41
+ apiCall: () => (0, call_api_1.callApi)('/api/add-effect-keyframe', {
42
+ fileName,
43
+ sequenceNodePath: nodePath,
44
+ effectIndex,
45
+ key: fieldKey,
46
+ frame: sourceFrame,
47
+ value: JSON.stringify(value),
48
+ schema,
49
+ clientId,
50
+ }),
51
+ errorLabel: 'Could not add keyframe',
52
+ });
53
+ };
54
+ exports.callAddEffectKeyframe = callAddEffectKeyframe;
@@ -0,0 +1,37 @@
1
+ import type { SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
2
+ import type { SetCodeValues } from './save-sequence-prop';
3
+ export type DeleteSequenceKeyframeChange = {
4
+ fileName: string;
5
+ nodePath: SequencePropsSubscriptionKey;
6
+ fieldKey: string;
7
+ sourceFrame: number;
8
+ schema: SequenceSchema;
9
+ };
10
+ export type DeleteEffectKeyframeChange = DeleteSequenceKeyframeChange & {
11
+ effectIndex: number;
12
+ };
13
+ export declare const callDeleteSequenceKeyframe: ({ fileName, nodePath, fieldKey, sourceFrame, schema, setCodeValues, clientId, }: {
14
+ fileName: string;
15
+ nodePath: SequencePropsSubscriptionKey;
16
+ fieldKey: string;
17
+ sourceFrame: number;
18
+ schema: SequenceSchema;
19
+ setCodeValues: SetCodeValues;
20
+ clientId: string;
21
+ }) => Promise<void>;
22
+ export declare const callDeleteEffectKeyframe: ({ fileName, nodePath, effectIndex, fieldKey, sourceFrame, schema, setCodeValues, clientId, }: {
23
+ fileName: string;
24
+ nodePath: SequencePropsSubscriptionKey;
25
+ effectIndex: number;
26
+ fieldKey: string;
27
+ sourceFrame: number;
28
+ schema: SequenceSchema;
29
+ setCodeValues: SetCodeValues;
30
+ clientId: string;
31
+ }) => Promise<void>;
32
+ export declare const callDeleteKeyframes: ({ sequenceKeyframes, effectKeyframes, setCodeValues, clientId, }: {
33
+ sequenceKeyframes: DeleteSequenceKeyframeChange[];
34
+ effectKeyframes: DeleteEffectKeyframeChange[];
35
+ setCodeValues: SetCodeValues;
36
+ clientId: string;
37
+ }) => Promise<void>;