@remotion/studio 4.0.473 → 4.0.475

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 (123) hide show
  1. package/dist/components/AssetSelectorItem.js +30 -6
  2. package/dist/components/Canvas.js +77 -0
  3. package/dist/components/ColorPicker/ColorPicker.js +4 -31
  4. package/dist/components/CompositionSelectorItem.js +4 -4
  5. package/dist/components/Editor.js +4 -1
  6. package/dist/components/Modals.js +2 -2
  7. package/dist/components/NewComposition/ComboBox.js +1 -0
  8. package/dist/components/NewComposition/InputDragger.d.ts +1 -0
  9. package/dist/components/NewComposition/InputDragger.js +9 -6
  10. package/dist/components/PreviewToolbar.js +2 -2
  11. package/dist/components/SelectedOutlineOverlay.d.ts +61 -33
  12. package/dist/components/SelectedOutlineOverlay.js +813 -351
  13. package/dist/components/SelectedOutlineUvControls.d.ts +17 -0
  14. package/dist/components/SelectedOutlineUvControls.js +167 -0
  15. package/dist/components/StudioCanvasCapture.d.ts +5 -0
  16. package/dist/components/StudioCanvasCapture.js +40 -0
  17. package/dist/components/Timeline/EasingEditorModal.d.ts +11 -0
  18. package/dist/components/Timeline/EasingEditorModal.js +247 -0
  19. package/dist/components/Timeline/KeyframeSettingsModal.js +5 -4
  20. package/dist/components/Timeline/SequencePropsObserver.js +3 -3
  21. package/dist/components/Timeline/Timeline.js +10 -7
  22. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +7 -7
  23. package/dist/components/Timeline/TimelineClipboardKeybindings.js +19 -16
  24. package/dist/components/Timeline/TimelineDeleteKeybindings.js +71 -40
  25. package/dist/components/Timeline/TimelineDragHandler.js +2 -2
  26. package/dist/components/Timeline/TimelineEffectItem.js +8 -9
  27. package/dist/components/Timeline/TimelineEffectPropItem.js +18 -18
  28. package/dist/components/Timeline/TimelineExpandedKeyframeRow.d.ts +1 -0
  29. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +7 -2
  30. package/dist/components/Timeline/TimelineExpandedSection.js +5 -5
  31. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.js +1 -1
  32. package/dist/components/Timeline/TimelineHeightContainer.js +2 -0
  33. package/dist/components/Timeline/TimelineItemStack.js +3 -56
  34. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +7 -0
  35. package/dist/components/Timeline/TimelineKeyframeControls.js +265 -68
  36. package/dist/components/Timeline/TimelineKeyframeDiamond.js +4 -3
  37. package/dist/components/Timeline/TimelineKeyframeEasingLine.d.ts +9 -0
  38. package/dist/components/Timeline/TimelineKeyframeEasingLine.js +245 -0
  39. package/dist/components/Timeline/TimelineKeyframeTracksContext.d.ts +7 -0
  40. package/dist/components/Timeline/TimelineKeyframeTracksContext.js +17 -0
  41. package/dist/components/Timeline/TimelineKeyframedValue.js +1 -1
  42. package/dist/components/Timeline/TimelineMediaInfo.js +4 -24
  43. package/dist/components/Timeline/TimelineNumberField.js +15 -7
  44. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +4 -0
  45. package/dist/components/Timeline/TimelineRotationField.js +22 -34
  46. package/dist/components/Timeline/TimelineScaleField.js +16 -12
  47. package/dist/components/Timeline/TimelineScrollable.js +19 -3
  48. package/dist/components/Timeline/TimelineSelection.d.ts +82 -3
  49. package/dist/components/Timeline/TimelineSelection.js +312 -30
  50. package/dist/components/Timeline/TimelineSequence.js +23 -15
  51. package/dist/components/Timeline/TimelineSequenceItem.js +48 -73
  52. package/dist/components/Timeline/TimelineSequenceName.js +3 -17
  53. package/dist/components/Timeline/TimelineSequencePropItem.js +37 -37
  54. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +5 -5
  55. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +46 -44
  56. package/dist/components/Timeline/TimelineTimeIndicators.js +4 -2
  57. package/dist/components/Timeline/TimelineTransformOriginField.d.ts +11 -0
  58. package/dist/components/Timeline/TimelineTransformOriginField.js +138 -0
  59. package/dist/components/Timeline/TimelineTranslateField.js +24 -19
  60. package/dist/components/Timeline/TimelineUvCoordinateField.js +18 -12
  61. package/dist/components/Timeline/{apply-effect-response-to-code-values.d.ts → apply-effect-response-to-prop-statuses.d.ts} +1 -1
  62. package/dist/components/Timeline/{apply-effect-response-to-code-values.js → apply-effect-response-to-prop-statuses.js} +3 -3
  63. package/dist/components/Timeline/call-add-keyframe.d.ts +22 -5
  64. package/dist/components/Timeline/call-add-keyframe.js +71 -7
  65. package/dist/components/Timeline/call-delete-keyframe.d.ts +7 -7
  66. package/dist/components/Timeline/call-delete-keyframe.js +7 -7
  67. package/dist/components/Timeline/call-move-keyframe.d.ts +3 -3
  68. package/dist/components/Timeline/call-move-keyframe.js +3 -3
  69. package/dist/components/Timeline/call-update-keyframe-settings.d.ts +5 -5
  70. package/dist/components/Timeline/call-update-keyframe-settings.js +6 -6
  71. package/dist/components/Timeline/delete-selected-keyframe.d.ts +5 -5
  72. package/dist/components/Timeline/delete-selected-keyframe.js +5 -5
  73. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +5 -5
  74. package/dist/components/Timeline/delete-selected-timeline-item.js +28 -16
  75. package/dist/components/Timeline/get-node-keyframes.d.ts +3 -3
  76. package/dist/components/Timeline/get-node-keyframes.js +4 -4
  77. package/dist/components/Timeline/get-timeline-easing-segments.d.ts +9 -0
  78. package/dist/components/Timeline/get-timeline-easing-segments.js +19 -0
  79. package/dist/components/Timeline/reset-selected-timeline-props.d.ts +7 -7
  80. package/dist/components/Timeline/reset-selected-timeline-props.js +23 -15
  81. package/dist/components/Timeline/save-effect-prop.d.ts +2 -2
  82. package/dist/components/Timeline/save-effect-prop.js +5 -5
  83. package/dist/components/Timeline/save-prop-queue.d.ts +3 -3
  84. package/dist/components/Timeline/save-prop-queue.js +3 -3
  85. package/dist/components/Timeline/save-sequence-prop.d.ts +3 -3
  86. package/dist/components/Timeline/save-sequence-prop.js +4 -4
  87. package/dist/components/Timeline/timeline-field-utils.d.ts +10 -0
  88. package/dist/components/Timeline/timeline-field-utils.js +26 -5
  89. package/dist/components/Timeline/timeline-rotation-utils.d.ts +2 -0
  90. package/dist/components/Timeline/timeline-rotation-utils.js +32 -0
  91. package/dist/components/Timeline/timeline-translate-utils.d.ts +1 -1
  92. package/dist/components/Timeline/timeline-translate-utils.js +4 -5
  93. package/dist/components/Timeline/transform-origin-utils.d.ts +24 -0
  94. package/dist/components/Timeline/transform-origin-utils.js +170 -0
  95. package/dist/components/Timeline/update-selected-easing.d.ts +35 -0
  96. package/dist/components/Timeline/update-selected-easing.js +133 -0
  97. package/dist/components/Timeline/use-expanded-track-keyframe-rows.d.ts +1 -0
  98. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +35 -7
  99. package/dist/components/Timeline/use-sequence-props-subscription.js +3 -3
  100. package/dist/components/Timeline/use-timeline-height.js +3 -3
  101. package/dist/components/Timeline/use-timeline-keyframe-drag.js +13 -11
  102. package/dist/components/canvas-capture-enabled.d.ts +1 -0
  103. package/dist/components/canvas-capture-enabled.js +4 -0
  104. package/dist/components/effect-drag-and-drop.d.ts +11 -0
  105. package/dist/components/effect-drag-and-drop.js +73 -0
  106. package/dist/components/import-assets.d.ts +15 -0
  107. package/dist/components/import-assets.js +63 -1
  108. package/dist/components/selected-outline-geometry.d.ts +20 -0
  109. package/dist/components/selected-outline-geometry.js +18 -0
  110. package/dist/components/selected-outline-uv.d.ts +46 -0
  111. package/dist/components/selected-outline-uv.js +240 -0
  112. package/dist/esm/{chunk-q0jkt0zq.js → chunk-qaqqvw4q.js} +8096 -5307
  113. package/dist/esm/internals.mjs +8096 -5307
  114. package/dist/esm/previewEntry.mjs +8106 -5317
  115. package/dist/esm/renderEntry.mjs +1 -1
  116. package/dist/helpers/colors.d.ts +0 -1
  117. package/dist/helpers/colors.js +1 -2
  118. package/dist/helpers/timeline-layout.d.ts +6 -6
  119. package/dist/helpers/timeline-layout.js +5 -5
  120. package/dist/state/modals.d.ts +2 -4
  121. package/package.json +11 -10
  122. package/dist/components/NewComposition/DeleteStaticFile.d.ts +0 -4
  123. package/dist/components/NewComposition/DeleteStaticFile.js +0 -44
