@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
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.callDeleteKeyframes = exports.callDeleteEffectKeyframe = exports.callDeleteSequenceKeyframe = 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 groupByNodePath = (keyframes) => {
8
+ var _a;
9
+ const groups = new Map();
10
+ for (const keyframe of keyframes) {
11
+ const key = JSON.stringify(keyframe.nodePath);
12
+ const group = (_a = groups.get(key)) !== null && _a !== void 0 ? _a : [];
13
+ group.push(keyframe);
14
+ groups.set(key, group);
15
+ }
16
+ return [...groups.values()];
17
+ };
18
+ const callDeleteSequenceKeyframe = ({ fileName, nodePath, fieldKey, sourceFrame, schema, setCodeValues, clientId, }) => {
19
+ return (0, save_prop_queue_1.enqueueSavePropChange)({
20
+ nodePath,
21
+ setCodeValues,
22
+ applyOptimistic: (prev) => (0, studio_shared_1.optimisticDeleteSequenceKeyframe)({
23
+ previous: prev,
24
+ fieldKey,
25
+ frame: sourceFrame,
26
+ }),
27
+ apiCall: () => (0, call_api_1.callApi)('/api/delete-keyframes', {
28
+ sequenceKeyframes: [
29
+ {
30
+ fileName,
31
+ nodePath,
32
+ key: fieldKey,
33
+ frame: sourceFrame,
34
+ schema,
35
+ },
36
+ ],
37
+ effectKeyframes: [],
38
+ clientId,
39
+ }),
40
+ errorLabel: 'Could not delete keyframe',
41
+ });
42
+ };
43
+ exports.callDeleteSequenceKeyframe = callDeleteSequenceKeyframe;
44
+ const callDeleteEffectKeyframe = ({ fileName, nodePath, effectIndex, fieldKey, sourceFrame, schema, setCodeValues, clientId, }) => {
45
+ return (0, save_prop_queue_1.enqueueSavePropChange)({
46
+ nodePath,
47
+ setCodeValues,
48
+ applyOptimistic: (prev) => (0, studio_shared_1.optimisticDeleteEffectKeyframe)({
49
+ previous: prev,
50
+ effectIndex,
51
+ fieldKey,
52
+ frame: sourceFrame,
53
+ }),
54
+ apiCall: () => (0, call_api_1.callApi)('/api/delete-keyframes', {
55
+ sequenceKeyframes: [],
56
+ effectKeyframes: [
57
+ {
58
+ fileName,
59
+ sequenceNodePath: nodePath,
60
+ effectIndex,
61
+ key: fieldKey,
62
+ frame: sourceFrame,
63
+ schema,
64
+ },
65
+ ],
66
+ clientId,
67
+ }),
68
+ errorLabel: 'Could not delete keyframe',
69
+ });
70
+ };
71
+ exports.callDeleteEffectKeyframe = callDeleteEffectKeyframe;
72
+ const callDeleteKeyframes = ({ sequenceKeyframes, effectKeyframes, setCodeValues, clientId, }) => {
73
+ if (sequenceKeyframes.length === 0 && effectKeyframes.length === 0) {
74
+ return Promise.resolve();
75
+ }
76
+ for (const keyframes of groupByNodePath(sequenceKeyframes)) {
77
+ const [firstKeyframe] = keyframes;
78
+ if (!firstKeyframe) {
79
+ continue;
80
+ }
81
+ setCodeValues(firstKeyframe.nodePath, (prev) => (0, studio_shared_1.optimisticDeleteSequenceKeyframes)({
82
+ previous: prev,
83
+ keyframes: keyframes.map((keyframe) => ({
84
+ fieldKey: keyframe.fieldKey,
85
+ frame: keyframe.sourceFrame,
86
+ })),
87
+ }));
88
+ }
89
+ for (const keyframes of groupByNodePath(effectKeyframes)) {
90
+ const [firstKeyframe] = keyframes;
91
+ if (!firstKeyframe) {
92
+ continue;
93
+ }
94
+ setCodeValues(firstKeyframe.nodePath, (prev) => (0, studio_shared_1.optimisticDeleteEffectKeyframes)({
95
+ previous: prev,
96
+ keyframes: keyframes.map((keyframe) => ({
97
+ effectIndex: keyframe.effectIndex,
98
+ fieldKey: keyframe.fieldKey,
99
+ frame: keyframe.sourceFrame,
100
+ })),
101
+ }));
102
+ }
103
+ return (0, call_api_1.callApi)('/api/delete-keyframes', {
104
+ sequenceKeyframes: sequenceKeyframes.map((keyframe) => ({
105
+ fileName: keyframe.fileName,
106
+ nodePath: keyframe.nodePath,
107
+ key: keyframe.fieldKey,
108
+ frame: keyframe.sourceFrame,
109
+ schema: keyframe.schema,
110
+ })),
111
+ effectKeyframes: effectKeyframes.map((keyframe) => ({
112
+ fileName: keyframe.fileName,
113
+ sequenceNodePath: keyframe.nodePath,
114
+ effectIndex: keyframe.effectIndex,
115
+ key: keyframe.fieldKey,
116
+ frame: keyframe.sourceFrame,
117
+ schema: keyframe.schema,
118
+ })),
119
+ clientId,
120
+ }).then(() => undefined);
121
+ };
122
+ exports.callDeleteKeyframes = callDeleteKeyframes;
@@ -0,0 +1,21 @@
1
+ import type { OverrideIdToNodePaths, TSequence } from 'remotion';
2
+ import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
3
+ import type { SetCodeValues } from './save-sequence-prop';
4
+ export declare const deleteSelectedKeyframe: ({ nodePathInfo, frame, sequences, overrideIdsToNodePaths, setCodeValues, clientId, }: {
5
+ nodePathInfo: SequenceNodePathInfo;
6
+ frame: number;
7
+ sequences: TSequence[];
8
+ overrideIdsToNodePaths: OverrideIdToNodePaths;
9
+ setCodeValues: SetCodeValues;
10
+ clientId: string;
11
+ }) => Promise<void> | null;
12
+ export declare const deleteSelectedKeyframes: ({ keyframes, sequences, overrideIdsToNodePaths, setCodeValues, clientId, }: {
13
+ keyframes: {
14
+ nodePathInfo: SequenceNodePathInfo;
15
+ frame: number;
16
+ }[];
17
+ sequences: TSequence[];
18
+ overrideIdsToNodePaths: OverrideIdToNodePaths;
19
+ setCodeValues: SetCodeValues;
20
+ clientId: string;
21
+ }) => Promise<void> | null;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteSelectedKeyframes = exports.deleteSelectedKeyframe = void 0;
4
+ const call_delete_keyframe_1 = require("./call-delete-keyframe");
5
+ const find_track_for_node_path_info_1 = require("./find-track-for-node-path-info");
6
+ const parse_keyframe_field_from_node_path_1 = require("./parse-keyframe-field-from-node-path");
7
+ const getSelectedKeyframeDeletion = ({ nodePathInfo, frame, sequences, overrideIdsToNodePaths, }) => {
8
+ var _a, _b;
9
+ const field = (0, parse_keyframe_field_from_node_path_1.parseKeyframeFieldFromNodePath)(nodePathInfo.auxiliaryKeys);
10
+ if (field === null) {
11
+ return null;
12
+ }
13
+ const track = (0, find_track_for_node_path_info_1.findTrackForNodePathInfo)({
14
+ sequences,
15
+ overrideIdsToNodePaths,
16
+ nodePathInfo,
17
+ });
18
+ const sequence = (_a = track === null || track === void 0 ? void 0 : track.sequence) !== null && _a !== void 0 ? _a : null;
19
+ if (!(sequence === null || sequence === void 0 ? void 0 : sequence.controls)) {
20
+ return null;
21
+ }
22
+ const sourceFrame = frame - ((_b = track === null || track === void 0 ? void 0 : track.keyframeDisplayOffset) !== null && _b !== void 0 ? _b : 0);
23
+ const nodePath = nodePathInfo.sequenceSubscriptionKey;
24
+ const fileName = nodePath.absolutePath;
25
+ if (field.type === 'effect') {
26
+ const effect = sequence.effects[field.effectIndex];
27
+ if (!effect) {
28
+ return null;
29
+ }
30
+ return {
31
+ type: 'effect',
32
+ fileName,
33
+ nodePath,
34
+ effectIndex: field.effectIndex,
35
+ fieldKey: field.fieldKey,
36
+ sourceFrame,
37
+ schema: effect.schema,
38
+ };
39
+ }
40
+ return {
41
+ type: 'sequence',
42
+ fileName,
43
+ nodePath,
44
+ fieldKey: field.fieldKey,
45
+ sourceFrame,
46
+ schema: sequence.controls.schema,
47
+ };
48
+ };
49
+ const deleteSelectedKeyframe = ({ nodePathInfo, frame, sequences, overrideIdsToNodePaths, setCodeValues, clientId, }) => {
50
+ const deletion = getSelectedKeyframeDeletion({
51
+ nodePathInfo,
52
+ frame,
53
+ sequences,
54
+ overrideIdsToNodePaths,
55
+ });
56
+ if (deletion === null) {
57
+ return null;
58
+ }
59
+ if (deletion.type === 'effect') {
60
+ return (0, call_delete_keyframe_1.callDeleteEffectKeyframe)({
61
+ ...deletion,
62
+ setCodeValues,
63
+ clientId,
64
+ });
65
+ }
66
+ return (0, call_delete_keyframe_1.callDeleteSequenceKeyframe)({
67
+ ...deletion,
68
+ setCodeValues,
69
+ clientId,
70
+ });
71
+ };
72
+ exports.deleteSelectedKeyframe = deleteSelectedKeyframe;
73
+ const deleteSelectedKeyframes = ({ keyframes, sequences, overrideIdsToNodePaths, setCodeValues, clientId, }) => {
74
+ const deletions = keyframes
75
+ .map((keyframe) => getSelectedKeyframeDeletion({
76
+ nodePathInfo: keyframe.nodePathInfo,
77
+ frame: keyframe.frame,
78
+ sequences,
79
+ overrideIdsToNodePaths,
80
+ }))
81
+ .filter((deletion) => deletion !== null);
82
+ if (deletions.length === 0) {
83
+ return null;
84
+ }
85
+ return (0, call_delete_keyframe_1.callDeleteKeyframes)({
86
+ sequenceKeyframes: deletions.filter((deletion) => deletion.type === 'sequence'),
87
+ effectKeyframes: deletions.filter((deletion) => deletion.type === 'effect'),
88
+ setCodeValues,
89
+ clientId,
90
+ });
91
+ };
92
+ exports.deleteSelectedKeyframes = deleteSelectedKeyframes;
@@ -0,0 +1,17 @@
1
+ import type { OverrideIdToNodePaths, TSequence } from 'remotion';
2
+ import type { SetCodeValues } from './save-sequence-prop';
3
+ import type { TimelineSelection } from './TimelineSelection';
4
+ export declare const deleteSelectedTimelineItem: ({ selection, sequences, overrideIdsToNodePaths, setCodeValues, clientId, }: {
5
+ selection: TimelineSelection;
6
+ sequences: TSequence[];
7
+ overrideIdsToNodePaths: OverrideIdToNodePaths;
8
+ setCodeValues: SetCodeValues;
9
+ clientId: string;
10
+ }) => Promise<void> | null;
11
+ export declare const deleteSelectedTimelineItems: ({ selections, sequences, overrideIdsToNodePaths, setCodeValues, clientId, }: {
12
+ selections: readonly TimelineSelection[];
13
+ sequences: TSequence[];
14
+ overrideIdsToNodePaths: OverrideIdToNodePaths;
15
+ setCodeValues: SetCodeValues;
16
+ clientId: string;
17
+ }) => Promise<void> | null;
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteSelectedTimelineItems = exports.deleteSelectedTimelineItem = void 0;
4
+ const call_api_1 = require("../call-api");
5
+ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
6
+ const delete_selected_keyframe_1 = require("./delete-selected-keyframe");
7
+ const confirmDeletingDuplicatedSequences = (nodePathInfos) => {
8
+ const duplicatedNodePathInfos = nodePathInfos.filter((nodePathInfo) => nodePathInfo.numberOfSequencesWithThisNodePath > 1);
9
+ if (duplicatedNodePathInfos.length === 0) {
10
+ return true;
11
+ }
12
+ if (duplicatedNodePathInfos.length === 1) {
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);
19
+ }
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);
24
+ };
25
+ const deleteSequences = (nodePathInfos) => {
26
+ if (!confirmDeletingDuplicatedSequences(nodePathInfos)) {
27
+ return Promise.resolve();
28
+ }
29
+ return (0, call_api_1.callApi)('/api/delete-jsx-node', {
30
+ nodes: nodePathInfos.map((nodePathInfo) => {
31
+ const nodePath = nodePathInfo.sequenceSubscriptionKey;
32
+ return {
33
+ fileName: nodePath.absolutePath,
34
+ nodePath: nodePath.nodePath,
35
+ };
36
+ }),
37
+ })
38
+ .then((result) => {
39
+ if (result.success) {
40
+ (0, NotificationCenter_1.showNotification)(nodePathInfos.length === 1
41
+ ? 'Removed sequence from source file'
42
+ : 'Removed sequences from source files', 2000);
43
+ }
44
+ else {
45
+ (0, NotificationCenter_1.showNotification)(result.reason, 4000);
46
+ }
47
+ })
48
+ .catch((err) => {
49
+ (0, NotificationCenter_1.showNotification)(err.message, 4000);
50
+ });
51
+ };
52
+ const deleteEffects = (effects) => {
53
+ if (effects.length === 0) {
54
+ return Promise.resolve();
55
+ }
56
+ return (0, call_api_1.callApi)('/api/delete-effect', effects.map((effect) => {
57
+ const nodePath = effect.nodePathInfo.sequenceSubscriptionKey;
58
+ return effect.type === 'single-effect'
59
+ ? {
60
+ type: 'single-effect',
61
+ fileName: nodePath.absolutePath,
62
+ sequenceNodePath: nodePath,
63
+ effectIndex: effect.effectIndex,
64
+ }
65
+ : {
66
+ type: 'all-effects',
67
+ fileName: nodePath.absolutePath,
68
+ sequenceNodePath: nodePath,
69
+ };
70
+ }))
71
+ .then((result) => {
72
+ if (result.success) {
73
+ const singleEffect = effects[0];
74
+ (0, NotificationCenter_1.showNotification)(effects.length === 1 && (singleEffect === null || singleEffect === void 0 ? void 0 : singleEffect.type) === 'single-effect'
75
+ ? 'Removed effect from source file'
76
+ : effects.length === 1
77
+ ? 'Removed effects from source file'
78
+ : 'Removed effects from source files', 2000);
79
+ }
80
+ else {
81
+ (0, NotificationCenter_1.showNotification)(result.reason, 4000);
82
+ }
83
+ })
84
+ .catch((err) => {
85
+ (0, NotificationCenter_1.showNotification)(err.message, 4000);
86
+ });
87
+ };
88
+ const deleteSelectedTimelineItem = ({ selection, sequences, overrideIdsToNodePaths, setCodeValues, clientId, }) => {
89
+ if (selection.type === 'keyframe') {
90
+ return (0, delete_selected_keyframe_1.deleteSelectedKeyframe)({
91
+ nodePathInfo: selection.nodePathInfo,
92
+ frame: selection.frame,
93
+ sequences,
94
+ overrideIdsToNodePaths,
95
+ setCodeValues,
96
+ clientId,
97
+ });
98
+ }
99
+ switch (selection.type) {
100
+ case 'sequence':
101
+ return deleteSequences([selection.nodePathInfo]);
102
+ case 'sequence-effect':
103
+ return deleteEffects([
104
+ {
105
+ type: 'single-effect',
106
+ nodePathInfo: selection.nodePathInfo,
107
+ effectIndex: selection.i,
108
+ },
109
+ ]);
110
+ case 'sequence-prop':
111
+ case 'sequence-effect-prop':
112
+ return null;
113
+ case 'sequence-all-effects':
114
+ return deleteEffects([
115
+ { type: 'all-effects', nodePathInfo: selection.nodePathInfo },
116
+ ]);
117
+ default:
118
+ throw new Error(`Unexpected timeline selection type: ${selection}`);
119
+ }
120
+ };
121
+ exports.deleteSelectedTimelineItem = deleteSelectedTimelineItem;
122
+ const isSequenceRowSelection = (selection) => selection.type === 'sequence';
123
+ const isSequenceEffectSelection = (selection) => selection.type === 'sequence-effect';
124
+ const isSequenceAllEffectsSelection = (selection) => selection.type === 'sequence-all-effects';
125
+ const isKeyframeSelection = (selection) => selection.type === 'keyframe';
126
+ const assertTimelineSelectionsHaveSameType = (selections) => {
127
+ const firstSelection = selections[0];
128
+ if (!firstSelection) {
129
+ return;
130
+ }
131
+ for (const selection of selections) {
132
+ if (selection.type !== firstSelection.type) {
133
+ throw new Error(`Assertion failed: Cannot delete timeline selections of different types (${firstSelection.type}, ${selection.type})`);
134
+ }
135
+ }
136
+ };
137
+ const deleteSelectedTimelineItems = ({ selections, sequences, overrideIdsToNodePaths, setCodeValues, clientId, }) => {
138
+ const firstSelection = selections[0];
139
+ if (!firstSelection) {
140
+ return null;
141
+ }
142
+ assertTimelineSelectionsHaveSameType(selections);
143
+ switch (firstSelection.type) {
144
+ case 'sequence':
145
+ return deleteSequences(selections
146
+ .filter(isSequenceRowSelection)
147
+ .map((selection) => selection.nodePathInfo));
148
+ case 'sequence-effect':
149
+ return deleteEffects(selections.filter(isSequenceEffectSelection).map((selection) => ({
150
+ type: 'single-effect',
151
+ nodePathInfo: selection.nodePathInfo,
152
+ effectIndex: selection.i,
153
+ })));
154
+ case 'keyframe': {
155
+ return (0, delete_selected_keyframe_1.deleteSelectedKeyframes)({
156
+ keyframes: selections.filter(isKeyframeSelection).map((selection) => ({
157
+ nodePathInfo: selection.nodePathInfo,
158
+ frame: selection.frame,
159
+ })),
160
+ sequences,
161
+ overrideIdsToNodePaths,
162
+ setCodeValues,
163
+ clientId,
164
+ });
165
+ }
166
+ case 'sequence-prop':
167
+ case 'sequence-effect-prop':
168
+ return null;
169
+ case 'sequence-all-effects':
170
+ return deleteEffects(selections.filter(isSequenceAllEffectsSelection).map((selection) => ({
171
+ type: 'all-effects',
172
+ nodePathInfo: selection.nodePathInfo,
173
+ })));
174
+ default:
175
+ throw new Error(`Unexpected timeline selection type: ${firstSelection}`);
176
+ }
177
+ };
178
+ exports.deleteSelectedTimelineItems = deleteSelectedTimelineItems;
@@ -0,0 +1,13 @@
1
+ import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
2
+ import type { TimelineSelection } from './TimelineSelection';
3
+ export declare const duplicateSequencesFromSource: (nodePathInfos: readonly SequenceNodePathInfo[]) => Promise<void>;
4
+ export declare const isDuplicatableSequenceRowSelection: (selection: TimelineSelection) => selection is {
5
+ readonly nodePathInfo: SequenceNodePathInfo;
6
+ } & {
7
+ readonly type: "sequence";
8
+ } & {
9
+ type: "sequence";
10
+ };
11
+ export declare const duplicateSelectedTimelineItems: ({ selections, }: {
12
+ selections: readonly TimelineSelection[];
13
+ }) => Promise<void> | null;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.duplicateSelectedTimelineItems = exports.isDuplicatableSequenceRowSelection = exports.duplicateSequencesFromSource = void 0;
4
+ const call_api_1 = require("../call-api");
5
+ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
6
+ const confirmDuplicatingProgrammaticallyDuplicatedSequences = (nodePathInfos) => {
7
+ if (nodePathInfos.length === 0) {
8
+ return true;
9
+ }
10
+ if (nodePathInfos.length === 1) {
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);
17
+ }
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);
22
+ };
23
+ const duplicateSequence = (nodePathInfo) => {
24
+ const nodePath = nodePathInfo.sequenceSubscriptionKey;
25
+ return (0, call_api_1.callApi)('/api/duplicate-jsx-node', {
26
+ fileName: nodePath.absolutePath,
27
+ nodePath: nodePath.nodePath,
28
+ });
29
+ };
30
+ const duplicateSequencesFromSource = (nodePathInfos) => {
31
+ const programmaticallyDuplicated = nodePathInfos.filter((nodePathInfo) => nodePathInfo.numberOfSequencesWithThisNodePath > 1);
32
+ 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;
47
+ }
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);
54
+ });
55
+ };
56
+ exports.duplicateSequencesFromSource = duplicateSequencesFromSource;
57
+ const isDuplicatableSequenceRowSelection = (selection) => selection.type === 'sequence';
58
+ exports.isDuplicatableSequenceRowSelection = isDuplicatableSequenceRowSelection;
59
+ const duplicateSelectedTimelineItems = ({ selections, }) => {
60
+ const sequenceSelections = selections.filter(exports.isDuplicatableSequenceRowSelection);
61
+ if (sequenceSelections.length === 0) {
62
+ return null;
63
+ }
64
+ return (0, exports.duplicateSequencesFromSource)(sequenceSelections.map((selection) => selection.nodePathInfo));
65
+ };
66
+ exports.duplicateSelectedTimelineItems = duplicateSelectedTimelineItems;
@@ -0,0 +1,7 @@
1
+ import type { OverrideIdToNodePaths, TSequence } from 'remotion';
2
+ import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
3
+ export declare const findTrackForNodePathInfo: ({ sequences, overrideIdsToNodePaths, nodePathInfo, }: {
4
+ sequences: TSequence[];
5
+ overrideIdsToNodePaths: OverrideIdToNodePaths;
6
+ nodePathInfo: SequenceNodePathInfo;
7
+ }) => import("../../helpers/get-timeline-sequence-sort-key").TrackWithHash | undefined;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findTrackForNodePathInfo = void 0;
4
+ const studio_shared_1 = require("@remotion/studio-shared");
5
+ const calculate_timeline_1 = require("../../helpers/calculate-timeline");
6
+ const findTrackForNodePathInfo = ({ sequences, overrideIdsToNodePaths, nodePathInfo, }) => {
7
+ const tracks = (0, calculate_timeline_1.calculateTimeline)({ sequences, overrideIdsToNodePaths });
8
+ return tracks.find((candidate) => candidate.nodePathInfo !== null &&
9
+ (0, studio_shared_1.stringifySequenceSubscriptionKey)(candidate.nodePathInfo.sequenceSubscriptionKey) ===
10
+ (0, studio_shared_1.stringifySequenceSubscriptionKey)(nodePathInfo.sequenceSubscriptionKey) &&
11
+ candidate.nodePathInfo.index === nodePathInfo.index);
12
+ };
13
+ exports.findTrackForNodePathInfo = findTrackForNodePathInfo;
@@ -0,0 +1,9 @@
1
+ export declare const getPreviousKeyframeDisplayFrame: (keyframes: readonly {
2
+ frame: number;
3
+ }[], currentDisplayFrame: number) => number | null;
4
+ export declare const getNextKeyframeDisplayFrame: (keyframes: readonly {
5
+ frame: number;
6
+ }[], currentDisplayFrame: number) => number | null;
7
+ export declare const hasKeyframeAtSourceFrame: (keyframes: readonly {
8
+ frame: number;
9
+ }[], sourceFrame: number) => boolean;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasKeyframeAtSourceFrame = exports.getNextKeyframeDisplayFrame = exports.getPreviousKeyframeDisplayFrame = void 0;
4
+ const getPreviousKeyframeDisplayFrame = (keyframes, currentDisplayFrame) => {
5
+ let previous = null;
6
+ for (const keyframe of keyframes) {
7
+ if (keyframe.frame < currentDisplayFrame) {
8
+ previous = keyframe.frame;
9
+ }
10
+ }
11
+ return previous;
12
+ };
13
+ exports.getPreviousKeyframeDisplayFrame = getPreviousKeyframeDisplayFrame;
14
+ const getNextKeyframeDisplayFrame = (keyframes, currentDisplayFrame) => {
15
+ for (const keyframe of keyframes) {
16
+ if (keyframe.frame > currentDisplayFrame) {
17
+ return keyframe.frame;
18
+ }
19
+ }
20
+ return null;
21
+ };
22
+ exports.getNextKeyframeDisplayFrame = getNextKeyframeDisplayFrame;
23
+ const hasKeyframeAtSourceFrame = (keyframes, sourceFrame) => {
24
+ return keyframes.some((keyframe) => keyframe.frame === sourceFrame);
25
+ };
26
+ exports.hasKeyframeAtSourceFrame = hasKeyframeAtSourceFrame;
@@ -0,0 +1,8 @@
1
+ export declare const parseKeyframeFieldFromNodePath: (auxiliaryKeys: string[]) => {
2
+ readonly type: "sequence";
3
+ readonly fieldKey: string;
4
+ } | {
5
+ readonly type: "effect";
6
+ readonly effectIndex: number;
7
+ readonly fieldKey: string;
8
+ } | null;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseKeyframeFieldFromNodePath = void 0;
4
+ const parseKeyframeFieldFromNodePath = (auxiliaryKeys) => {
5
+ // Sequence control field: ['controls', fieldKey]
6
+ if (auxiliaryKeys[0] === 'controls' && auxiliaryKeys.length >= 2) {
7
+ return {
8
+ type: 'sequence',
9
+ fieldKey: auxiliaryKeys[1],
10
+ };
11
+ }
12
+ // Effect field: ['effects', effectIndex, fieldKey]
13
+ if (auxiliaryKeys[0] === 'effects' && auxiliaryKeys.length >= 3) {
14
+ const effectIndex = Number(auxiliaryKeys[1]);
15
+ if (!Number.isInteger(effectIndex) || effectIndex < 0) {
16
+ return null;
17
+ }
18
+ return {
19
+ type: 'effect',
20
+ effectIndex,
21
+ fieldKey: auxiliaryKeys[2],
22
+ };
23
+ }
24
+ return null;
25
+ };
26
+ exports.parseKeyframeFieldFromNodePath = parseKeyframeFieldFromNodePath;
@@ -0,0 +1,38 @@
1
+ import type { CodeValues, OverrideIdToNodePaths, SequencePropsSubscriptionKey, SequenceSchema, TSequence } from 'remotion';
2
+ import type { SetCodeValues } from './save-sequence-prop';
3
+ import type { TimelineSelection } from './TimelineSelection';
4
+ type SequencePropResetTarget = {
5
+ readonly type: 'sequence-prop';
6
+ readonly fileName: string;
7
+ readonly nodePath: SequencePropsSubscriptionKey;
8
+ readonly fieldKey: string;
9
+ readonly value: unknown;
10
+ readonly defaultValue: string | null;
11
+ readonly schema: SequenceSchema;
12
+ };
13
+ type EffectPropResetTarget = {
14
+ readonly type: 'effect-prop';
15
+ readonly fileName: string;
16
+ readonly nodePath: SequencePropsSubscriptionKey;
17
+ readonly effectIndex: number;
18
+ readonly fieldKey: string;
19
+ readonly value: unknown;
20
+ readonly defaultValue: string | null;
21
+ readonly schema: SequenceSchema;
22
+ };
23
+ type TimelinePropResetTarget = SequencePropResetTarget | EffectPropResetTarget;
24
+ export declare const getTimelinePropResetTargets: ({ selections, sequences, overrideIdsToNodePaths, codeValues, }: {
25
+ readonly selections: readonly TimelineSelection[];
26
+ readonly sequences: TSequence[];
27
+ readonly overrideIdsToNodePaths: OverrideIdToNodePaths;
28
+ readonly codeValues: CodeValues;
29
+ }) => TimelinePropResetTarget[] | null;
30
+ export declare const resetSelectedTimelineProps: ({ selections, sequences, overrideIdsToNodePaths, codeValues, setCodeValues, clientId, }: {
31
+ readonly selections: readonly TimelineSelection[];
32
+ readonly sequences: TSequence[];
33
+ readonly overrideIdsToNodePaths: OverrideIdToNodePaths;
34
+ readonly codeValues: CodeValues;
35
+ readonly setCodeValues: SetCodeValues;
36
+ readonly clientId: string;
37
+ }) => Promise<void> | null;
38
+ export {};