@remotion/studio 4.0.483 → 4.0.485

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 (113) hide show
  1. package/dist/components/ColorPicker/ColorPicker.js +65 -3
  2. package/dist/components/ColorPicker/ColorPickerPopup.d.ts +1 -0
  3. package/dist/components/ColorPicker/ColorPickerPopup.js +3 -2
  4. package/dist/components/ContextMenu.js +75 -1
  5. package/dist/components/CurrentComposition.js +3 -2
  6. package/dist/components/InlineCompositionName.d.ts +7 -0
  7. package/dist/components/InlineCompositionName.js +58 -0
  8. package/dist/components/InlineEditableTitle.d.ts +7 -0
  9. package/dist/components/InlineEditableTitle.js +129 -0
  10. package/dist/components/InspectorPanel/EasingInspector.js +184 -10
  11. package/dist/components/InspectorPanel/KeyframeEasingNavigator.d.ts +14 -0
  12. package/dist/components/InspectorPanel/KeyframeEasingNavigator.js +146 -0
  13. package/dist/components/InspectorPanel/KeyframeInspector.d.ts +1 -1
  14. package/dist/components/InspectorPanel/KeyframeInspector.js +229 -5
  15. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +17 -0
  16. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +80 -0
  17. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +4 -58
  18. package/dist/components/InspectorPanel/common.d.ts +12 -0
  19. package/dist/components/InspectorPanel/common.js +78 -1
  20. package/dist/components/InspectorPanel/easing-inspector-selection.d.ts +14 -0
  21. package/dist/components/InspectorPanel/easing-inspector-selection.js +18 -0
  22. package/dist/components/InspectorPanel/keyframe-easing-navigator-items.d.ts +24 -0
  23. package/dist/components/InspectorPanel/keyframe-easing-navigator-items.js +40 -0
  24. package/dist/components/InspectorPanel/keyframe-inspector-frame.d.ts +8 -0
  25. package/dist/components/InspectorPanel/keyframe-inspector-frame.js +14 -0
  26. package/dist/components/InspectorPanel/styles.d.ts +1 -0
  27. package/dist/components/InspectorPanel/styles.js +9 -3
  28. package/dist/components/InspectorSequenceSection.js +37 -10
  29. package/dist/components/Modals.js +1 -1
  30. package/dist/components/NewComposition/CodemodFooter.d.ts +7 -1
  31. package/dist/components/NewComposition/CodemodFooter.js +17 -12
  32. package/dist/components/NewComposition/DeleteComposition.js +7 -1
  33. package/dist/components/NewComposition/DeleteFolder.js +7 -1
  34. package/dist/components/NewComposition/DuplicateComposition.js +17 -10
  35. package/dist/components/NewComposition/InputAndValidationContainer.d.ts +3 -0
  36. package/dist/components/NewComposition/InputAndValidationContainer.js +15 -0
  37. package/dist/components/NewComposition/NewCompDuration.js +7 -6
  38. package/dist/components/NewComposition/NewComposition.d.ts +5 -1
  39. package/dist/components/NewComposition/NewComposition.js +29 -86
  40. package/dist/components/NewComposition/RenameComposition.js +13 -14
  41. package/dist/components/NewComposition/RenameFolder.js +9 -2
  42. package/dist/components/NewComposition/RenameStaticFile.js +2 -1
  43. package/dist/components/NewComposition/ValidationMessage.js +9 -1
  44. package/dist/components/OptionsPanel.d.ts +0 -3
  45. package/dist/components/OptionsPanel.js +7 -3
  46. package/dist/components/Preview.js +1 -1
  47. package/dist/components/RenderModal/ServerRenderModal.js +4 -3
  48. package/dist/components/RenderModal/WebRenderModal.js +2 -1
  49. package/dist/components/SelectedOutlineElement.js +45 -3
  50. package/dist/components/SelectedOutlineOverlay.d.ts +3 -1
  51. package/dist/components/SelectedOutlineOverlay.js +48 -15
  52. package/dist/components/Timeline/EasingEditorModal.js +9 -4
  53. package/dist/components/Timeline/TimelineDeleteKeybindings.js +45 -2
  54. package/dist/components/Timeline/TimelineEffectPropItem.js +82 -1
  55. package/dist/components/Timeline/TimelineExpandedSection.js +1 -0
  56. package/dist/components/Timeline/TimelineInOutPointerHandle.js +2 -1
  57. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +1 -1
  58. package/dist/components/Timeline/TimelineKeyframeControls.js +38 -7
  59. package/dist/components/Timeline/TimelineKeyframeEasingLine.d.ts +4 -0
  60. package/dist/components/Timeline/TimelineKeyframeEasingLine.js +12 -6
  61. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +4 -0
  62. package/dist/components/Timeline/TimelineSelection.js +1 -0
  63. package/dist/components/Timeline/TimelineSequenceItem.js +13 -62
  64. package/dist/components/Timeline/TimelineSequenceName.d.ts +1 -0
  65. package/dist/components/Timeline/TimelineSequenceName.js +7 -6
  66. package/dist/components/Timeline/TimelineSequencePropItem.d.ts +1 -1
  67. package/dist/components/Timeline/TimelineSequencePropItem.js +86 -4
  68. package/dist/components/Timeline/TimelineSlider.js +17 -3
  69. package/dist/components/Timeline/TimelineTextContentField.d.ts +12 -0
  70. package/dist/components/Timeline/TimelineTextContentField.js +100 -0
  71. package/dist/components/Timeline/TimelineWidthProvider.js +18 -3
  72. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +8 -2
  73. package/dist/components/Timeline/delete-selected-timeline-item.js +80 -1
  74. package/dist/components/Timeline/focus-inspector-field.d.ts +16 -0
  75. package/dist/components/Timeline/focus-inspector-field.js +49 -0
  76. package/dist/components/Timeline/get-animation-item-selection-for-frame.d.ts +18 -0
  77. package/dist/components/Timeline/get-animation-item-selection-for-frame.js +49 -0
  78. package/dist/components/Timeline/get-easing-selection-after-keyframe-delete.d.ts +15 -0
  79. package/dist/components/Timeline/get-easing-selection-after-keyframe-delete.js +26 -0
  80. package/dist/components/Timeline/save-sequence-prop.js +2 -0
  81. package/dist/components/Timeline/split-selected-timeline-item.d.ts +38 -0
  82. package/dist/components/Timeline/split-selected-timeline-item.js +156 -0
  83. package/dist/components/Timeline/timeline-field-display-utils.js +2 -0
  84. package/dist/components/Timeline/update-selected-easing.d.ts +1 -0
  85. package/dist/components/Timeline/update-selected-easing.js +4 -3
  86. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +1 -0
  87. package/dist/components/Timeline/use-rename-sequence.d.ts +30 -0
  88. package/dist/components/Timeline/use-rename-sequence.js +115 -0
  89. package/dist/components/Timeline/use-timeline-expanded-tree.d.ts +2 -1
  90. package/dist/components/Timeline/use-timeline-expanded-tree.js +3 -1
  91. package/dist/components/Timeline/use-timeline-height.js +1 -0
  92. package/dist/components/composition-menu-items.js +3 -0
  93. package/dist/components/folder-menu-items.js +20 -0
  94. package/dist/components/options-sidebar-tabs.d.ts +4 -0
  95. package/dist/components/options-sidebar-tabs.js +5 -0
  96. package/dist/components/selected-outline-types.d.ts +6 -1
  97. package/dist/esm/{chunk-fq0j774v.js → chunk-103pp4n7.js} +17652 -15098
  98. package/dist/esm/internals.mjs +17652 -15098
  99. package/dist/esm/previewEntry.mjs +18357 -15803
  100. package/dist/esm/renderEntry.mjs +1 -1
  101. package/dist/helpers/render-codec-label.d.ts +1 -1
  102. package/dist/helpers/timeline-layout.d.ts +4 -3
  103. package/dist/helpers/timeline-layout.js +3 -1
  104. package/dist/helpers/use-create-composition.d.ts +35 -0
  105. package/dist/helpers/use-create-composition.js +111 -0
  106. package/dist/helpers/use-menu-structure.js +0 -14
  107. package/dist/helpers/use-rename-composition.d.ts +16 -0
  108. package/dist/helpers/use-rename-composition.js +49 -0
  109. package/dist/state/modals.d.ts +3 -0
  110. package/dist/state/timeline-zoom.js +17 -14
  111. package/dist/state/z-index.d.ts +1 -0
  112. package/dist/state/z-index.js +11 -2
  113. package/package.json +12 -12