@@ -7,9 +7,8 @@ export declare const TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING = 2;
7
7
  export declare const getTimelineSelectedLabelStyle: (selected: boolean, subcategory: boolean) => CSSProperties;
8
8
  export declare const getTimelineColor: (selected: boolean, subcategory: boolean) => "black" | "rgba(255, 255, 255, 0.8)";
9
9
  export declare const getTimelineSelectedTrackHighlightStyle: (timelineWidth: number) => CSSProperties;
10
- export declare const SELECTION_ENABLED = false;
11
- export declare const TIMELINE_TOP_DRAG = false;
12
- export declare const ENABLE_OUTLINES = false;
10
+ export declare const TIMELINE_BACKGROUND = "#0F1113";
11
+ export declare const TIMELINE_TICKS_BACKGROUND = "rgb(31,36,40)";
13
12
  type TimelineSelectionBase = {
14
13
  readonly nodePathInfo: SequenceNodePathInfo;
15
14
  };
@@ -30,7 +29,15 @@ export type TimelineSelection = (TimelineSelectionBase & {
30
29
  }) | (TimelineSelectionBase & {
31
30
  readonly type: 'keyframe';
32
31
  readonly frame: number;
32
+ }) | (TimelineSelectionBase & {
33
+ readonly type: 'easing';
34
+ readonly fromFrame: number;
35
+ readonly toFrame: number;
36
+ readonly segmentIndex: number;
33
37
  });
