@remotion/studio 4.0.492 → 4.0.493

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 (58) hide show
  1. package/dist/ResolveCompositionConfigInStudio.js +16 -6
  2. package/dist/components/CompositionSelector.js +1 -1
  3. package/dist/components/CompositionSelectorItem.js +1 -1
  4. package/dist/components/CurrentComposition.d.ts +1 -1
  5. package/dist/components/CurrentComposition.js +3 -4
  6. package/dist/components/InspectorInfoHeader.d.ts +1 -0
  7. package/dist/components/InspectorInfoHeader.js +7 -2
  8. package/dist/components/InspectorPanel/CompositionDimensions.d.ts +6 -0
  9. package/dist/components/InspectorPanel/CompositionDimensions.js +173 -0
  10. package/dist/components/InspectorPanel/ConnectedCompositionsSection.d.ts +9 -0
  11. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +32 -0
  12. package/dist/components/InspectorPanel/DefaultInspector.js +6 -3
  13. package/dist/components/InspectorPanel/EasingInspector.js +3 -3
  14. package/dist/components/InspectorPanel/KeyframeInspector.js +6 -4
  15. package/dist/components/InspectorPanel/KeyframeSettings.js +1 -1
  16. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +1 -1
  17. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +9 -6
  18. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +5 -2
  19. package/dist/components/InspectorPanel/common.d.ts +2 -1
  20. package/dist/components/InspectorPanel/common.js +11 -7
  21. package/dist/components/InspectorPanel/optimistic-composition-metadata.d.ts +22 -0
  22. package/dist/components/InspectorPanel/optimistic-composition-metadata.js +41 -0
  23. package/dist/components/InspectorPanel/styles.d.ts +2 -0
  24. package/dist/components/InspectorPanel/styles.js +7 -2
  25. package/dist/components/InspectorSequenceSection.js +2 -5
  26. package/dist/components/SelectedOutlineElement.js +21 -2
  27. package/dist/components/SelectedOutlineOverlay.d.ts +1 -1
  28. package/dist/components/SelectedOutlineOverlay.js +4 -3
  29. package/dist/components/Timeline/Timeline.js +8 -1
  30. package/dist/components/Timeline/TimelineClipboardKeybindings.js +133 -1
  31. package/dist/components/Timeline/TimelineList.js +2 -1
  32. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +1 -3
  33. package/dist/components/Timeline/TimelineSelection.js +19 -5
  34. package/dist/components/Timeline/TimelineSequenceItem.d.ts +2 -1
  35. package/dist/components/Timeline/TimelineSequenceItem.js +31 -8
  36. package/dist/components/Timeline/TimelineSequenceName.js +4 -0
  37. package/dist/components/Timeline/keyframe-clipboard.d.ts +34 -0
  38. package/dist/components/Timeline/keyframe-clipboard.js +278 -0
  39. package/dist/components/Timeline/timeline-field-display-utils.js +2 -1
  40. package/dist/components/Timeline/update-selected-easing.d.ts +1 -1
  41. package/dist/components/Timeline/update-selected-easing.js +4 -5
  42. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +3 -4
  43. package/dist/components/selected-outline-measurement.d.ts +2 -5
  44. package/dist/components/selected-outline-measurement.js +3 -4
  45. package/dist/esm/{chunk-ewx0568t.js → chunk-mndqr3zx.js} +5191 -4369
  46. package/dist/esm/internals.mjs +5191 -4369
  47. package/dist/esm/previewEntry.mjs +5781 -4963
  48. package/dist/esm/renderEntry.mjs +1 -1
  49. package/dist/helpers/calculate-timeline.d.ts +2 -1
  50. package/dist/helpers/calculate-timeline.js +36 -5
  51. package/dist/{components/InspectorPanel/get-compositions-matching-single-child.d.ts → helpers/get-connected-compositions.d.ts} +1 -1
  52. package/dist/{components/InspectorPanel/get-compositions-matching-single-child.js → helpers/get-connected-compositions.js} +3 -3
  53. package/dist/helpers/get-sequence-double-click-action.d.ts +6 -0
  54. package/dist/helpers/get-sequence-double-click-action.js +13 -0
  55. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +2 -1
  56. package/package.json +11 -11
  57. package/dist/components/InspectorPanel/SequenceCompositionsSection.d.ts +0 -5
  58. package/dist/components/InspectorPanel/SequenceCompositionsSection.js +0 -37
@@ -40,16 +40,19 @@ const remotion_1 = require("remotion");
40
40
  const client_id_1 = require("../../helpers/client-id");
41
41
  const colors_1 = require("../../helpers/colors");
42
42
  const format_file_location_1 = require("../../helpers/format-file-location");
43
+ const get_sequence_double_click_action_1 = require("../../helpers/get-sequence-double-click-action");
43
44
  const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
44
45
  const studio_runtime_config_1 = require("../../helpers/studio-runtime-config");