@@ -63,6 +63,7 @@ const TimelineRowChrome_1 = require("./TimelineRowChrome");
63
63
  const TimelineSelection_1 = require("./TimelineSelection");
64
64
  const TimelineSequenceName_1 = require("./TimelineSequenceName");
65
65
  const use_open_sequence_in_editor_1 = require("./use-open-sequence-in-editor");
66
+ const use_rename_sequence_1 = require("./use-rename-sequence");
66
67
  const use_sequence_freeze_frame_menu_item_1 = require("./use-sequence-freeze-frame-menu-item");
67
68
  const use_timeline_expanded_tree_1 = require("./use-timeline-expanded-tree");
68
69
  const labelContainerStyle = {
@@ -83,6 +84,7 @@ const TimelineSequenceExpandArrow = ({ disabled, isExpanded, nodePathInfo, onTog
83
84
  const { filteredTree } = (0, use_timeline_expanded_tree_1.useTimelineExpandedTree)({
84
85
  sequence,
85
86
  nodePathInfo,
87
+ includeTextContent: false,
86
88
  });
87
89
  if (filteredTree.length === 0) {
88
90
  return jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {});
@@ -157,7 +159,6 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
157
159
  const previewConnected = previewServerState.type === 'connected';
158
160
  const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
159
161
  const { toggleTrack } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksSetterContext);
160
- const { propStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
161
162
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
162
163
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
163
164
  const { isHighestContext } = (0, use_keybinding_1.useKeybinding)();
@@ -188,6 +189,14 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
188
189
  column: (_a = originalLocation.column) !== null && _a !== void 0 ? _a : 0,
189
190
  };
190
191
  }, [originalLocation]);
192
+ const { canRename: canRenameThisSequence, displayName, fallbackDisplayName, propStatusesForOverride, saveName, } = (0, use_rename_sequence_1.useRenameSequence)({
193
+ clientId: previewServerState.type === 'connected'
194
+ ? previewServerState.clientId
195
+ : null,
196
+ nodePathInfo,
197
+ sequence,
198
+ validatedLocation,
199
+ });
191
200
  const canDeleteFromSource = Boolean(nodePath && (validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source));
192
201
  const nodePathKey = (0, react_1.useMemo)(() => nodePath ? remotion_1.Internals.makeSequencePropsSubscriptionKey(nodePath) : null, [nodePath]);
193
202
  const parentId = (_e = sequence.parent) !== null && _e !== void 0 ? _e : null;