38
+ export type TimelineEasingSelection = Extract<TimelineSelection, {
39
+ type: 'easing';
40
+ }>;
34
41
  export type TimelineSelectionInteraction = {
35
42
  readonly shiftKey: boolean;
36
43
  readonly toggleKey: boolean;
@@ -40,27 +47,74 @@ export declare const isTimelineSelectionModifierEvent: ({ shiftKey, metaKey, ctr
40
47
  readonly metaKey: boolean;
41
48
  readonly ctrlKey: boolean;
42
49
  }) => boolean;
50
+ export declare const shouldSelectTimelineRowOnPointerDown: ({ selected, shiftKey, metaKey, ctrlKey, }: {
51
+ readonly selected: boolean;
52
+ readonly shiftKey: boolean;
53
+ readonly metaKey: boolean;
54
+ readonly ctrlKey: boolean;
55
+ }) => boolean;
43
56
  export type TimelineSelectionState = {
44
57
  readonly selectedItems: readonly TimelineSelection[];
45
58
  readonly anchor: TimelineSelection | null;
46
59
  };
60
+ export type TimelineMarqueeRect = {
61
+ readonly left: number;
62
+ readonly top: number;
63
+ readonly right: number;
64
+ readonly bottom: number;
65
+ };
66
+ export type TimelineMarqueeSelectionKind = 'sequence' | 'keyframes-and-easings';
67
+ export type TimelineMarqueeSelectionCandidate = {
68
+ readonly item: TimelineSelection;
69
+ readonly rect: TimelineMarqueeRect;
70
+ };
47
71
  export declare const getTimelineSelectionAfterInteraction: ({ currentState, clickedItem, interaction, allSelectableItems, }: {
48
72
  readonly currentState: TimelineSelectionState;
49
73
  readonly clickedItem: TimelineSelection;
50
74
  readonly interaction: TimelineSelectionInteraction;
51
75
  readonly allSelectableItems: readonly TimelineSelection[];
52
76
  }) => TimelineSelectionState;
77
+ export declare const getNormalizedTimelineMarqueeRect: ({ startX, startY, currentX, currentY, }: {
78
+ readonly startX: number;
79
+ readonly startY: number;
80
+ readonly currentX: number;
81
+ readonly currentY: number;
82
+ }) => TimelineMarqueeRect;
83
+ export declare const getClampedTimelineMarqueePoint: ({ x, y, bounds, }: {
84
+ readonly x: number;
85
+ readonly y: number;
86
+ readonly bounds: TimelineMarqueeRect;
87
+ }) => {
88
+ readonly x: number;
89
+ readonly y: number;
90
+ };
91
+ export declare const timelineMarqueeRectsIntersect: (a: TimelineMarqueeRect, b: TimelineMarqueeRect) => boolean;
92
+ export declare const getTimelineMarqueeSelection: ({ candidates, lockedSelectionKind, marqueeRect, }: {
93
+ readonly candidates: readonly TimelineMarqueeSelectionCandidate[];
94
+ readonly lockedSelectionKind: TimelineMarqueeSelectionKind | null;
95
+ readonly marqueeRect: TimelineMarqueeRect;
96
+ }) => {
97
+ readonly lockedSelectionKind: TimelineMarqueeSelectionKind | null;
98
+ readonly selectedItems: readonly TimelineSelection[];
99
+ };
53
100
  type TimelineSelectionContextValue = {
54
101
  readonly canSelect: boolean;
102
+ readonly canSelectEasing: boolean;
55
103
  readonly selectedItems: readonly TimelineSelection[];
56
104
  readonly isSelected: (item: TimelineSelection) => boolean;
57
105
  readonly selectItem: (item: TimelineSelection, interaction?: TimelineSelectionInteraction) => void;
58
106
  readonly selectItems: (items: readonly TimelineSelection[]) => void;
59
107
  readonly registerSelectableItem: (item: TimelineSelection) => () => void;
108
+ readonly registerMarqueeSelectableItem: (item: TimelineSelection, getRect: () => DOMRect | null) => () => void;
109
+ readonly getMarqueeSelection: (marqueeRect: TimelineMarqueeRect, lockedSelectionKind: TimelineMarqueeSelectionKind | null) => {
110
+ readonly lockedSelectionKind: TimelineMarqueeSelectionKind | null;
111
+ readonly selectedItems: readonly TimelineSelection[];
112
+ };
60
113
  readonly containsSelection: (nodePathInfo: SequenceNodePathInfo) => boolean;
61
114
  readonly clearSelection: () => void;
62
115
  };
63
116
  export declare const getTimelineSelectionFromNodePathInfo: (nodePathInfo: SequenceNodePathInfo | null) => TimelineSelection | null;
117
+ export declare const getTimelineSelectionKey: (item: TimelineSelection) => string;
64
118
  export declare const getSelectableTimelineSequenceSelections: (tracks: readonly Pick<TrackWithHash, "nodePathInfo">[]) => TimelineSelection[];
65
119
  export declare const getTimelineSequenceSelectionKey: (nodePathInfo: SequenceNodePathInfo) => string;
66
120
  export declare const TimelineSelectAllKeybindings: React.FC<{
@@ -70,16 +124,41 @@ export declare const TimelineSelectionProvider: React.FC<{
70
124
  readonly children: React.ReactNode;
71
125
  }>;
72
126
  export declare const useTimelineSelection: () => TimelineSelectionContextValue;
127
+ export declare const TIMELINE_MARQUEE_ITEM_ATTR = "data-timeline-marquee-item";
128
+ export declare const TIMELINE_SCRUBBER_ATTR = "data-timeline-scrubber";
73
129
  export declare const useCurrentTimelineSelectionStateAsRef: () => React.RefObject<TimelineSelectionContextValue>;
130
+ export declare const useTimelineMarqueeSelection: () => {
131
+ marqueeRect: TimelineMarqueeRect | null;
132
+ onPointerDownCapture: (event: React.PointerEvent<HTMLDivElement>) => void;
133
+ };
134
+ export declare const useTimelineMarqueeSelectableItem: (item: TimelineSelection | null, ref: React.RefObject<Element | null>) => void;
74
135
  export declare const useTimelineRowSelection: (nodePathInfo: SequenceNodePathInfo | null) => {
75
136
  onSelect: (interaction?: TimelineSelectionInteraction | undefined) => void;
76
137
  selectable: boolean;
138
+ selectionItem: TimelineSelection | null;
77
139
  selected: boolean;
78
140
  };
79
141
  export declare const useTimelineKeyframeSelection: (nodePathInfo: SequenceNodePathInfo, frame: number) => {
142
+ onSelect: (interaction?: TimelineSelectionInteraction | undefined) => void;
143
+ selectable: boolean;
144
+ selectionItem: TimelineSelection;
145
+ selected: boolean;
146
+ };
147
+ export declare const useTimelineEasingSelection: ({ nodePathInfo, fromFrame, toFrame, segmentIndex, }: {
148
+ readonly nodePathInfo: SequenceNodePathInfo;
149
+ readonly fromFrame: number;
150
+ readonly toFrame: number;
151
+ readonly segmentIndex: number;
152
+ }) => {
80
153
  onSelect: (interaction?: TimelineSelectionInteraction | undefined) => void;
81
154
  selectable: boolean;
82
155
  selected: boolean;
156
+ selectionItem: TimelineSelectionBase & {
157
+ readonly type: "easing";
158
+ readonly fromFrame: number;
159
+ readonly toFrame: number;
160
+ readonly segmentIndex: number;
161
+ };
83
162
  };
84
163
  export declare const useTimelineRowContainsSelection: (nodePathInfo: SequenceNodePathInfo | null) => boolean;
85
164
  export {};
@@ -1,13 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useTimelineRowContainsSelection = exports.useTimelineKeyframeSelection = exports.useTimelineRowSelection = exports.useCurrentTimelineSelectionStateAsRef = exports.useTimelineSelection = exports.TimelineSelectionProvider = exports.TimelineSelectAllKeybindings = exports.getTimelineSequenceSelectionKey = exports.getSelectableTimelineSequenceSelections = exports.getTimelineSelectionFromNodePathInfo = exports.getTimelineSelectionAfterInteraction = exports.isTimelineSelectionModifierEvent = exports.ENABLE_OUTLINES = exports.TIMELINE_TOP_DRAG = exports.SELECTION_ENABLED = exports.getTimelineSelectedTrackHighlightStyle = exports.getTimelineColor = exports.getTimelineSelectedLabelStyle = exports.TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING = exports.TIMELINE_SELECTED_LABEL_TEXT = exports.TIMELINE_SELECTED_LABEL_BACKGROUND = exports.TIMELINE_SELECTED_BACKGROUND = void 0;
3
+ exports.useTimelineRowContainsSelection = exports.useTimelineEasingSelection = exports.useTimelineKeyframeSelection = exports.useTimelineRowSelection = exports.useTimelineMarqueeSelectableItem = exports.useTimelineMarqueeSelection = exports.useCurrentTimelineSelectionStateAsRef = exports.TIMELINE_SCRUBBER_ATTR = exports.TIMELINE_MARQUEE_ITEM_ATTR = exports.useTimelineSelection = exports.TimelineSelectionProvider = exports.TimelineSelectAllKeybindings = exports.getTimelineSequenceSelectionKey = exports.getSelectableTimelineSequenceSelections = exports.getTimelineSelectionKey = exports.getTimelineSelectionFromNodePathInfo = exports.getTimelineMarqueeSelection = exports.timelineMarqueeRectsIntersect = exports.getClampedTimelineMarqueePoint = exports.getNormalizedTimelineMarqueeRect = exports.getTimelineSelectionAfterInteraction = exports.shouldSelectTimelineRowOnPointerDown = exports.isTimelineSelectionModifierEvent = exports.TIMELINE_TICKS_BACKGROUND = exports.TIMELINE_BACKGROUND = exports.getTimelineSelectedTrackHighlightStyle = exports.getTimelineColor = exports.getTimelineSelectedLabelStyle = exports.TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING = exports.TIMELINE_SELECTED_LABEL_TEXT = exports.TIMELINE_SELECTED_LABEL_BACKGROUND = exports.TIMELINE_SELECTED_BACKGROUND = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const studio_shared_1 = require("@remotion/studio-shared");
6
6
  const react_1 = require("react");
7
7
  const client_id_1 = require("../../helpers/client-id");
8
+ const colors_1 = require("../../helpers/colors");
8
9
  const timeline_layout_1 = require("../../helpers/timeline-layout");
9
10
  const timeline_node_path_key_1 = require("../../helpers/timeline-node-path-key");
10
11
  const use_keybinding_1 = require("../../helpers/use-keybinding");
12
+ const z_index_1 = require("../../state/z-index");
11
13
  const TimelineClipboardKeybindings_1 = require("./TimelineClipboardKeybindings");
12
14
  const TimelineDeleteKeybindings_1 = require("./TimelineDeleteKeybindings");
13
15
  exports.TIMELINE_SELECTED_BACKGROUND = '#3B3F42';
@@ -44,14 +46,27 @@ const getTimelineSelectedTrackHighlightStyle = (timelineWidth) => ({
44
46
  width: timelineWidth,
45
47
  });
46
48
  exports.getTimelineSelectedTrackHighlightStyle = getTimelineSelectedTrackHighlightStyle;
47
- exports.SELECTION_ENABLED = false;
48
- exports.TIMELINE_TOP_DRAG = false;
49
- exports.ENABLE_OUTLINES = false;
49
+ exports.TIMELINE_BACKGROUND = '#0F1113';
50
+ exports.TIMELINE_TICKS_BACKGROUND = colors_1.BACKGROUND;
50
51
  const isTimelineSelectionModifierEvent = ({ shiftKey, metaKey, ctrlKey, }) => {
51
52
  return shiftKey || metaKey || ctrlKey;
52
53
  };
53
54
  exports.isTimelineSelectionModifierEvent = isTimelineSelectionModifierEvent;
55
+ const shouldSelectTimelineRowOnPointerDown = ({ selected, shiftKey, metaKey, ctrlKey, }) => {
56
+ return (!selected || (0, exports.isTimelineSelectionModifierEvent)({ shiftKey, metaKey, ctrlKey }));
57
+ };
58
+ exports.shouldSelectTimelineRowOnPointerDown = shouldSelectTimelineRowOnPointerDown;
54
59
  const getTimelineSelectionType = (item) => item.type;
60
+ const areTimelineSelectionTypesCompatible = (firstType, secondType) => {
61
+ if (firstType === secondType) {
62
+ return true;
63
+ }
64
+ return ((firstType === 'sequence-prop' && secondType === 'sequence-effect-prop') ||
65
+ (firstType === 'sequence-effect-prop' && secondType === 'sequence-prop') ||
66
+ (firstType === 'keyframe' && secondType === 'easing') ||
67
+ (firstType === 'easing' && secondType === 'keyframe'));
68
+ };
69
+ const isTimelineSelectionCompatibleWithType = (item, type) => areTimelineSelectionTypesCompatible(getTimelineSelectionType(item), type);
55
70
  const getTimelineSelectionAnchor = (selectedItems, previousAnchor, targetType) => {
56
71
  if (previousAnchor &&
57
72
  getTimelineSelectionType(previousAnchor) === targetType) {
@@ -66,11 +81,11 @@ const getTimelineSelectionAnchor = (selectedItems, previousAnchor, targetType) =
66
81
  return null;
67
82
  };
68
83
  const getRangeSelection = ({ anchor, clickedItem, allSelectableItems, }) => {
69
- const anchorKey = getTimelineSelectionKey(anchor);
70
- const clickedKey = getTimelineSelectionKey(clickedItem);
84
+ const anchorKey = (0, exports.getTimelineSelectionKey)(anchor);
85
+ const clickedKey = (0, exports.getTimelineSelectionKey)(clickedItem);
71
86
  const orderedOfType = allSelectableItems.filter((item) => getTimelineSelectionType(item) === clickedItem.type);
72
- const anchorIndex = orderedOfType.findIndex((item) => getTimelineSelectionKey(item) === anchorKey);
73
- const clickedIndex = orderedOfType.findIndex((item) => getTimelineSelectionKey(item) === clickedKey);
87
+ const anchorIndex = orderedOfType.findIndex((item) => (0, exports.getTimelineSelectionKey)(item) === anchorKey);
88
+ const clickedIndex = orderedOfType.findIndex((item) => (0, exports.getTimelineSelectionKey)(item) === clickedKey);
74
89
  if (anchorIndex === -1 || clickedIndex === -1) {
75
90
  return [clickedItem];
76
91
  }
@@ -83,7 +98,7 @@ const getTimelineSelectionAfterInteraction = ({ currentState, clickedItem, inter
83
98
  const { selectedItems, anchor: previousAnchor } = currentState;
84
99
  const clickedType = getTimelineSelectionType(clickedItem);
85
100
  const nextAnchor = getTimelineSelectionAnchor(selectedItems, previousAnchor, clickedType);
86
- const clickedKey = getTimelineSelectionKey(clickedItem);
101
+ const clickedKey = (0, exports.getTimelineSelectionKey)(clickedItem);
87
102
  if (interaction.shiftKey && nextAnchor) {
88
103
  return {
89
104
  selectedItems: getRangeSelection({
@@ -95,22 +110,22 @@ const getTimelineSelectionAfterInteraction = ({ currentState, clickedItem, inter
95
110
  };
96
111
  }
97
112
  if (interaction.toggleKey) {
98
- const sameTypeItems = selectedItems.filter((item) => getTimelineSelectionType(item) === clickedType);
99
- const existingKeySet = new Set(sameTypeItems.map(getTimelineSelectionKey));
113
+ const compatibleItems = selectedItems.filter((item) => isTimelineSelectionCompatibleWithType(item, clickedType));
114
+ const existingKeySet = new Set(compatibleItems.map(exports.getTimelineSelectionKey));
100
115
  if (existingKeySet.has(clickedKey)) {
101
- const toggledSelection = sameTypeItems.filter((item) => getTimelineSelectionKey(item) !== clickedKey);
116
+ const toggledSelection = compatibleItems.filter((item) => (0, exports.getTimelineSelectionKey)(item) !== clickedKey);
102
117
  return {
103
118
  selectedItems: toggledSelection,
104
119
  anchor: toggledSelection.length === 0 ? null : clickedItem,
105
120
  };
106
121
  }
107
122
  const selectableOrderMap = new Map(allSelectableItems
108
- .filter((item) => getTimelineSelectionType(item) === clickedType)
109
- .map((item, index) => [getTimelineSelectionKey(item), index]));
110
- const extendedSelection = [...sameTypeItems, clickedItem].sort((a, b) => {
123
+ .filter((item) => isTimelineSelectionCompatibleWithType(item, clickedType))
124
+ .map((item, index) => [(0, exports.getTimelineSelectionKey)(item), index]));
125
+ const extendedSelection = [...compatibleItems, clickedItem].sort((a, b) => {
111
126
  var _a, _b;
112
- return (((_a = selectableOrderMap.get(getTimelineSelectionKey(a))) !== null && _a !== void 0 ? _a : 0) -
113
- ((_b = selectableOrderMap.get(getTimelineSelectionKey(b))) !== null && _b !== void 0 ? _b : 0));
127
+ return (((_a = selectableOrderMap.get((0, exports.getTimelineSelectionKey)(a))) !== null && _a !== void 0 ? _a : 0) -
128
+ ((_b = selectableOrderMap.get((0, exports.getTimelineSelectionKey)(b))) !== null && _b !== void 0 ? _b : 0));
114
129
  });
115
130
  return {
116
131
  selectedItems: extendedSelection,
@@ -123,13 +138,80 @@ const getTimelineSelectionAfterInteraction = ({ currentState, clickedItem, inter
123
138
  };
124
139
  };
125
140
  exports.getTimelineSelectionAfterInteraction = getTimelineSelectionAfterInteraction;
141
+ const getNormalizedTimelineMarqueeRect = ({ startX, startY, currentX, currentY, }) => ({
142
+ left: Math.min(startX, currentX),
143
+ top: Math.min(startY, currentY),
144
+ right: Math.max(startX, currentX),
145
+ bottom: Math.max(startY, currentY),
146
+ });
147
+ exports.getNormalizedTimelineMarqueeRect = getNormalizedTimelineMarqueeRect;
148
+ const getClampedTimelineMarqueePoint = ({ x, y, bounds, }) => ({
149
+ x: Math.min(bounds.right, Math.max(bounds.left, x)),
150
+ y: Math.min(bounds.bottom, Math.max(bounds.top, y)),
151
+ });
152
+ exports.getClampedTimelineMarqueePoint = getClampedTimelineMarqueePoint;
153
+ const timelineMarqueeRectsIntersect = (a, b) => a.left <= b.right &&
154
+ a.right >= b.left &&
155
+ a.top <= b.bottom &&
156
+ a.bottom >= b.top;
157
+ exports.timelineMarqueeRectsIntersect = timelineMarqueeRectsIntersect;
158
+ const getTimelineMarqueeSelectionKind = (item) => {
159
+ if (item.type === 'sequence') {
160
+ return 'sequence';
161
+ }
162
+ if (item.type === 'keyframe' || item.type === 'easing') {
163
+ return 'keyframes-and-easings';
164
+ }
165
+ return null;
166
+ };
167
+ const isTimelineSelectionCompatibleWithMarqueeKind = (item, kind) => {
168
+ if (kind === 'sequence') {
169
+ return item.type === 'sequence';
170
+ }
171
+ return item.type === 'keyframe' || item.type === 'easing';
172
+ };
173
+ const getTimelineMarqueeSelection = ({ candidates, lockedSelectionKind, marqueeRect, }) => {
174
+ const intersectingCandidates = candidates.filter((candidate) => {
175
+ return (getTimelineMarqueeSelectionKind(candidate.item) !== null &&
176
+ (0, exports.timelineMarqueeRectsIntersect)(candidate.rect, marqueeRect));
177
+ });
178
+ const getFirstIntersectingSelectionKind = () => intersectingCandidates.length === 0
179
+ ? null
180
+ : getTimelineMarqueeSelectionKind(intersectingCandidates[0].item);
181
+ let nextLockedSelectionKind = lockedSelectionKind !== null && lockedSelectionKind !== void 0 ? lockedSelectionKind : getFirstIntersectingSelectionKind();
182
+ const getSelectedItemsForKind = (kind) => intersectingCandidates
183
+ .filter((candidate) => isTimelineSelectionCompatibleWithMarqueeKind(candidate.item, kind))
184
+ .map((candidate) => candidate.item);
185
+ if (nextLockedSelectionKind === null) {
186
+ return { lockedSelectionKind: null, selectedItems: [] };
187
+ }
188
+ let selectedItems = getSelectedItemsForKind(nextLockedSelectionKind);
189
+ if (lockedSelectionKind !== null && selectedItems.length === 0) {
190
+ nextLockedSelectionKind = getFirstIntersectingSelectionKind();
191
+ selectedItems =
192
+ nextLockedSelectionKind === null
193
+ ? []
194
+ : getSelectedItemsForKind(nextLockedSelectionKind);
195
+ }
196
+ return {
197
+ lockedSelectionKind: nextLockedSelectionKind,
198
+ selectedItems,
199
+ };
200
+ };
201
+ exports.getTimelineMarqueeSelection = getTimelineMarqueeSelection;
126
202
  const defaultTimelineSelectionContextValue = {
127
203
  canSelect: false,
204
+ canSelectEasing: false,
128
205
  selectedItems: [],
129
206
  isSelected: () => false,
130
207
  selectItem: () => undefined,
131
208
  selectItems: () => undefined,
132
209
  registerSelectableItem: () => () => undefined,
210
+ registerMarqueeSelectableItem: () => () => undefined,
211
+ getMarqueeSelection: () => ({
212
+ lockedSelectionKind: null,
213
+ selectedItems: [],
214
+ }),
133
215
  containsSelection: () => false,
134
216
  clearSelection: () => undefined,
135
217
  };
@@ -191,10 +273,13 @@ const getTimelineSelectionKey = (item) => {
191
273
  return `${sequenceKey}.sequence-effect-prop.${item.i}.${item.key}`;
192
274
  case 'keyframe':
193
275
  return `${(0, timeline_node_path_key_1.timelineNodePathInfoToKey)(item.nodePathInfo)}.keyframe.${item.frame}`;
276
+ case 'easing':
277
+ return `${(0, timeline_node_path_key_1.timelineNodePathInfoToKey)(item.nodePathInfo)}.easing.${item.segmentIndex}.${item.fromFrame}.${item.toFrame}`;
194
278
  default:
195
279
  throw new Error(`Unexpected timeline selection type: ${item}`);
196
280
  }
197
281
  };
282
+ exports.getTimelineSelectionKey = getTimelineSelectionKey;
198
283
  const nodePathDescendsFrom = (descendant, ancestor) => {
199
284
  if ((0, studio_shared_1.stringifySequenceExpandedRowKey)(descendant.sequenceSubscriptionKey) !==
200
285
  (0, studio_shared_1.stringifySequenceExpandedRowKey)(ancestor.sequenceSubscriptionKey)) {
@@ -256,28 +341,32 @@ const TimelineSelectAllKeybindings = ({ timeline }) => {
256
341
  exports.TimelineSelectAllKeybindings = TimelineSelectAllKeybindings;
257
342
  const TimelineSelectionProvider = ({ children }) => {
258
343
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
259
- const canSelect = (exports.SELECTION_ENABLED || exports.ENABLE_OUTLINES) &&
260
- previewServerState.type === 'connected' &&
344
+ const canSelect = previewServerState.type === 'connected' &&
345
+ !window.remotion_isReadOnlyStudio;
346
+ const canSelectEasing = previewServerState.type === 'connected' &&
261
347
  !window.remotion_isReadOnlyStudio;
262
348
  const [selectedItems, setSelectedItems] = (0, react_1.useState)([]);
263
349
  const selectionAnchor = (0, react_1.useRef)(null);
264
350
  const selectableItemsOrder = (0, react_1.useRef)(new Map());
265
351
  const selectableItems = (0, react_1.useRef)(new Map());
352
+ const marqueeSelectableItems = (0, react_1.useRef)(new Map());
266
353
  const registrationCounter = (0, react_1.useRef)(0);
354
+ const marqueeRegistrationCounter = (0, react_1.useRef)(0);
267
355
  (0, react_1.useEffect)(() => {
268
- if (!canSelect) {
356
+ if (!canSelect && !canSelectEasing) {
269
357
  setSelectedItems([]);
270
358
  }
271
- }, [canSelect]);
272
- const selectedKeys = (0, react_1.useMemo)(() => new Set(selectedItems.map(getTimelineSelectionKey)), [selectedItems]);
359
+ }, [canSelect, canSelectEasing]);
360
+ const canSelectItem = (0, react_1.useCallback)((item) => canSelect || (canSelectEasing && item.type === 'easing'), [canSelect, canSelectEasing]);
361
+ const selectedKeys = (0, react_1.useMemo)(() => new Set(selectedItems.map(exports.getTimelineSelectionKey)), [selectedItems]);
273
362
  const isSelected = (0, react_1.useCallback)((item) => {
274
- return selectedKeys.has(getTimelineSelectionKey(item));
363
+ return selectedKeys.has((0, exports.getTimelineSelectionKey)(item));
275
364
  }, [selectedKeys]);
276
365
  const selectItem = (0, react_1.useCallback)((item, interaction = {
277
366
  shiftKey: false,
278
367
  toggleKey: false,
279
368
  }) => {
280
- if (!canSelect) {
369
+ if (!canSelectItem(item)) {
281
370
  return;
282
371
  }
283
372
  setSelectedItems((currentSelectedItems) => {
@@ -285,8 +374,8 @@ const TimelineSelectionProvider = ({ children }) => {
285
374
  ...selectableItems.current.values(),
286
375
  ].sort((a, b) => {
287
376
  var _a, _b;
288
- return (((_a = selectableItemsOrder.current.get(getTimelineSelectionKey(a))) !== null && _a !== void 0 ? _a : 0) -
289
- ((_b = selectableItemsOrder.current.get(getTimelineSelectionKey(b))) !== null && _b !== void 0 ? _b : 0));
377
+ return (((_a = selectableItemsOrder.current.get((0, exports.getTimelineSelectionKey)(a))) !== null && _a !== void 0 ? _a : 0) -
378
+ ((_b = selectableItemsOrder.current.get((0, exports.getTimelineSelectionKey)(b))) !== null && _b !== void 0 ? _b : 0));
290
379
  });
291
380
  const nextState = (0, exports.getTimelineSelectionAfterInteraction)({
292
381
  currentState: {
@@ -300,17 +389,17 @@ const TimelineSelectionProvider = ({ children }) => {
300
389
  selectionAnchor.current = nextState.anchor;
301
390
  return nextState.selectedItems;
302
391
  });
303
- }, [canSelect]);
392
+ }, [canSelectItem]);
304
393
  const selectItems = (0, react_1.useCallback)((items) => {
305
- if (!canSelect) {
394
+ if (!items.every(canSelectItem)) {
306
395
  return;
307
396
  }
308
397
  selectionAnchor.current =
309
398
  items.length === 0 ? null : items[items.length - 1];
310
399
  setSelectedItems(items);
311
- }, [canSelect]);
400
+ }, [canSelectItem]);
312
401
  const registerSelectableItem = (0, react_1.useCallback)((item) => {
313
- const key = getTimelineSelectionKey(item);
402
+ const key = (0, exports.getTimelineSelectionKey)(item);
314
403
  const registrationOrder = registrationCounter.current;
315
404
  registrationCounter.current += 1;
316
405
  selectableItems.current.set(key, item);
@@ -320,6 +409,48 @@ const TimelineSelectionProvider = ({ children }) => {
320
409
  selectableItemsOrder.current.delete(key);
321
410
  };
322
411
  }, []);
412
+ const registerMarqueeSelectableItem = (0, react_1.useCallback)((item, getRect) => {
413
+ const key = (0, exports.getTimelineSelectionKey)(item);
414
+ const registrationOrder = marqueeRegistrationCounter.current;
415
+ marqueeRegistrationCounter.current += 1;
416
+ marqueeSelectableItems.current.set(key, {
417
+ getRect,
418
+ item,
419
+ order: registrationOrder,
420
+ });
421
+ return () => {
422
+ marqueeSelectableItems.current.delete(key);
423
+ };
424
+ }, []);
425
+ const getMarqueeSelectionForRect = (0, react_1.useCallback)((marqueeRect, lockedSelectionKind) => {
426
+ const candidates = [...marqueeSelectableItems.current.values()]
427
+ .sort((a, b) => a.order - b.order)
428
+ .flatMap((candidate) => {
429
+ if (!canSelectItem(candidate.item)) {
430
+ return [];
431
+ }
432
+ const rect = candidate.getRect();
433
+ if (rect === null) {
434
+ return [];
435
+ }
436
+ return [
437
+ {
438
+ item: candidate.item,
439
+ rect: {
440
+ bottom: rect.bottom,
441
+ left: rect.left,
442
+ right: rect.right,
443
+ top: rect.top,
444
+ },
445
+ },
446
+ ];
447
+ });
448
+ return (0, exports.getTimelineMarqueeSelection)({
449
+ candidates,
450
+ lockedSelectionKind,
451
+ marqueeRect,
452
+ });
453
+ }, [canSelectItem]);
323
454
  const clearSelection = (0, react_1.useCallback)(() => {
324
455
  selectionAnchor.current = null;
325
456
  setSelectedItems([]);
@@ -329,20 +460,26 @@ const TimelineSelectionProvider = ({ children }) => {
329
460
  }, [selectedItems]);
330
461
  const value = (0, react_1.useMemo)(() => ({
331
462
  canSelect,
463
+ canSelectEasing,
332
464
  selectedItems,
333
465
  isSelected,
334
466
  selectItem,
335
467
  selectItems,
336
468
  registerSelectableItem,
469
+ registerMarqueeSelectableItem,
470
+ getMarqueeSelection: getMarqueeSelectionForRect,
337
471
  containsSelection,
338
472
  clearSelection,
339
473
  }), [
340
474
  canSelect,
475
+ canSelectEasing,
341
476
  selectedItems,
342
477
  isSelected,
343
478
  selectItem,
344
479
  selectItems,
345
480
  registerSelectableItem,
481
+ registerMarqueeSelectableItem,
482
+ getMarqueeSelectionForRect,
346
483
  containsSelection,
347
484
  clearSelection,
348
485
  ]);
@@ -356,6 +493,8 @@ const useTimelineSelection = () => {
356
493
  return (0, react_1.useContext)(TimelineSelectionContext);
357
494
  };
358
495
  exports.useTimelineSelection = useTimelineSelection;
496
+ exports.TIMELINE_MARQUEE_ITEM_ATTR = 'data-timeline-marquee-item';
497
+ exports.TIMELINE_SCRUBBER_ATTR = 'data-timeline-scrubber';
359
498
  const useCurrentTimelineSelectionStateAsRef = () => {
360
499
  const currentSelection = (0, react_1.useContext)(CurrentTimelineSelectionContext);
361
500
  if (currentSelection === null) {
@@ -364,6 +503,123 @@ const useCurrentTimelineSelectionStateAsRef = () => {
364
503
  return currentSelection;
365
504
  };
366
505
  exports.useCurrentTimelineSelectionStateAsRef = useCurrentTimelineSelectionStateAsRef;
506
+ const useTimelineMarqueeSelection = () => {
507
+ const { canSelect, canSelectEasing, getMarqueeSelection, selectItems } = (0, exports.useTimelineSelection)();
508
+ const { isHighestContext } = (0, z_index_1.useZIndex)();
509
+ const [marqueeRect, setMarqueeRect] = (0, react_1.useState)(null);
510
+ const onPointerDownCapture = (0, react_1.useCallback)((event) => {
511
+ if (!isHighestContext) {
512
+ return;
513
+ }
514
+ if (event.button !== 0 || (!canSelect && !canSelectEasing)) {
515
+ return;
516
+ }
517
+ if (event.shiftKey || event.metaKey || event.ctrlKey) {
518
+ return;
519
+ }
520
+ if (!(event.target instanceof Element)) {
521
+ return;
522
+ }
523
+ if (event.target.closest(`[${exports.TIMELINE_MARQUEE_ITEM_ATTR}]`) ||
524
+ event.target.closest(`[${exports.TIMELINE_SCRUBBER_ATTR}]`)) {
525
+ return;
526
+ }
527
+ const { currentTarget: target, pointerId } = event;
528
+ if (target.setPointerCapture) {
529
+ target.setPointerCapture(pointerId);
530
+ }
531
+ const initialBounds = target.getBoundingClientRect();
532
+ const marqueeBounds = {
533
+ bottom: initialBounds.bottom,
534
+ left: initialBounds.left,
535
+ right: initialBounds.right,
536
+ top: initialBounds.top,
537
+ };
538
+ const start = (0, exports.getClampedTimelineMarqueePoint)({
539
+ bounds: marqueeBounds,
540
+ x: event.clientX,
541
+ y: event.clientY,
542
+ });
543
+ const startX = start.x;
544
+ const startY = start.y;
545
+ const previousUserSelect = document.body.style.userSelect;
546
+ const previousWebkitUserSelect = document.body.style.webkitUserSelect;
547
+ document.body.style.userSelect = 'none';
548
+ document.body.style.webkitUserSelect = 'none';
549
+ let hasDragged = false;
550
+ let lockedSelectionKind = null;
551
+ const cleanup = () => {
552
+ var _a;
553
+ window.removeEventListener('pointermove', onPointerMove);
554
+ window.removeEventListener('pointerup', onPointerUp);
555
+ window.removeEventListener('pointercancel', onPointerCancel);
556
+ if ((_a = target.hasPointerCapture) === null || _a === void 0 ? void 0 : _a.call(target, pointerId)) {
557
+ target.releasePointerCapture(pointerId);
558
+ }
559
+ document.body.style.userSelect = previousUserSelect;
560
+ document.body.style.webkitUserSelect = previousWebkitUserSelect;
561
+ setMarqueeRect(null);
562
+ };
563
+ const updateSelection = (clientX, clientY) => {
564
+ const current = (0, exports.getClampedTimelineMarqueePoint)({
565
+ bounds: marqueeBounds,
566
+ x: clientX,
567
+ y: clientY,
568
+ });
569
+ if (!hasDragged &&
570
+ Math.max(Math.abs(current.x - startX), Math.abs(current.y - startY)) <
571
+ 3) {
572
+ return;
573
+ }
574
+ hasDragged = true;
575
+ const rect = (0, exports.getNormalizedTimelineMarqueeRect)({
576
+ currentX: current.x,
577
+ currentY: current.y,
578
+ startX,
579
+ startY,
580
+ });
581
+ const nextSelection = getMarqueeSelection(rect, lockedSelectionKind);
582
+ lockedSelectionKind = nextSelection.lockedSelectionKind;
583
+ setMarqueeRect(rect);
584
+ selectItems(nextSelection.selectedItems);
585
+ };
586
+ const onPointerMove = (moveEvent) => {
587
+ updateSelection(moveEvent.clientX, moveEvent.clientY);
588
+ };
589
+ const onPointerUp = (upEvent) => {
590
+ updateSelection(upEvent.clientX, upEvent.clientY);
591
+ cleanup();
592
+ };
593
+ const onPointerCancel = () => {
594
+ cleanup();
595
+ };
596
+ window.addEventListener('pointermove', onPointerMove);
597
+ window.addEventListener('pointerup', onPointerUp);
598
+ window.addEventListener('pointercancel', onPointerCancel);
599
+ }, [
600
+ canSelect,
601
+ canSelectEasing,
602
+ getMarqueeSelection,
603
+ isHighestContext,
604
+ selectItems,
605
+ ]);
606
+ return { marqueeRect, onPointerDownCapture };
607
+ };
608
+ exports.useTimelineMarqueeSelection = useTimelineMarqueeSelection;
609
+ const useTimelineMarqueeSelectableItem = (item, ref) => {
610
+ const { registerMarqueeSelectableItem } = (0, exports.useTimelineSelection)();
611
+ (0, react_1.useEffect)(() => {
612
+ if (item === null) {
613
+ return;
614
+ }
615
+ return registerMarqueeSelectableItem(item, () => {
616
+ var _a;
617
+ var _b;
618
+ return (_b = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) !== null && _b !== void 0 ? _b : null;
619
+ });
620
+ }, [item, ref, registerMarqueeSelectableItem]);
621
+ };
622
+ exports.useTimelineMarqueeSelectableItem = useTimelineMarqueeSelectableItem;
367
623
  const useTimelineRowSelection = (nodePathInfo) => {
368
624
  const { canSelect, isSelected, selectItem, registerSelectableItem } = (0, exports.useTimelineSelection)();
369
625
  const selectionItem = (0, react_1.useMemo)(() => (0, exports.getTimelineSelectionFromNodePathInfo)(nodePathInfo), [nodePathInfo]);
@@ -383,6 +639,7 @@ const useTimelineRowSelection = (nodePathInfo) => {
383
639
  return {
384
640
  onSelect,
385
641
  selectable: canSelect && selectionItem !== null,
642
+ selectionItem,
386
643
  selected,
387
644
  };
388
645
  };
@@ -404,10 +661,35 @@ const useTimelineKeyframeSelection = (nodePathInfo, frame) => {
404
661
  return {
405
662
  onSelect,
406
663
  selectable: canSelect,
664
+ selectionItem,
407
665
  selected,
408
666
  };
409
667
  };
410
668
  exports.useTimelineKeyframeSelection = useTimelineKeyframeSelection;
669
+ const useTimelineEasingSelection = ({ nodePathInfo, fromFrame, toFrame, segmentIndex, }) => {
670
+ const { canSelectEasing, isSelected, selectItem, registerSelectableItem } = (0, exports.useTimelineSelection)();
671
+ const selectionItem = (0, react_1.useMemo)(() => ({
672
+ type: 'easing',
673
+ nodePathInfo,
674
+ fromFrame,
675
+ toFrame,
676
+ segmentIndex,
677
+ }), [nodePathInfo, fromFrame, segmentIndex, toFrame]);
678
+ (0, react_1.useEffect)(() => {
679
+ return registerSelectableItem(selectionItem);
680
+ }, [registerSelectableItem, selectionItem]);
681
+ const selected = isSelected(selectionItem);
682
+ const onSelect = (0, react_1.useCallback)((interaction) => {
683
+ selectItem(selectionItem, interaction);
684
+ }, [selectItem, selectionItem]);
685
+ return {
686
+ onSelect,
687
+ selectable: canSelectEasing,
688
+ selected,
689
+ selectionItem,
690
+ };
691
+ };
692
+ exports.useTimelineEasingSelection = useTimelineEasingSelection;
411
693
  const useTimelineRowContainsSelection = (nodePathInfo) => {
412
694
  const { containsSelection } = (0, exports.useTimelineSelection)();
413
695
  if (nodePathInfo === null) {