45
46
  const timeline_layout_1 = require("../../helpers/timeline-layout");
46
47
  const use_keybinding_1 = require("../../helpers/use-keybinding");
47
48
  const modals_1 = require("../../state/modals");
48
49
  const call_api_1 = require("../call-api");
50
+ const CompositionOrStillIcon_1 = require("../CompositionOrStillIcon");
49
51
  const ConfirmationDialog_1 = require("../ConfirmationDialog");
50
52
  const ContextMenu_1 = require("../ContextMenu");
51
53
  const effect_drag_and_drop_1 = require("../effect-drag-and-drop");
52
54
  const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
55
+ const InitialCompositionLoader_1 = require("../InitialCompositionLoader");
53
56
  const layout_1 = require("../layout");
54
57
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
55
58
  const use_select_asset_1 = require("../use-select-asset");
@@ -76,6 +79,11 @@ const labelContainerStyle = {
76
79
  flexDirection: 'row',
77
80
  minWidth: 0,
78
81
  };
82
+ const connectedCompositionIconStyle = {
83
+ flexShrink: 0,
84
+ height: 12,
85
+ width: 12,
86
+ };
79
87
  const effectDropHighlight = {
80
88
  backgroundColor: colors_1.TIMELINE_DROP_BLUE_ALPHA_16,
81
89
  outline: colors_1.BORDER_TIMELINE_DROP_BLUE,
@@ -155,7 +163,7 @@ const getSequenceReorderDragData = (dataTransfer) => {
155
163
  const getDestinationIndex = ({ fromIndex, insertionIndex, }) => {
156
164
  return insertionIndex > fromIndex ? insertionIndex - 1 : insertionIndex;
157
165
  };
158
- const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDisplayOffset, sequenceFrameOffset, trackIndex, }) => {
166
+ const TimelineSequenceItem = ({ connectedCompositions, nestedDepth, sequence, nodePathInfo, keyframeDisplayOffset, sequenceFrameOffset, trackIndex, }) => {
159
167
  var _a, _b, _c;
160
168
  var _d, _e, _f;
161
169
  const nodePath = (_d = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _d !== void 0 ? _d : null;
@@ -168,6 +176,7 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
168
176
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
169
177
  const { isHighestContext } = (0, use_keybinding_1.useKeybinding)();
170
178
  const selectAsset = (0, use_select_asset_1.useSelectAsset)();
179
+ const selectComposition = (0, InitialCompositionLoader_1.useSelectComposition)();
171
180
  const { onSelect, selectable, selected, selectionItem } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
172
181
  const { selectedItems } = (0, TimelineSelection_1.useTimelineSelection)();
173
182
  const containsSelection = (0, TimelineSelection_1.useTimelineRowContainsSelection)(nodePathInfo);
@@ -202,6 +211,9 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
202
211
  sequence,
203
212
  validatedLocation,
204
213
  });
214
+ const timelineDisplayName = sequence.displayName === '' && connectedCompositions.length === 1
215
+ ? connectedCompositions[0].id
216
+ : displayName;
205
217
  const canDeleteFromSource = Boolean(nodePath && (validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source));
206
218
  const nodePathKey = (0, react_1.useMemo)(() => nodePath ? remotion_1.Internals.makeSequencePropsSubscriptionKey(nodePath) : null, [nodePath]);
207
219
  const parentId = (_e = sequence.parent) !== null && _e !== void 0 ? _e : null;
@@ -536,17 +548,27 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
536
548
  codeHiddenStatus !== undefined &&
537
549
  codeHiddenStatus !== null &&
538
550
  codeHiddenStatus.status === 'static';
539
- const onShowInEditorDoubleClick = (0, react_1.useCallback)((e) => {
540
- if (!canOpenInEditor) {
541
- return;
542
- }
551
+ const onSequenceDoubleClick = (0, react_1.useCallback)((e) => {
543
552
  if ((0, TimelineSelection_1.isTimelineSelectionModifierEvent)(e)) {
544
553
  e.stopPropagation();
545
554
  return;
546
555
  }
556
+ const action = (0, get_sequence_double_click_action_1.getSequenceDoubleClickAction)({
557
+ button: e.button,
558
+ canOpenInEditor,
559
+ numberOfConnectedCompositions: connectedCompositions.length,
560
+ });
561
+ if (action === null) {
562
+ return;
563
+ }
547
564
  e.stopPropagation();
565
+ if (action === 'open-connected-composition') {
566
+ selectComposition(connectedCompositions[0], true);
567
+ return;
568
+ }
548
569
  openInEditor();
549
- }, [canOpenInEditor, openInEditor]);
570
+ }, [canOpenInEditor, connectedCompositions, openInEditor, selectComposition]);
571
+ const canHandleSequenceDoubleClick = connectedCompositions.length === 1 || canOpenInEditor;
550
572
  const canRenameSelectedSequence = canRenameThisSequence &&
551
573
  selected &&
552
574
  selectedItems.length === 1 &&
@@ -766,8 +788,9 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
766
788
  clientId: previewServerState.clientId,
767
789
  });