@@ -437,13 +446,7 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
437
446
  }
438
447
  toggleTrack(nodePathInfo);
439
448
  }, [nodePathInfo, toggleTrack]);
440
- const propStatusesForOverride = (0, react_1.useMemo)(() => {
441
- return nodePath
442
- ? remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)
443
- : undefined;
444
- }, [propStatuses, nodePath]);
445
449
  const codeHiddenStatus = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.hidden;
446
- const codeNameStatus = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.name;
447
450
  const isItemHidden = (0, react_1.useMemo)(() => {
448
451
  var _a;
449
452
  const propStatus = codeHiddenStatus && codeHiddenStatus.status === 'static'
@@ -453,14 +456,6 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
453
456
  const effective = (propStatus !== null && propStatus !== void 0 ? propStatus : runtimeValue);
454
457
  return effective !== null && effective !== void 0 ? effective : false;
455
458
  }, [codeHiddenStatus, (_a = sequence.controls) === null || _a === void 0 ? void 0 : _a.currentRuntimeValueDotNotation]);
456
- const displayName = (0, react_1.useMemo)(() => {
457
- if (codeNameStatus &&
458
- codeNameStatus.status === 'static' &&
459
- typeof codeNameStatus.codeValue === 'string') {
460
- return codeNameStatus.codeValue;
461
- }
462
- return sequence.displayName;
463
- }, [codeNameStatus, sequence.displayName]);
464
459
  const onToggleVisibility = (0, react_1.useCallback)((type) => {
465
460
  if (!sequence.controls ||
466
461
  !nodePath ||
@@ -529,14 +524,6 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
529
524
  codeHiddenStatus !== undefined &&
530
525
  codeHiddenStatus !== null &&
531
526
  codeHiddenStatus.status === 'static';
532
- const canRenameThisSequence = previewServerState.type === 'connected' &&
533
- !window.remotion_isReadOnlyStudio &&
534
- Boolean(sequence.controls) &&
535
- nodePath !== null &&
536
- validatedLocation !== null &&
537
- codeNameStatus !== undefined &&
538
- codeNameStatus !== null &&
539
- codeNameStatus.status === 'static';
540
527
  const onSequenceDoubleClick = (0, react_1.useCallback)((e) => {
541
528
  if ((0, TimelineSelection_1.isTimelineSelectionModifierEvent)(e)) {
542
529
  e.stopPropagation();
@@ -557,45 +544,9 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
557
544
  setIsRenaming(false);
558
545
  }, []);
559
546
  const onSaveName = (0, react_1.useCallback)(async (name) => {
560
- if (!canRenameThisSequence ||
561
- previewServerState.type !== 'connected' ||
562
- !sequence.controls ||
563
- !nodePath ||
564
- !validatedLocation) {
565
- setIsRenaming(false);
566
- return;
567
- }
568
- if (name === displayName) {
569
- setIsRenaming(false);
570
- return;
571
- }
572
- const savePromise = (0, save_sequence_prop_1.saveSequenceProps)({
573
- changes: [
574
- {
575
- fileName: validatedLocation.source,
576
- nodePath,
577
- fieldKey: 'name',
578
- value: name,
579
- defaultValue: null,
580
- schema: sequence.controls.schema,
581
- },
582
- ],
583
- setPropStatuses,
584
- clientId: previewServerState.clientId,
585
- undoLabel: 'Rename sequence',
586
- redoLabel: 'Rename sequence again',
587
- });
588
547
  setIsRenaming(false);
589
- await savePromise;
590
- }, [
591
- canRenameThisSequence,
592
- displayName,
593
- nodePath,
594
- previewServerState,
595
- sequence.controls,
596
- setPropStatuses,
597
- validatedLocation,
598
- ]);
548
+ await saveName(name);
549
+ }, [saveName]);
599
550
  react_1.default.useEffect(() => {
600
551
  if (!canRenameSelectedSequence || !process.env.KEYBOARD_SHORTCUTS_ENABLED) {
601
552
  setIsRenaming(false);
@@ -805,7 +756,7 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
805
756
  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 && nodePathInfo !== null ? (jsx_runtime_1.jsx(TimelineSequenceExpandArrow, { disabled: !previewConnected, isExpanded: isExpanded, nodePathInfo: nodePathInfo, onToggleExpand: onToggleExpand, sequence: sequence })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {})), style: rowStyle, selected: selected, selectable: selectable, selectionItem: selectionItem, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, outerHeight: outerHeight, onDragLeave: canDropEffect ? onEffectDragLeave : undefined, onDragOver: canDropEffect ? onEffectDragOver : undefined, onDrop: canDropEffect ? onEffectDrop : undefined, onDoubleClick: canRenameThisSequence || canOpenInEditor
806
757
  ? onSequenceDoubleClick
807
758
  : undefined, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [
808
- jsx_runtime_1.jsx(TimelineSequenceName_1.TimelineSequenceName, { displayName: displayName, selected: selected, containsSelection: containsSelection, editing: isRenaming, onCancelEditing: onCancelRenaming, onSaveName: onSaveName }), mediaSrc ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
759
+ jsx_runtime_1.jsx(TimelineSequenceName_1.TimelineSequenceName, { displayName: displayName, fallbackDisplayName: fallbackDisplayName, selected: selected, containsSelection: containsSelection, editing: isRenaming, onCancelEditing: onCancelRenaming, onSaveName: onSaveName }), mediaSrc ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
809
760
  jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }),
810
761
  " ",
811
762
  jsx_runtime_1.jsx(TimelineMediaInfo_1.TimelineMediaInfo, { src: mediaSrc })
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  export declare const TimelineSequenceName: React.FC<{
3
3
  readonly displayName: string;
4
+ readonly fallbackDisplayName: string;
4
5
  readonly selected: boolean;
5
6
  readonly containsSelection: boolean;
6
7
  readonly editing: boolean;
@@ -13,7 +13,7 @@ const getTruncatedDisplayName = (displayName) => {
13
13
  }
14
14
  return displayName;
15
15
  };
16
- const TimelineSequenceName = ({ displayName, selected, containsSelection, editing, onCancelEditing, onSaveName, }) => {
16
+ const TimelineSequenceName = ({ displayName, fallbackDisplayName, selected, containsSelection, editing, onCancelEditing, onSaveName, }) => {
17
17
  const inputRef = (0, react_1.useRef)(null);
18
18
  const [draftName, setDraftName] = (0, react_1.useState)(displayName);
19
19
  const cancelNextBlurRef = (0, react_1.useRef)(false);
@@ -53,10 +53,11 @@ const TimelineSequenceName = ({ displayName, selected, containsSelection, editin
53
53
  WebkitUserSelect: 'text',
54
54
  };
55
55
  }, [style]);
56
- const text = getTruncatedDisplayName(displayName) || '<Sequence>';
56
+ const editableDisplayName = displayName || fallbackDisplayName;
57
+ const text = getTruncatedDisplayName(editableDisplayName);
57
58
  (0, react_1.useEffect)(() => {
58
59
  if (!editing) {
59
- setDraftName(displayName);
60
+ setDraftName(editableDisplayName);
60
61
  return;
61
62
  }
62
63
  const input = inputRef.current;
@@ -64,10 +65,10 @@ const TimelineSequenceName = ({ displayName, selected, containsSelection, editin
64
65
  return;
65
66
  }
66
67
  input.focus();
67
- const basenameIndex = displayName.lastIndexOf('.');
68
- const selectionEnd = basenameIndex > 0 ? basenameIndex : displayName.length;
68
+ const basenameIndex = editableDisplayName.lastIndexOf('.');
69
+ const selectionEnd = basenameIndex > 0 ? basenameIndex : editableDisplayName.length;
69
70
  input.setSelectionRange(0, selectionEnd);
70
- }, [displayName, editing]);
71
+ }, [editableDisplayName, editing]);
71
72
  const save = (0, react_1.useCallback)(() => {
72
73
  onSaveName(draftName).catch(() => undefined);
73
74
  }, [draftName, onSaveName]);
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { CanUpdateSequencePropStatusKeyframed, SequencePropsSubscriptionKey, InteractivitySchema } from 'remotion';
2
+ import type { CanUpdateSequencePropStatusKeyframed, InteractivitySchema, SequencePropsSubscriptionKey } 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';
@@ -9,6 +9,7 @@ const client_id_1 = require("../../helpers/client-id");
9
9
  const modals_1 = require("../../state/modals");
10
10
  const ContextMenu_1 = require("../ContextMenu");
11
11
  const call_add_keyframe_1 = require("./call-add-keyframe");
12
+ const get_animation_item_selection_for_frame_1 = require("./get-animation-item-selection-for-frame");
12
13
  const save_sequence_prop_1 = require("./save-sequence-prop");
13
14
  const timeline_field_row_layout_1 = require("./timeline-field-row-layout");
14
15
  const TimelineExpandArrowButton_1 = require("./TimelineExpandArrowButton");
@@ -19,6 +20,7 @@ const TimelineLayerEye_1 = require("./TimelineLayerEye");
19
20
  const TimelineRowChrome_1 = require("./TimelineRowChrome");
20
21
  const TimelineSchemaField_1 = require("./TimelineSchemaField");
21
22
  const TimelineSelection_1 = require("./TimelineSelection");
23
+ const update_selected_easing_1 = require("./update-selected-easing");
22
24
  const fieldRowBase = {};
23
25
  const isKeyframedStatus = (status) => {
24
26
  return status.status === 'keyframed';
@@ -62,9 +64,11 @@ const Value = ({ field, nodePath, validatedLocation, schema, propStatus }) => {
62
64
  if (!clientId) {
63
65
  return Promise.reject(new Error('Not connected to studio server'));
64
66
  }
65
- const defaultValue = field.fieldSchema.default !== undefined
66
- ? JSON.stringify(field.fieldSchema.default)
67
- : null;
67
+ const defaultValue = field.fieldSchema.type === 'text-content'
68
+ ? null
69
+ : field.fieldSchema.default !== undefined
70
+ ? JSON.stringify(field.fieldSchema.default)
71
+ : null;
68
72
  const stringifiedValue = JSON.stringify(value);
69
73
  const fieldLabel = (_a = field.description) !== null && _a !== void 0 ? _a : field.key;
70
74
  if (value === propStatus.codeValue) {
@@ -95,6 +99,7 @@ const Value = ({ field, nodePath, validatedLocation, schema, propStatus }) => {
95
99
  clientId,
96
100
  field.description,
97
101
  field.fieldSchema.default,
102
+ field.fieldSchema.type,
98
103
  field.key,
99
104
  nodePath,
100
105
  schema,
@@ -162,6 +167,9 @@ const TimelineSequencePropItem = ({ field, validatedLocation, rowDepth, nodePath
162
167
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
163
168
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
164
169
  const selection = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
170
+ const { selectItems } = (0, TimelineSelection_1.useTimelineSelection)();
171
+ const setFrame = remotion_1.Internals.useTimelineSetFrame();
172
+ const videoConfig = (0, remotion_1.useVideoConfig)();
165
173
  const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
166
174
  const sourceFrame = timelinePosition - keyframeDisplayOffset;
167
175
  const propStatusesForOverride = remotion_1.Internals.getPropStatusesCtx(visualModePropStatuses, nodePath);
@@ -303,10 +311,84 @@ const TimelineSequencePropItem = ({ field, validatedLocation, rowDepth, nodePath
303
311
  onReset,
304
312
  previewServerState,
305
313
  ]);
314
+ const seekToDisplayFrame = (0, react_1.useCallback)((frame) => {
315
+ setFrame((current) => {
316
+ const next = { ...current, [videoConfig.id]: frame };
317
+ remotion_1.Internals.persistCurrentFrame(next);
318
+ return next;
319
+ });
320
+ }, [setFrame, videoConfig.id]);
321
+ const onPropertyDoubleClick = (0, react_1.useCallback)((event) => {
322
+ if (propStatus === null || propStatus.status === 'computed') {
323
+ return;
324
+ }
325
+ const keyframeSelection = {
326
+ type: 'keyframe',
327
+ nodePathInfo,
328
+ frame: sourceFrame + keyframeDisplayOffset,
329
+ };
330
+ if (propStatus.status === 'static') {
331
+ if (!keyframable || previewServerState.type !== 'connected') {
332
+ return;
333
+ }
334
+ const value = remotion_1.Internals.getEffectiveVisualModeValue({
335
+ propStatus,
336
+ dragOverrideValue,
337
+ frame: sourceFrame,
338
+ defaultValue: field.fieldSchema.default,
339
+ shouldResortToDefaultValueIfUndefined: true,
340
+ });
341
+ event.stopPropagation();
342
+ (0, call_add_keyframe_1.callAddSequenceKeyframe)({
343
+ fileName: validatedLocation.source,
344
+ nodePath,
345
+ fieldKey: field.key,
346
+ sourceFrame,
347
+ value,
348
+ schema,
349
+ setPropStatuses,
350
+ clientId: previewServerState.clientId,
351
+ }).catch(() => undefined);
352
+ selectItems([keyframeSelection], { reveal: true });
353
+ seekToDisplayFrame(keyframeSelection.frame);
354
+ return;
355
+ }
356
+ const targetSelection = (0, get_animation_item_selection_for_frame_1.getAnimationItemSelectionForSourceFrame)({
357
+ includeEasings: (0, update_selected_easing_1.canEditEasingForInterpolationFunction)(propStatus.interpolationFunction),
358
+ keyframeDisplayOffset,
359
+ keyframes: propStatus.keyframes,
360
+ nodePathInfo,
361
+ sourceFrame,
362
+ });
363
+ if (targetSelection === null) {
364
+ return;
365
+ }
366
+ event.stopPropagation();
367
+ selectItems([targetSelection], { reveal: true });
368
+ if (targetSelection.type === 'keyframe') {
369
+ seekToDisplayFrame(targetSelection.frame);
370
+ }
371
+ }, [
372
+ dragOverrideValue,
373
+ field.fieldSchema.default,
374
+ field.key,
375
+ keyframeDisplayOffset,
376
+ keyframable,
377
+ nodePath,
378
+ nodePathInfo,
379
+ previewServerState,
380
+ propStatus,
381
+ schema,
382
+ seekToDisplayFrame,
383
+ selectItems,
384
+ setPropStatuses,
385
+ sourceFrame,
386
+ validatedLocation.source,
387
+ ]);
306
388
  if (propStatus === null) {
307
389
  return null;
308
390
  }
309
- 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, selectionItem: selection.selectionItem, onSelect: selection.onSelect, showSelectedBackground: true, containsSelection: false, outerHeight: null, children: [
391
+ 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, selectionItem: selection.selectionItem, onSelect: selection.onSelect, onDoubleClick: onPropertyDoubleClick, showSelectedBackground: true, containsSelection: false, outerHeight: null, children: [
310
392
  jsx_runtime_1.jsx(TimelineFieldLabel_1.TimelineFieldLabel, { rowDepth: rowDepth, selected: selection.selected, label: (_b = field.description) !== null && _b !== void 0 ? _b : field.key }), isKeyframedStatus(propStatus) ? (jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(exports.TimelineSequenceKeyframedValue, { field: field, fileName: validatedLocation.source, nodePath: nodePath, schema: schema, propStatus: propStatus, sourceFrame: sourceFrame }) })) : propStatus.status === 'static' ? (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, propStatus: propStatus }) })) : (jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineNonEditableStatus, { propStatus: propStatus }) }))] }));