768
790
  }, [canDropEffect, nodePath, previewServerState, validatedLocation]);
769
- 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: !previewInteractive, 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: canOpenInEditor ? onShowInEditorDoubleClick : undefined, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [
770
- 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: [
791
+ 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: !previewInteractive, 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: canHandleSequenceDoubleClick ? onSequenceDoubleClick : undefined, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [connectedCompositions.length > 0 ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
792
+ jsx_runtime_1.jsx(CompositionOrStillIcon_1.CompositionOrStillIcon, { color: (0, TimelineSelection_1.getTimelineColor)(false, false), composition: connectedCompositions[0], style: connectedCompositionIconStyle }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 })
793
+ ] })) : null, jsx_runtime_1.jsx(TimelineSequenceName_1.TimelineSequenceName, { displayName: timelineDisplayName, fallbackDisplayName: fallbackDisplayName, selected: selected, containsSelection: containsSelection, editing: isRenaming, onCancelEditing: onCancelRenaming, onSaveName: onSaveName }), mediaSrc ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
771
794
  jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }),
772
795
  " ",
773
796
  jsx_runtime_1.jsx(TimelineMediaInfo_1.TimelineMediaInfo, { src: mediaSrc })
@@ -24,7 +24,11 @@ const TimelineSequenceName = ({ displayName, fallbackDisplayName, selected, cont
24
24
  alignSelf: 'stretch',
25
25
  ...(0, TimelineSelection_1.getTimelineSelectedLabelStyle)(selected, false),
26
26
  display: 'inline-flex',
27
+ fontFamily: 'inherit',
27
28
  fontSize: 12,
29
+ lineHeight: 'normal',
30
+ minWidth: 0,
31
+ overflow: 'hidden',
28
32
  whiteSpace: 'nowrap',
29
33
  textOverflow: 'ellipsis',
30
34
  color: (0, TimelineSelection_1.getTimelineColor)(selected, false),
@@ -0,0 +1,34 @@
1
+ import type { KeyframeClipboardData } from '@remotion/studio-shared';
2
+ import { type InteractivitySchema, type OverrideIdToNodePaths, type PropStatuses, type SequencePropsSubscriptionKey, type TSequence } from 'remotion';
3
+ import type { TimelineSelection } from './TimelineSelection';
4
+ export declare const getKeyframeClipboardDataFromSelections: ({ selections, sequences, overrideIdsToNodePaths, propStatuses, }: {
5
+ readonly selections: readonly TimelineSelection[];
6
+ readonly sequences: TSequence[];
7
+ readonly overrideIdsToNodePaths: OverrideIdToNodePaths;
8
+ readonly propStatuses: PropStatuses;
9
+ }) => KeyframeClipboardData | null;
10
+ export type PasteKeyframeTarget = {
11
+ readonly type: 'valid';
12
+ readonly fileName: string;
13
+ readonly nodePath: SequencePropsSubscriptionKey;
14
+ readonly fieldKey: string;
15
+ readonly effectIndex: number | null;
16
+ readonly keyframes: readonly {
17
+ readonly sourceFrame: number;
18
+ readonly value: unknown;
19
+ }[];
20
+ readonly keyframesToDelete: readonly number[];
21
+ readonly easing: KeyframeClipboardData['easing'];
22
+ readonly firstEasingSegmentIndex: number;
23
+ readonly schema: InteractivitySchema;
24
+ } | {
25
+ readonly type: 'none' | 'multiple' | 'uncopyable' | 'incompatible';
26
+ };
27
+ export declare const getPasteKeyframeTarget: ({ selectedItems, payload, timelinePosition, sequences, overrideIdsToNodePaths, propStatuses, }: {
28
+ readonly selectedItems: readonly TimelineSelection[];
29
+ readonly payload: KeyframeClipboardData;
30
+ readonly timelinePosition: number;
31
+ readonly sequences: TSequence[];
32
+ readonly overrideIdsToNodePaths: OverrideIdToNodePaths;
33
+ readonly propStatuses: PropStatuses;
34
+ }) => PasteKeyframeTarget;
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPasteKeyframeTarget = exports.getKeyframeClipboardDataFromSelections = void 0;
4
+ const studio_shared_1 = require("@remotion/studio-shared");
5
+ const remotion_1 = require("remotion");
6
+ const find_track_for_node_path_info_1 = require("./find-track-for-node-path-info");
7
+ const parse_keyframe_field_from_node_path_1 = require("./parse-keyframe-field-from-node-path");
8
+ const getKeyframeClipboardFieldType = ({ schema, fieldKey, }) => {
9
+ const field = remotion_1.Internals.getFlatSchemaWithAllKeys(schema)[fieldKey];
10
+ if (!field) {
11
+ return null;
12
+ }
13
+ return (0, studio_shared_1.isKeyframeClipboardFieldType)(field.type) ? field.type : null;
14
+ };
15
+ const getKeyframeFieldIdentity = (selection) => {
16
+ if (selection.type === 'keyframe' || selection.type === 'easing') {
17
+ return (0, parse_keyframe_field_from_node_path_1.parseKeyframeFieldFromNodePath)(selection.nodePathInfo.auxiliaryKeys);
18
+ }
19
+ if (selection.type === 'sequence-prop') {
20
+ return { type: 'sequence', fieldKey: selection.key };
21
+ }
22
+ if (selection.type === 'sequence-effect-prop') {
23
+ return {
24
+ type: 'effect',
25
+ effectIndex: selection.i,
26
+ fieldKey: selection.key,
27
+ };
28
+ }
29
+ return null;
30
+ };
31
+ const resolveKeyframeField = ({ selection, sequences, overrideIdsToNodePaths, propStatuses, }) => {
32
+ var _a, _b;
33
+ if (selection.type !== 'keyframe' &&
34
+ selection.type !== 'easing' &&
35
+ selection.type !== 'sequence-prop' &&
36
+ selection.type !== 'sequence-effect-prop') {
37
+ return null;
38
+ }
39
+ const identity = getKeyframeFieldIdentity(selection);
40
+ if (identity === null) {
41
+ return null;
42
+ }
43
+ const track = (0, find_track_for_node_path_info_1.findTrackForNodePathInfo)({
44
+ sequences,
45
+ overrideIdsToNodePaths,
46
+ nodePathInfo: selection.nodePathInfo,
47
+ });
48
+ if (!track || track.nodePathInfo === null) {
49
+ return null;
50
+ }
51
+ const nodePath = track.nodePathInfo.sequenceSubscriptionKey;
52
+ if (identity.type === 'sequence') {
53
+ if (!track.sequence.controls) {
54
+ return null;
55
+ }
56
+ const sequencePropStatus = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a[identity.fieldKey];
57
+ if (!sequencePropStatus || sequencePropStatus.status === 'computed') {
58
+ return null;
59
+ }
60
+ const { schema } = track.sequence.controls;
61
+ return {
62
+ identity,
63
+ nodePath,
64
+ fileName: nodePath.absolutePath,
65
+ schema,
66
+ fieldType: getKeyframeClipboardFieldType({
67
+ schema,
68
+ fieldKey: identity.fieldKey,
69
+ }),
70
+ propStatus: sequencePropStatus,
71
+ keyframeDisplayOffset: track.keyframeDisplayOffset,
72
+ };
73
+ }
74
+ const effect = track.sequence.effects[identity.effectIndex];
75
+ const effectStatus = remotion_1.Internals.getEffectPropStatusesCtx({
76
+ propStatuses,
77
+ nodePath,
78
+ effectIndex: identity.effectIndex,
79
+ });
80
+ const effectPropStatus = effectStatus.type === 'can-update-effect'
81
+ ? (_b = effectStatus.props) === null || _b === void 0 ? void 0 : _b[identity.fieldKey]
82
+ : null;
83
+ if (!effect || !effectPropStatus || effectPropStatus.status === 'computed') {
84
+ return null;
85
+ }
86
+ return {
87
+ identity,
88
+ nodePath,
89
+ fileName: nodePath.absolutePath,
90
+ schema: effect.schema,
91
+ fieldType: getKeyframeClipboardFieldType({
92
+ schema: effect.schema,
93
+ fieldKey: identity.fieldKey,
94
+ }),
95
+ propStatus: effectPropStatus,
96
+ keyframeDisplayOffset: track.keyframeDisplayOffset,
97
+ };
98
+ };
99
+ const areResolvedFieldsEqual = (first, second) => {
100
+ if (remotion_1.Internals.makeSequencePropsSubscriptionKey(first.nodePath) !==
101
+ remotion_1.Internals.makeSequencePropsSubscriptionKey(second.nodePath)) {
102
+ return false;
103
+ }
104
+ if (first.identity.type !== second.identity.type) {
105
+ return false;
106
+ }
107
+ if (first.identity.fieldKey !== second.identity.fieldKey) {
108
+ return false;
109
+ }
110
+ return (first.identity.type === 'sequence' ||
111
+ (second.identity.type === 'effect' &&
112
+ first.identity.effectIndex === second.identity.effectIndex));
113
+ };
114
+ const getKeyframeClipboardDataFromSelections = ({ selections, sequences, overrideIdsToNodePaths, propStatuses, }) => {
115
+ var _a, _b;
116
+ const keyframeSelections = selections.filter((selection) => selection.type === 'keyframe');
117
+ const easingSelections = selections.filter((selection) => selection.type === 'easing');
118
+ if (keyframeSelections.length + easingSelections.length !==
119
+ selections.length) {
120
+ return null;
121
+ }
122
+ const resolvedFields = keyframeSelections.map((selection) => ({
123
+ selection,
124
+ resolved: resolveKeyframeField({
125
+ selection,
126
+ sequences,
127
+ overrideIdsToNodePaths,
128
+ propStatuses,
129
+ }),
130
+ }));
131
+ const firstResolved = (_a = resolvedFields[0]) === null || _a === void 0 ? void 0 : _a.resolved;
132
+ if (firstResolved === null ||
133
+ firstResolved === undefined ||
134
+ resolvedFields.some(({ resolved }) => resolved === null || !areResolvedFieldsEqual(firstResolved, resolved))) {
135
+ return null;
136
+ }
137
+ const keyframedPropStatus = firstResolved.propStatus;
138
+ if (keyframedPropStatus.status !== 'keyframed') {
139
+ return null;
140
+ }
141
+ const keyframes = [];
142
+ for (const { selection } of resolvedFields) {
143
+ const sourceFrame = selection.frame - firstResolved.keyframeDisplayOffset;
144
+ const keyframe = keyframedPropStatus.keyframes.find((item) => item.frame === sourceFrame);
145
+ if (keyframe === undefined ||
146
+ JSON.stringify(keyframe.value) === undefined) {
147
+ return null;
148
+ }
149
+ keyframes.push({ frame: sourceFrame, value: keyframe.value });
150
+ }
151
+ keyframes.sort((first, second) => first.frame - second.frame);
152
+ const firstFrame = (_b = keyframes[0]) === null || _b === void 0 ? void 0 : _b.frame;
153
+ if (firstFrame === undefined) {
154
+ return null;
155
+ }
156
+ const keyframeIndexes = keyframes.map((keyframe) => keyframedPropStatus.keyframes.findIndex((item) => item.frame === keyframe.frame));
157
+ if (keyframeIndexes.some((index, position) => index === -1 ||
158
+ (position > 0 && index !== keyframeIndexes[position - 1] + 1))) {
159
+ return null;
160
+ }
161
+ const firstKeyframeIndex = keyframeIndexes[0];
162
+ const lastKeyframeIndex = keyframeIndexes.at(-1);
163
+ if (firstKeyframeIndex === undefined || lastKeyframeIndex === undefined) {
164
+ return null;
165
+ }
166
+ for (const easingSelection of easingSelections) {
167
+ const resolved = resolveKeyframeField({
168
+ selection: easingSelection,
169
+ sequences,
170
+ overrideIdsToNodePaths,
171
+ propStatuses,
172
+ });
173
+ if (resolved === null ||
174
+ !areResolvedFieldsEqual(firstResolved, resolved) ||
175
+ easingSelection.segmentIndex < firstKeyframeIndex ||
176
+ easingSelection.segmentIndex >= lastKeyframeIndex) {
177
+ return null;
178
+ }
179
+ }
180
+ return {
181
+ type: 'keyframe',
182
+ version: 1,
183
+ remotionClipboard: 'keyframe',
184
+ fieldType: firstResolved.fieldType,
185
+ keyframes: keyframes.map((keyframe) => {
186
+ return {
187
+ frameOffset: keyframe.frame - firstFrame,
188
+ value: keyframe.value,
189
+ };
190
+ }),
191
+ easing: keyframeIndexes.slice(0, -1).map((index) => {
192
+ var _a;
193
+ return (_a = keyframedPropStatus.easing[index]) !== null && _a !== void 0 ? _a : studio_shared_1.LINEAR_KEYFRAME_EASING;
194
+ }),
195
+ };
196
+ };
197
+ exports.getKeyframeClipboardDataFromSelections = getKeyframeClipboardDataFromSelections;
198
+ const isKeyframeValueCompatible = ({ value, fieldType, }) => {
199
+ if (fieldType === null) {
200
+ return true;
201
+ }
202
+ if (fieldType === 'number' || fieldType === 'rotation-degrees') {
203
+ return typeof value === 'number' && Number.isFinite(value);
204
+ }
205
+ if (fieldType === 'scale') {
206
+ return ((typeof value === 'number' && Number.isFinite(value)) ||
207
+ typeof value === 'string');
208
+ }
209
+ if (fieldType === 'uv-coordinate') {
210
+ return (Array.isArray(value) &&
211
+ value.length === 2 &&
212
+ value.every((item) => typeof item === 'number' && Number.isFinite(item)));
213
+ }
214
+ return typeof value === 'string';
215
+ };
216
+ const getPasteKeyframeTarget = ({ selectedItems, payload, timelinePosition, sequences, overrideIdsToNodePaths, propStatuses, }) => {
217
+ var _a, _b;
218
+ if (selectedItems.length === 0) {
219
+ return { type: 'none' };
220
+ }
221
+ const selection = selectedItems[0];
222
+ if (!selection || getKeyframeFieldIdentity(selection) === null) {
223
+ return { type: 'none' };
224
+ }
225
+ const resolvedFields = selectedItems.map((item) => resolveKeyframeField({
226
+ selection: item,
227
+ sequences,
228
+ overrideIdsToNodePaths,
229
+ propStatuses,
230
+ }));
231
+ const resolved = resolvedFields[0];
232
+ if (resolved === null) {
233
+ return { type: 'uncopyable' };
234
+ }
235
+ if (resolvedFields.some((field) => field === null || !areResolvedFieldsEqual(resolved, field))) {
236
+ return { type: 'multiple' };
237
+ }
238
+ const keyframes = payload.keyframes.map((keyframe) => ({
239
+ sourceFrame: timelinePosition - resolved.keyframeDisplayOffset + keyframe.frameOffset,
240
+ value: keyframe.value,
241
+ }));
242
+ const firstFrame = (_a = keyframes[0]) === null || _a === void 0 ? void 0 : _a.sourceFrame;
243
+ const lastFrame = (_b = keyframes.at(-1)) === null || _b === void 0 ? void 0 : _b.sourceFrame;
244
+ if (firstFrame === undefined || lastFrame === undefined) {
245
+ return { type: 'incompatible' };
246
+ }
247
+ const existingFrames = resolved.propStatus.status === 'keyframed'
248
+ ? resolved.propStatus.keyframes.map((keyframe) => keyframe.frame)
249
+ : [];
250
+ const keyframesToDelete = existingFrames.filter((frame) => frame >= firstFrame && frame <= lastFrame);
251
+ const finalFrames = [
252
+ ...existingFrames.filter((frame) => frame < firstFrame || frame > lastFrame),
253
+ ...keyframes.map((keyframe) => keyframe.sourceFrame),
254
+ ].sort((first, second) => first - second);
255
+ const firstEasingSegmentIndex = finalFrames.indexOf(firstFrame);
256
+ if (resolved.fieldType !== payload.fieldType ||
257
+ payload.keyframes.some((keyframe) => !isKeyframeValueCompatible({
258
+ value: keyframe.value,
259
+ fieldType: payload.fieldType,
260
+ }))) {
261
+ return { type: 'incompatible' };
262
+ }
263
+ return {
264
+ type: 'valid',
265
+ fileName: resolved.fileName,
266
+ nodePath: resolved.nodePath,
267
+ fieldKey: resolved.identity.fieldKey,
268
+ effectIndex: resolved.identity.type === 'effect'
269
+ ? resolved.identity.effectIndex
270
+ : null,
271
+ keyframes,
272
+ keyframesToDelete,
273
+ easing: payload.easing,
274
+ firstEasingSegmentIndex,
275
+ schema: resolved.schema,
276
+ };
277
+ };
278
+ exports.getPasteKeyframeTarget = getPasteKeyframeTarget;
@@ -241,10 +241,11 @@ const formatTimelineFieldValueForDisplay = ({ fieldSchema, value, }) => {
241
241
  case 'boolean':
242
242
  case 'color':
243
243
  case 'enum':
244
+ case 'font-family':
244
245
  case 'hidden':
245
246
  return formatUnknownTimelineValueForDisplay(value);
246
247
  default:
247
- return formatUnknownTimelineValueForDisplay(value);
248
+ throw new Error(`Unsupported field type: ${fieldSchema}`);
248
249
  }
249
250
  };
250
251
  exports.formatTimelineFieldValueForDisplay = formatTimelineFieldValueForDisplay;
@@ -1,3 +1,4 @@
1
+ export { canEditEasingForInterpolationFunction } from '@remotion/studio-shared';
1
2
  import type { CanUpdateSequencePropStatusKeyframed, CanUpdateSequencePropStatusEasing, DragOverrideValue, OverrideIdToNodePaths, PropStatuses, SequencePropsSubscriptionKey, InteractivitySchema, TSequence } from 'remotion';
2
3
  import type { SetPropStatuses } from './save-sequence-prop';
3
4
  import type { TimelineEasingSelection, TimelineSelection } from './TimelineSelection';
@@ -23,7 +24,6 @@ export type SelectedEasingUpdate = {
23
24
  readonly currentEasing: TimelineEasingValue;
24
25
  readonly propStatus: CanUpdateSequencePropStatusKeyframed;
25
26
  };
26
- export declare const canEditEasingForInterpolationFunction: (interpolationFunction: string) => boolean;
27
27
  export declare const getSelectedEasingUpdate: ({ selection, sequences, overrideIdsToNodePaths, propStatuses, }: {
28
28
  selection: {
29
29
  readonly type: "easing";
@@ -2,13 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.updateSelectedTimelineEasings = exports.getTimelineEasingValueForSelection = exports.getEasingSelections = exports.makeEasingDragOverride = exports.getSelectedEasingUpdates = exports.getSelectedEasingUpdate = exports.canEditEasingForInterpolationFunction = void 0;
4
4
  const studio_shared_1 = require("@remotion/studio-shared");
5
+ const studio_shared_2 = require("@remotion/studio-shared");
6
+ Object.defineProperty(exports, "canEditEasingForInterpolationFunction", { enumerable: true, get: function () { return studio_shared_2.canEditEasingForInterpolationFunction; } });
5
7
  const remotion_1 = require("remotion");
6
8
  const call_update_keyframe_settings_1 = require("./call-update-keyframe-settings");
7
9
  const find_track_for_node_path_info_1 = require("./find-track-for-node-path-info");
8
10
  const parse_keyframe_field_from_node_path_1 = require("./parse-keyframe-field-from-node-path");
9
- const canEditEasingForInterpolationFunction = (interpolationFunction) => interpolationFunction === 'interpolate' ||
10
- interpolationFunction === 'interpolateColors';
11
- exports.canEditEasingForInterpolationFunction = canEditEasingForInterpolationFunction;
12
11
  const isEasingSelection = (selection) => selection.type === 'easing';
13
12
  const getSelectedEasingUpdate = ({ selection, sequences, overrideIdsToNodePaths, propStatuses, }) => {
14
13
  var _a;
@@ -34,7 +33,7 @@ const getSelectedEasingUpdate = ({ selection, sequences, overrideIdsToNodePaths,
34
33
  }
35
34
  const sequencePropStatus = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a[field.fieldKey];
36
35
  if ((sequencePropStatus === null || sequencePropStatus === void 0 ? void 0 : sequencePropStatus.status) !== 'keyframed' ||
37
- !(0, exports.canEditEasingForInterpolationFunction)(sequencePropStatus.interpolationFunction)) {
36
+ !(0, studio_shared_1.canEditEasingForInterpolationFunction)(sequencePropStatus.interpolationFunction)) {
38
37
  return null;
39
38
  }
40
39
  return {
@@ -61,7 +60,7 @@ const getSelectedEasingUpdate = ({ selection, sequences, overrideIdsToNodePaths,
61
60
  ? effectStatus.props[field.fieldKey]
62
61
  : null;
63
62
  if ((effectPropStatus === null || effectPropStatus === void 0 ? void 0 : effectPropStatus.status) !== 'keyframed' ||
64
- !(0, exports.canEditEasingForInterpolationFunction)(effectPropStatus.interpolationFunction)) {
63
+ !(0, studio_shared_1.canEditEasingForInterpolationFunction)(effectPropStatus.interpolationFunction)) {
65
64
  return null;
66
65
  }
67
66
  return {
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useExpandedTrackKeyframeRows = void 0;
4
+ const studio_shared_1 = require("@remotion/studio-shared");
4
5
  const react_1 = require("react");
5
6
  const remotion_1 = require("remotion");
6
7
  const timeline_layout_1 = require("../../helpers/timeline-layout");
@@ -9,8 +10,6 @@ const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
9
10
  const get_node_keyframes_1 = require("./get-node-keyframes");
10
11
  const timeline_expanded_filter_1 = require("./timeline-expanded-filter");
11
12
  const TimelineSelection_1 = require("./TimelineSelection");
12
- const canEditEasingForInterpolationFunction = (interpolationFunction) => interpolationFunction === 'interpolate' ||
13
- interpolationFunction === 'interpolateColors';
14
13
  const getNodeCanEditEasing = ({ node, nodePath, propStatuses, }) => {
15
14
  var _a;
16
15
  if (node.kind !== 'field' || node.field === null) {
@@ -19,7 +18,7 @@ const getNodeCanEditEasing = ({ node, nodePath, propStatuses, }) => {
19
18
  if (node.field.kind === 'sequence-field') {
20
19
  const sequencePropStatus = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a[node.field.key];
21
20
  return ((sequencePropStatus === null || sequencePropStatus === void 0 ? void 0 : sequencePropStatus.status) === 'keyframed' &&
22
- canEditEasingForInterpolationFunction(sequencePropStatus.interpolationFunction));
21
+ (0, studio_shared_1.canEditEasingForInterpolationFunction)(sequencePropStatus.interpolationFunction));
23
22
  }
24
23
  const effectStatus = remotion_1.Internals.getEffectPropStatusesCtx({
25
24
  propStatuses,
@@ -30,7 +29,7 @@ const getNodeCanEditEasing = ({ node, nodePath, propStatuses, }) => {
30
29
  ? effectStatus.props[node.field.key]
31
30
  : null;
32
31
  return ((effectPropStatus === null || effectPropStatus === void 0 ? void 0 : effectPropStatus.status) === 'keyframed' &&
33
- canEditEasingForInterpolationFunction(effectPropStatus.interpolationFunction));
32
+ (0, studio_shared_1.canEditEasingForInterpolationFunction)(effectPropStatus.interpolationFunction));
34
33
  };
35
34
  const useExpandedTrackKeyframeRows = ({ sequence, nodePathInfo, keyframeDisplayOffset, }) => {
36
35
  const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
@@ -48,10 +48,6 @@ export declare const getOutlineSelectionInteraction: ({ shiftKey, metaKey, ctrlK
48
48
  readonly metaKey: boolean;
49
49
  readonly ctrlKey: boolean;
50
50
  }) => TimelineSelectionInteraction;
51
- export declare const getOutlineDoubleClickAction: ({ button, canOpenInEditor, }: {
52
- readonly button: number;
53
- readonly canOpenInEditor: boolean;
54
- }) => "open-in-editor" | null;
55
51
  type SelectedEffectFields = {
56
52
  allFields: boolean;
57
53
  fieldKeys: Set<string>;
@@ -62,9 +58,10 @@ type SelectedTransformOriginInfo = {
62
58
  readonly displayFrame: number | null;
63
59
  };
64
60
  export declare const getSelectedTransformOriginInfo: (selectedItems: readonly TimelineSelection[]) => SelectedTransformOriginInfo | null;
65
- export declare const getSequencesWithSelectableOutlines: ({ sequences, overrideIdsToNodePaths, }: {
61
+ export declare const getSequencesWithSelectableOutlines: ({ sequences, overrideIdsToNodePaths, compositions, }: {
66
62
  readonly sequences: readonly TSequence[];
67
63
  readonly overrideIdsToNodePaths: OverrideIdToNodePaths;
64
+ readonly compositions?: readonly import("remotion").AnyComposition[] | undefined;
68
65
  }) => SequenceWithSelectedOutline[];
69
66
  export declare const measureOutlines: (container: SVGSVGElement, targets: readonly SelectedOutlineTarget[]) => SelectedOutline[];
70
67
  export declare const outlinesAreEqual: (a: readonly SelectedOutline[], b: readonly SelectedOutline[]) => boolean;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.outlinesAreEqual = exports.measureOutlines = exports.getSequencesWithSelectableOutlines = exports.getSelectedTransformOriginInfo = exports.getSelectedEffectFieldsBySequenceKey = exports.getOutlineDoubleClickAction = exports.getOutlineSelectionInteraction = exports.getSequenceKeysContainingSelection = exports.getSelectedSequenceKeys = exports.getTransformedSvgViewportPoints = exports.getSelectedOutlineRotationPivot = exports.getSelectedOutlineRotationCornerInfo = exports.getRotationCursor = exports.getSelectedOutlineRotationDeltaDegrees = exports.getAngleDegrees = exports.vectorBetween = exports.vectorLength = exports.dot = exports.getOutlineCenter = exports.midpoint = exports.pointToString = void 0;
3
+ exports.outlinesAreEqual = exports.measureOutlines = exports.getSequencesWithSelectableOutlines = exports.getSelectedTransformOriginInfo = exports.getSelectedEffectFieldsBySequenceKey = exports.getOutlineSelectionInteraction = exports.getSequenceKeysContainingSelection = exports.getSelectedSequenceKeys = exports.getTransformedSvgViewportPoints = exports.getSelectedOutlineRotationPivot = exports.getSelectedOutlineRotationCornerInfo = exports.getRotationCursor = exports.getSelectedOutlineRotationDeltaDegrees = exports.getAngleDegrees = exports.vectorBetween = exports.vectorLength = exports.dot = exports.getOutlineCenter = exports.midpoint = exports.pointToString = void 0;
4
4
  const calculate_timeline_1 = require("../helpers/calculate-timeline");
5
5
  const colors_1 = require("../helpers/colors");
6
6
  const get_box_quads_ponyfill_1 = require("../helpers/get-box-quads-ponyfill");
@@ -220,8 +220,6 @@ const getOutlineSelectionInteraction = ({ shiftKey, metaKey, ctrlKey, }) => ({
220
220
  toggleKey: metaKey || ctrlKey,
221
221
  });
222
222
  exports.getOutlineSelectionInteraction = getOutlineSelectionInteraction;
223
- const getOutlineDoubleClickAction = ({ button, canOpenInEditor, }) => button === 0 && canOpenInEditor ? 'open-in-editor' : null;
224
- exports.getOutlineDoubleClickAction = getOutlineDoubleClickAction;
225
223
  const getKeyframeOrEasingField = (item) => {
226
224
  if (item.type !== 'keyframe' && item.type !== 'easing') {
227
225
  return null;
@@ -308,10 +306,11 @@ const getSelectedTransformOriginInfo = (selectedItems) => {
308
306
  };
309
307
  };
310
308
  exports.getSelectedTransformOriginInfo = getSelectedTransformOriginInfo;
311
- const getSequencesWithSelectableOutlines = ({ sequences, overrideIdsToNodePaths, }) => {
309
+ const getSequencesWithSelectableOutlines = ({ sequences, overrideIdsToNodePaths, compositions = [], }) => {
312
310
  return (0, calculate_timeline_1.calculateTimeline)({
313
311
  sequences: [...sequences],
314
312
  overrideIdsToNodePaths,
313
+ compositions,
315
314
  })
316
315
  .filter((track) => {
317
316
  if (track.nodePathInfo === null) {