311
393
  return (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: selection.selectable ? selection.onSelect : null, children: row }));
312
394
  };
@@ -16,12 +16,18 @@ const container = {
16
16
  top: 0,
17
17
  pointerEvents: 'none',
18
18
  };
19
+ const PLAYHEAD_LINE_WIDTH = 1;
19
20
  const line = {
20
21
  height: '100vh',
21
- width: 1,
22
+ width: PLAYHEAD_LINE_WIDTH,
22
23
  position: 'fixed',
23
24
  backgroundColor: '#f02c00',
24
25
  };
26
+ const PLAYHEAD_CENTER_OFFSET = PLAYHEAD_LINE_WIDTH / 2;
27
+ const getTimelineSliderTransform = ({ durationInFrames, frame, width, }) => {
28
+ const left = (0, get_left_of_timeline_slider_1.getXPositionOfItemInTimelineImperatively)(frame, durationInFrames, width);
29
+ return `translateX(${left - PLAYHEAD_CENTER_OFFSET}px)`;
30
+ };
25
31
  exports.redrawTimelineSliderFast = (0, react_1.createRef)();
26
32
  const TimelineSlider = () => {
27
33
  const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
@@ -53,7 +59,11 @@ const TimelineSliderInner = () => {
53
59
  if (!el || measuredWidth === undefined || measuredWidth === 0) {
54
60
  return;
55
61
  }
56
- el.style.transform = `translateX(${(0, get_left_of_timeline_slider_1.getXPositionOfItemInTimelineImperatively)(timelinePosition, videoConfig.durationInFrames, measuredWidth)}px)`;
62
+ el.style.transform = getTimelineSliderTransform({
63
+ durationInFrames: videoConfig.durationInFrames,
64
+ frame: timelinePosition,
65
+ width: measuredWidth,
66
+ });
57
67
  }, [
58
68
  timelinePosition,
59
69
  videoConfig.durationInFrames,
@@ -69,7 +79,11 @@ const TimelineSliderInner = () => {
69
79
  if (!current) {
70
80
  throw new Error('unexpectedly did not have ref to timelineslider');
71
81
  }
72
- current.style.transform = `translateX(${(0, get_left_of_timeline_slider_1.getXPositionOfItemInTimelineImperatively)(frame, (0, imperative_state_1.getCurrentDuration)(), (_b = width !== null && width !== void 0 ? width : (_a = timeline_refs_1.sliderAreaRef.current) === null || _a === void 0 ? void 0 : _a.clientWidth) !== null && _b !== void 0 ? _b : 0)}px)`;
82
+ current.style.transform = getTimelineSliderTransform({
83
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
84
+ frame,
85
+ width: (_b = width !== null && width !== void 0 ? width : (_a = timeline_refs_1.sliderAreaRef.current) === null || _a === void 0 ? void 0 : _a.clientWidth) !== null && _b !== void 0 ? _b : 0,
86
+ });
73
87
  },
74
88
  };
75
89
  }, []);
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { CanUpdateSequencePropStatusStatic, SequencePropsSubscriptionKey } from 'remotion';
3
+ import type { SchemaFieldInfo, TimelineFieldOnDragValueChange, TimelineFieldOnSave } from '../../helpers/timeline-layout';
4
+ export declare const TimelineTextContentField: React.FC<{
5
+ readonly field: SchemaFieldInfo;
6
+ readonly effectiveValue: unknown;
7
+ readonly propStatus: CanUpdateSequencePropStatusStatic;
8
+ readonly nodePath: SequencePropsSubscriptionKey | null;
9
+ readonly onDragEnd: () => void;
10
+ readonly onDragValueChange: TimelineFieldOnDragValueChange;
11
+ readonly onSave: TimelineFieldOnSave;
12
+ }>;
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelineTextContentField = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const RemTextarea_1 = require("../NewComposition/RemTextarea");
7
+ const focus_inspector_field_1 = require("./focus-inspector-field");
8
+ const TimelineTextContentField = ({ effectiveValue, field, nodePath, onDragEnd, onDragValueChange, onSave, propStatus, }) => {
9
+ var _a;
10
+ const inputRef = (0, react_1.useRef)(null);
11
+ const currentValue = String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : '');
12
+ const draftRef = (0, react_1.useRef)({
13
+ dirty: false,
14
+ value: currentValue,
15
+ });
16
+ const latestRef = (0, react_1.useRef)({
17
+ codeValue: propStatus.codeValue,
18
+ onDragEnd,
19
+ onDragValueChange,
20
+ onSave,
21
+ });
22
+ latestRef.current = {
23
+ codeValue: propStatus.codeValue,
24
+ onDragEnd,
25
+ onDragValueChange,
26
+ onSave,
27
+ };
28
+ if (!draftRef.current.dirty) {
29
+ draftRef.current.value = currentValue;
30
+ }
31
+ const commitPending = (0, react_1.useCallback)(() => {
32
+ var _a;
33
+ var _b, _c;
34
+ if (!draftRef.current.dirty) {
35
+ return false;
36
+ }
37
+ const value = (_b = (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : draftRef.current.value;
38
+ const savedValue = String((_c = latestRef.current.codeValue) !== null && _c !== void 0 ? _c : '');
39
+ draftRef.current = {
40
+ dirty: false,
41
+ value,
42
+ };
43
+ if (value === savedValue) {
44
+ latestRef.current.onDragEnd();
45
+ return false;
46
+ }
47
+ latestRef.current
48
+ .onSave(value)
49
+ .finally(() => {
50
+ if (!draftRef.current.dirty && draftRef.current.value === value) {
51
+ latestRef.current.onDragEnd();
52
+ }
53
+ })
54
+ .catch(() => undefined);
55
+ return true;
56
+ }, []);
57
+ const setInputRef = (0, react_1.useCallback)((element) => {
58
+ if (element === null && inputRef.current !== null) {
59
+ commitPending();
60
+ }
61
+ inputRef.current = element;
62
+ (0, focus_inspector_field_1.registerFocusInspectorFieldElement)({
63
+ element,
64
+ fieldKey: field.key,
65
+ nodePath,
66
+ });
67
+ (0, focus_inspector_field_1.registerCommitPendingInspectorField)({
68
+ commitPending: element === null ? null : commitPending,
69
+ fieldKey: field.key,
70
+ nodePath,
71
+ });
72
+ }, [commitPending, field.key, nodePath]);
73
+ const onChange = (0, react_1.useCallback)((event) => {
74
+ const { value } = event.currentTarget;
75
+ draftRef.current = {
76
+ dirty: true,
77
+ value,
78
+ };
79
+ latestRef.current.onDragValueChange(value);
80
+ }, []);
81
+ const onKeyDownCapture = (0, react_1.useCallback)((event) => {
82
+ var _a;
83
+ if (event.key === 'Escape') {
84
+ const savedValue = String((_a = latestRef.current.codeValue) !== null && _a !== void 0 ? _a : '');
85
+ draftRef.current = {
86
+ dirty: false,
87
+ value: savedValue,
88
+ };
89
+ event.currentTarget.value = savedValue;
90
+ latestRef.current.onDragEnd();
91
+ event.currentTarget.blur();
92
+ }
93
+ }, []);
94
+ return (jsx_runtime_1.jsx(RemTextarea_1.RemTextarea, { ref: setInputRef, status: "ok", small: true, defaultValue: currentValue, onBlur: commitPending, onChange: onChange, onKeyDownCapture: onKeyDownCapture, style: {
95
+ boxSizing: 'border-box',
96
+ height: 40,
97
+ width: 160,
98
+ } }, String((_a = propStatus.codeValue) !== null && _a !== void 0 ? _a : '')));
99
+ };
100
+ exports.TimelineTextContentField = TimelineTextContentField;
@@ -4,14 +4,29 @@ exports.TimelineWidthProvider = exports.TimelineWidthContext = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const player_1 = require("@remotion/player");
6
6
  const react_1 = require("react");
7
+ const remotion_1 = require("remotion");
8
+ const timeline_zoom_1 = require("../../state/timeline-zoom");
7
9
  const timeline_refs_1 = require("./timeline-refs");
8
10
  exports.TimelineWidthContext = (0, react_1.createContext)(null);
9
11
  const TimelineWidthProvider = ({ children }) => {
10
- var _a;
11
- const size = player_1.PlayerInternals.useElementSize(timeline_refs_1.sliderAreaRef, {
12
+ const size = player_1.PlayerInternals.useElementSize(timeline_refs_1.scrollableRef, {
12
13
  triggerOnWindowResize: false,
13
14
  shouldApplyCssTransforms: true,
14
15
  });
15
- return (jsx_runtime_1.jsx(exports.TimelineWidthContext.Provider, { value: (_a = size === null || size === void 0 ? void 0 : size.width) !== null && _a !== void 0 ? _a : null, children: children }));
16
+ const { zoom: zoomMap } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
17
+ const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
18
+ const width = (0, react_1.useMemo)(() => {
19
+ var _a, _b;
20
+ var _c, _d, _e;
21
+ const zoom = (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition'
22
+ ? ((_c = zoomMap[canvasContent.compositionId]) !== null && _c !== void 0 ? _c : timeline_zoom_1.TIMELINE_MIN_ZOOM)
23
+ : timeline_zoom_1.TIMELINE_MIN_ZOOM;
24
+ const scrollableWidth = (_d = size === null || size === void 0 ? void 0 : size.width) !== null && _d !== void 0 ? _d : (_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.clientWidth;
25
+ if (scrollableWidth === undefined) {
26
+ return (_e = (_b = timeline_refs_1.sliderAreaRef.current) === null || _b === void 0 ? void 0 : _b.clientWidth) !== null && _e !== void 0 ? _e : null;
27
+ }
28
+ return scrollableWidth * zoom;
29
+ }, [canvasContent, size === null || size === void 0 ? void 0 : size.width, zoomMap]);
30
+ return (jsx_runtime_1.jsx(exports.TimelineWidthContext.Provider, { value: width, children: children }));
16
31
  };
17
32
  exports.TimelineWidthProvider = TimelineWidthProvider;
@@ -1,4 +1,4 @@
1
- import type { OverrideIdToNodePaths, TSequence } from 'remotion';
1
+ import type { OverrideIdToNodePaths, PropStatuses, TSequence } from 'remotion';
2
2
  import type { ConfirmationDialogFunction } from '../ConfirmationDialog-types';
3
3
  import type { SetPropStatuses } from './save-sequence-prop';
4
4
  import { type TimelineSelection } from './TimelineSelection';
@@ -10,7 +10,13 @@ export declare const deleteSelectedTimelineItem: ({ selection, sequences, overri
10
10
  clientId: string;
11
11
  confirm: ConfirmationDialogFunction;
12
12
  }) => Promise<boolean> | null;
13
- export declare const getTimelineSelectionAfterDeletingItems: (selections: readonly TimelineSelection[]) => readonly TimelineSelection[];
13
+ export declare const getTimelineSelectionAfterDeletingItems: ({ selections, sequences, overrideIdsToNodePaths, propStatuses, timelinePosition, }: {
14
+ readonly selections: readonly TimelineSelection[];
15
+ readonly sequences?: TSequence[] | undefined;
16
+ readonly overrideIdsToNodePaths?: OverrideIdToNodePaths | undefined;
17
+ readonly propStatuses?: PropStatuses | undefined;
18
+ readonly timelinePosition?: number | undefined;
19
+ }) => readonly TimelineSelection[];
14
20
  export declare const deleteSelectedTimelineItems: ({ selections, sequences, overrideIdsToNodePaths, setPropStatuses, clientId, confirm, }: {
15
21
  selections: readonly TimelineSelection[];
16
22
  sequences: TSequence[];
@@ -1,10 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.deleteSelectedTimelineItems = exports.getTimelineSelectionAfterDeletingItems = exports.deleteSelectedTimelineItem = void 0;
4
+ const remotion_1 = require("remotion");
4
5
  const call_api_1 = require("../call-api");
5
6
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
6
7
  const delete_selected_keyframe_1 = require("./delete-selected-keyframe");
8
+ const find_track_for_node_path_info_1 = require("./find-track-for-node-path-info");
9
+ const get_easing_selection_after_keyframe_delete_1 = require("./get-easing-selection-after-keyframe-delete");
10
+ const parse_keyframe_field_from_node_path_1 = require("./parse-keyframe-field-from-node-path");
7
11
  const TimelineSelection_1 = require("./TimelineSelection");
12
+ const update_selected_easing_1 = require("./update-selected-easing");
8
13
  const confirmDeletingDuplicatedSequences = (nodePathInfos, confirm) => {
9
14
  const duplicatedNodePathInfos = nodePathInfos.filter((nodePathInfo) => nodePathInfo.numberOfSequencesWithThisNodePath > 1);
10
15
  if (duplicatedNodePathInfos.length === 0) {
@@ -150,7 +155,81 @@ const getSequenceSelectionAfterDeletingEffect = (selection) => {
150
155
  },
151
156
  };
152
157
  };
153
- const getTimelineSelectionAfterDeletingItems = (selections) => {
158
+ const getEasingSelectionAfterDeletingKeyframes = ({ selections, sequences, overrideIdsToNodePaths, propStatuses, timelinePosition, }) => {
159
+ var _a;
160
+ if (sequences === undefined ||
161
+ overrideIdsToNodePaths === undefined ||
162
+ propStatuses === undefined ||
163
+ timelinePosition === undefined) {
164
+ return null;
165
+ }
166
+ const keyframeSelections = selections.filter(isKeyframeSelection);
167
+ if (keyframeSelections.length !== 1) {
168
+ return null;
169
+ }
170
+ const [selection] = keyframeSelections;
171
+ if (!selection) {
172
+ return null;
173
+ }
174
+ const field = (0, parse_keyframe_field_from_node_path_1.parseKeyframeFieldFromNodePath)(selection.nodePathInfo.auxiliaryKeys);
175
+ if (field === null) {
176
+ return null;
177
+ }
178
+ const track = (0, find_track_for_node_path_info_1.findTrackForNodePathInfo)({
179
+ sequences,
180
+ overrideIdsToNodePaths,
181
+ nodePathInfo: selection.nodePathInfo,
182
+ });
183
+ if (!track || !track.sequence.controls) {
184
+ return null;
185
+ }
186
+ const nodePath = selection.nodePathInfo.sequenceSubscriptionKey;
187
+ const sourceFrame = selection.frame - track.keyframeDisplayOffset;
188
+ if (field.type === 'sequence') {
189
+ const sequencePropStatus = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a[field.fieldKey];
190
+ if ((sequencePropStatus === null || sequencePropStatus === void 0 ? void 0 : sequencePropStatus.status) !== 'keyframed' ||
191
+ !(0, update_selected_easing_1.canEditEasingForInterpolationFunction)(sequencePropStatus.interpolationFunction)) {
192
+ return null;
193
+ }
194
+ return (0, get_easing_selection_after_keyframe_delete_1.getEasingSelectionAfterKeyframeDelete)({
195
+ deletedSourceFrames: [sourceFrame],
196
+ keyframeDisplayOffset: track.keyframeDisplayOffset,
197
+ nodePathInfo: selection.nodePathInfo,
198
+ propStatus: sequencePropStatus,
199
+ timelinePosition,
200
+ });
201
+ }
202
+ const effectStatus = remotion_1.Internals.getEffectPropStatusesCtx({
203
+ propStatuses,
204
+ nodePath,
205
+ effectIndex: field.effectIndex,
206
+ });
207
+ const effectPropStatus = effectStatus.type === 'can-update-effect'
208
+ ? effectStatus.props[field.fieldKey]
209
+ : null;
210
+ if ((effectPropStatus === null || effectPropStatus === void 0 ? void 0 : effectPropStatus.status) !== 'keyframed' ||
211
+ !(0, update_selected_easing_1.canEditEasingForInterpolationFunction)(effectPropStatus.interpolationFunction)) {
212
+ return null;
213
+ }
214
+ return (0, get_easing_selection_after_keyframe_delete_1.getEasingSelectionAfterKeyframeDelete)({
215
+ deletedSourceFrames: [sourceFrame],
216
+ keyframeDisplayOffset: track.keyframeDisplayOffset,
217
+ nodePathInfo: selection.nodePathInfo,
218
+ propStatus: effectPropStatus,
219
+ timelinePosition,
220
+ });
221
+ };
222
+ const getTimelineSelectionAfterDeletingItems = ({ selections, sequences, overrideIdsToNodePaths, propStatuses, timelinePosition, }) => {
223
+ const easingSelection = getEasingSelectionAfterDeletingKeyframes({
224
+ selections,
225
+ sequences,
226
+ overrideIdsToNodePaths,
227
+ propStatuses,
228
+ timelinePosition,
229
+ });
230
+ if (easingSelection !== null) {
231
+ return [easingSelection];
232
+ }
154
233
  const nextSelections = new Map();
155
234
  for (const selection of selections) {
156
235
  const nextSelection = getSequenceSelectionAfterDeletingEffect(selection);