@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
@@ -3,15 +3,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.InspectorDefaultPropsWarnings = exports.InspectorInlineAction = exports.InspectorDetailRow = exports.InspectorMessage = exports.InspectorBackHeaderWithDivider = exports.InspectorSectionHeader = void 0;
6
+ exports.InspectorDefaultPropsWarnings = exports.InspectorInlineAction = exports.InspectorDetailRow = exports.InspectorMessage = exports.InspectorBackHeader = exports.InspectorSectionDivider = exports.InspectorSectionHeader = void 0;
7
7
  const jsx_runtime_1 = require("react/jsx-runtime");
8
8
  const react_1 = __importDefault(require("react"));
9
9
  const colors_1 = require("../../helpers/colors");
10
10
  const InlineAction_1 = require("../InlineAction");
11
+ const InspectorPanelLayout_1 = require("../InspectorPanelLayout");
11
12
  const ValidationMessage_1 = require("../NewComposition/ValidationMessage");
12
13
  const styles_1 = require("./styles");
13
14
  const InspectorSectionHeader = ({ children }) => jsx_runtime_1.jsx("div", { style: styles_1.sectionHeader, children: children });
14
15
  exports.InspectorSectionHeader = InspectorSectionHeader;
16
+ const InspectorSectionDivider = () => (jsx_runtime_1.jsx("div", { style: styles_1.inspectorSectionDivider }));
17
+ exports.InspectorSectionDivider = InspectorSectionDivider;
15
18
  const backIcon = {
16
19
  alignItems: 'center',
17
20
  display: 'flex',
@@ -22,12 +25,10 @@ const backIcon = {
22
25
  const BackChevron = ({ color }) => {
23
26
  return (jsx_runtime_1.jsx("svg", { viewBox: "0 0 8 12", style: backIcon, children: jsx_runtime_1.jsx("path", { d: "M6 1L2 6L6 11", fill: "none", stroke: color, strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5" }) }));
24
27
  };
25
- const InspectorBackHeaderWithDivider = ({ children, disabled, onClick, title }) => {
26
- return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
27
- jsx_runtime_1.jsx(exports.InspectorSectionHeader, { children: jsx_runtime_1.jsx("div", { style: styles_1.sectionHeaderRow, children: jsx_runtime_1.jsxs("div", { style: styles_1.sectionHeaderStart, children: [jsx_runtime_1.jsx(InlineAction_1.InlineAction, { disabled: disabled, onClick: onClick, title: title, renderAction: (color) => jsx_runtime_1.jsx(BackChevron, { color: color }) }), children] }) }) }), jsx_runtime_1.jsx("div", { style: styles_1.inspectorSectionDivider })
28
- ] }));
28
+ const InspectorBackHeader = ({ children, disabled, onClick, title }) => {
29
+ return (jsx_runtime_1.jsx(exports.InspectorSectionHeader, { children: jsx_runtime_1.jsx("div", { style: styles_1.sectionHeaderRow, children: jsx_runtime_1.jsxs("div", { style: styles_1.sectionHeaderStart, children: [jsx_runtime_1.jsx(InlineAction_1.InlineAction, { disabled: disabled, onClick: onClick, title: title, renderAction: (color) => jsx_runtime_1.jsx(BackChevron, { color: color }) }), children] }) }) }));
29
30
  };
30
- exports.InspectorBackHeaderWithDivider = InspectorBackHeaderWithDivider;
31
+ exports.InspectorBackHeader = InspectorBackHeader;
31
32
  const InspectorMessage = ({ children }) => jsx_runtime_1.jsx("div", { style: styles_1.centeredMessage, children: children });
32
33
  exports.InspectorMessage = InspectorMessage;
33
34
  const InspectorDetailRow = ({ label, children }) => (jsx_runtime_1.jsxs("div", { style: styles_1.detailRow, children: [
@@ -39,6 +40,7 @@ const inlineLabelButton = {
39
40
  appearance: 'none',
40
41
  backgroundColor: colors_1.TRANSPARENT,
41
42
  border: 'none',
43
+ boxSizing: 'border-box',
42
44
  color: colors_1.LIGHT_TEXT,
43
45
  cursor: 'default',
44
46
  display: 'flex',
@@ -47,7 +49,9 @@ const inlineLabelButton = {
47
49
  gap: 8,
48
50
  lineHeight: '18px',
49
51
  margin: 0,
50
- padding: '5px 0',
52
+ padding: `5px ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px`,
53
+ textAlign: 'left',
54
+ width: '100%',
51
55
  };
52
56
  const inlineLabelButtonDisabled = {
53
57
  ...inlineLabelButton,
@@ -0,0 +1,22 @@
1
+ export type CompositionMetadataField = 'durationInFrames' | 'fps' | 'height' | 'width';
2
+ export type PendingCompositionMetadataValue = {
3
+ readonly baseline: object;
4
+ readonly status: 'saving' | 'awaiting-hmr';
5
+ readonly value: number;
6
+ };
7
+ export type PendingCompositionMetadata = Partial<Record<CompositionMetadataField, PendingCompositionMetadataValue>>;
8
+ export declare const failPendingCompositionMetadataValue: ({ field, pending, value, }: {
9
+ readonly field: CompositionMetadataField;
10
+ readonly pending: Partial<Record<CompositionMetadataField, PendingCompositionMetadataValue>>;
11
+ readonly value: PendingCompositionMetadataValue;
12
+ }) => Partial<Record<CompositionMetadataField, PendingCompositionMetadataValue>>;
13
+ export declare const acceptPendingCompositionMetadataValue: ({ currentConfig, field, pending, value, }: {
14
+ readonly currentConfig: object;
15
+ readonly field: CompositionMetadataField;
16
+ readonly pending: Partial<Record<CompositionMetadataField, PendingCompositionMetadataValue>>;
17
+ readonly value: PendingCompositionMetadataValue;
18
+ }) => Partial<Record<CompositionMetadataField, PendingCompositionMetadataValue>>;
19
+ export declare const reconcilePendingCompositionMetadata: ({ currentConfig, pending, }: {
20
+ readonly currentConfig: object;
21
+ readonly pending: Partial<Record<CompositionMetadataField, PendingCompositionMetadataValue>>;
22
+ }) => Partial<Record<CompositionMetadataField, PendingCompositionMetadataValue>>;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reconcilePendingCompositionMetadata = exports.acceptPendingCompositionMetadataValue = exports.failPendingCompositionMetadataValue = void 0;
4
+ const removePendingValue = ({ field, pending, }) => {
5
+ const { [field]: _removed, ...remaining } = pending;
6
+ return remaining;
7
+ };
8
+ const failPendingCompositionMetadataValue = ({ field, pending, value, }) => {
9
+ if (pending[field] !== value) {
10
+ return pending;
11
+ }
12
+ return removePendingValue({ field, pending });
13
+ };
14
+ exports.failPendingCompositionMetadataValue = failPendingCompositionMetadataValue;
15
+ const acceptPendingCompositionMetadataValue = ({ currentConfig, field, pending, value, }) => {
16
+ if (pending[field] !== value) {
17
+ return pending;
18
+ }
19
+ if (currentConfig !== value.baseline) {
20
+ return removePendingValue({ field, pending });
21
+ }
22
+ return {
23
+ ...pending,
24
+ [field]: {
25
+ ...value,
26
+ status: 'awaiting-hmr',
27
+ },
28
+ };
29
+ };
30
+ exports.acceptPendingCompositionMetadataValue = acceptPendingCompositionMetadataValue;
31
+ const reconcilePendingCompositionMetadata = ({ currentConfig, pending, }) => {
32
+ let reconciled = pending;
33
+ for (const field of Object.keys(pending)) {
34
+ const value = pending[field];
35
+ if ((value === null || value === void 0 ? void 0 : value.status) === 'awaiting-hmr' && value.baseline !== currentConfig) {
36
+ reconciled = removePendingValue({ field, pending: reconciled });
37
+ }
38
+ }
39
+ return reconciled;
40
+ };
41
+ exports.reconcilePendingCompositionMetadata = reconcilePendingCompositionMetadata;
@@ -20,6 +20,8 @@ export declare const resolveLinkStyle: React.CSSProperties;
20
20
  export declare const selectedContainer: React.CSSProperties;
21
21
  export declare const centeredMessage: React.CSSProperties;
22
22
  export declare const detailsContainer: React.CSSProperties;
23
+ export declare const detailsWithInlineAction: React.CSSProperties;
24
+ export declare const detailsBeforeInlineAction: React.CSSProperties;
23
25
  export declare const guideDetailsContainer: React.CSSProperties;
24
26
  export declare const detailRow: React.CSSProperties;
25
27
  export declare const detailLabel: React.CSSProperties;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.keyframeEditorValue = exports.keyframeEditorLabel = exports.keyframeEditorRow = exports.detailValue = exports.detailLabel = exports.detailRow = exports.guideDetailsContainer = exports.detailsContainer = exports.centeredMessage = exports.selectedContainer = exports.resolveLinkStyle = exports.defaultPropsWarningMessages = exports.defaultPropsWarningContainer = exports.sectionHeaderEnd = exports.sectionHeaderStart = exports.sectionHeaderTitle = exports.sectionHeaderRow = exports.sequenceHeaderSubtitle = exports.sequenceHeaderTitle = exports.sequenceHeader = exports.sectionHeader = exports.sequenceHeaderDivider = exports.inspectorSectionDivider = exports.compositionSection = exports.visualControlsSection = exports.defaultPropsSection = exports.scrollableContainer = exports.container = void 0;
3
+ exports.keyframeEditorValue = exports.keyframeEditorLabel = exports.keyframeEditorRow = exports.detailValue = exports.detailLabel = exports.detailRow = exports.guideDetailsContainer = exports.detailsBeforeInlineAction = exports.detailsWithInlineAction = exports.detailsContainer = exports.centeredMessage = exports.selectedContainer = exports.resolveLinkStyle = exports.defaultPropsWarningMessages = exports.defaultPropsWarningContainer = exports.sectionHeaderEnd = exports.sectionHeaderStart = exports.sectionHeaderTitle = exports.sectionHeaderRow = exports.sequenceHeaderSubtitle = exports.sequenceHeaderTitle = exports.sequenceHeader = exports.sectionHeader = exports.sequenceHeaderDivider = exports.inspectorSectionDivider = exports.compositionSection = exports.visualControlsSection = exports.defaultPropsSection = exports.scrollableContainer = exports.container = void 0;
4
4
  const colors_1 = require("../../helpers/colors");
5
5
  const InspectorPanelLayout_1 = require("../InspectorPanelLayout");
6
6
  exports.container = {
@@ -155,6 +155,12 @@ exports.centeredMessage = {
155
155
  exports.detailsContainer = {
156
156
  padding: `0 ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px`,
157
157
  };
158
+ exports.detailsWithInlineAction = {
159
+ paddingBottom: InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING,
160
+ };
161
+ exports.detailsBeforeInlineAction = {
162
+ padding: `0 ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px`,
163
+ };
158
164
  exports.guideDetailsContainer = {
159
165
  padding: `0 ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px`,
160
166
  };
@@ -163,7 +169,6 @@ exports.detailRow = {
163
169
  display: 'flex',
164
170
  gap: 12,
165
171
  justifyContent: 'space-between',
166
- padding: '10px 0',
167
172
  };
168
173
  exports.detailLabel = {
169
174
  color: colors_1.LIGHT_TEXT,
@@ -269,12 +269,9 @@ const InspectorSequenceSection = ({ sequence, validatedLocation, nodePathInfo, k
269
269
  return (jsx_runtime_1.jsx(TimelineRowLayoutContext_1.TimelineRowLayoutContext.Provider, { value: TimelineRowLayoutContext_1.INSPECTOR_TIMELINE_ROW_LAYOUT, children: jsx_runtime_1.jsx(TimelineExpandedRow_1.TimelineExpandedRow, { node: node, depth: depth, nestedDepth: 0, rowDepthBase: 0, getIsExpanded: getIsExpanded, toggleTrack: toggleTrack, validatedLocation: validatedLocation, nodePath: nodePathInfo.sequenceSubscriptionKey, schema: schema, keyframeDisplayOffset: keyframeDisplayOffset, keyframeControlsMode: "inspector" }) }, JSON.stringify(node.nodePathInfo)));
270
270
  };
271
271
  if (controlRows.length === 0 && !showEffectsSection) {
272
- return (jsx_runtime_1.jsxs("div", { style: container, children: [
273
- jsx_runtime_1.jsx("div", { style: styles_1.sequenceHeaderDivider }), jsx_runtime_1.jsx("div", { style: emptyState, children: "No schema" })
274
- ] }));
272
+ return (jsx_runtime_1.jsx("div", { style: container, children: jsx_runtime_1.jsx("div", { style: emptyState, children: "No schema" }) }));
275
273
  }
276
- return (jsx_runtime_1.jsxs("div", { style: container, children: [
277
- jsx_runtime_1.jsx("div", { style: styles_1.sequenceHeaderDivider }), controlRows.length > 0 ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: controlSelectableItems, children: controlGroups.map((group, i) => (jsx_runtime_1.jsxs(react_1.default.Fragment, { children: [i === 0 ? null : jsx_runtime_1.jsx("div", { style: controlsEffectsDivider }), renderSectionHeader(group.label), group.id === 'source' && localAsset ? (jsx_runtime_1.jsx(CurrentAsset_1.AssetInfo, { assetName: localAsset.assetPath, contentSized: true, onAssetClick: jumpToAsset, readOnlyStudio: true })) : null, group.id === 'source' && remoteAsset && remoteSourceParts ? (jsx_runtime_1.jsxs("div", { style: remoteSourceLabel, title: remoteAsset.href, children: [
274
+ return (jsx_runtime_1.jsxs("div", { style: container, children: [controlRows.length > 0 ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: controlSelectableItems, children: controlGroups.map((group, i) => (jsx_runtime_1.jsxs(react_1.default.Fragment, { children: [i === 0 ? null : jsx_runtime_1.jsx("div", { style: controlsEffectsDivider }), renderSectionHeader(group.label), group.id === 'source' && localAsset ? (jsx_runtime_1.jsx(CurrentAsset_1.AssetInfo, { assetName: localAsset.assetPath, contentSized: true, onAssetClick: jumpToAsset, readOnlyStudio: true })) : null, group.id === 'source' && remoteAsset && remoteSourceParts ? (jsx_runtime_1.jsxs("div", { style: remoteSourceLabel, title: remoteAsset.href, children: [
278
275
  jsx_runtime_1.jsx("span", { style: remoteSourceLeading, children: remoteSourceParts.leading }), jsx_runtime_1.jsx("span", { style: remoteSourceTrailing, children: remoteSourceParts.trailing })
279
276
  ] })) : null, group.id === 'transforms' ? renderTransformControls() : null, group.id === 'source' ? null : group.rows.map(renderRow)] }, group.id))) })) : null, showEffectsSection ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [showControlsEffectsDivider ? (jsx_runtime_1.jsx("div", { style: controlsEffectsDivider })) : null, renderEffectsHeader(), effectRows.length > 0 ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: effectSelectableItems, children: effectRows.map(renderRow) })) : null] })) : null] }));
280
277
  };
@@ -41,6 +41,8 @@ const no_react_1 = require("remotion/no-react");
41
41
  const client_id_1 = require("../helpers/client-id");
42
42
  const colors_1 = require("../helpers/colors");
43
43
  const format_file_location_1 = require("../helpers/format-file-location");
44
+ const get_connected_compositions_1 = require("../helpers/get-connected-compositions");
45
+ const get_sequence_double_click_action_1 = require("../helpers/get-sequence-double-click-action");
44
46
  const open_in_editor_1 = require("../helpers/open-in-editor");
45
47
  const editor_snapping_1 = require("../state/editor-snapping");
46
48
  const modals_1 = require("../state/modals");
@@ -49,6 +51,7 @@ const ConfirmationDialog_1 = require("./ConfirmationDialog");
49
51
  const ContextMenu_1 = require("./ContextMenu");
50
52
  const effect_drag_and_drop_1 = require("./effect-drag-and-drop");
51
53
  const ForceSpecificCursor_1 = require("./ForceSpecificCursor");
54
+ const InitialCompositionLoader_1 = require("./InitialCompositionLoader");
52
55
  const NotificationCenter_1 = require("./Notifications/NotificationCenter");
53
56
  const selected_outline_drag_1 = require("./selected-outline-drag");
54
57
  const selected_outline_measurement_1 = require("./selected-outline-measurement");
@@ -981,6 +984,8 @@ const SelectedOutlineElement = ({ allDragTargets, allDragOutlines, allRotationDr
981
984
  const updateResolvedStackTrace = (0, react_1.useContext)(remotion_1.Internals.SequenceStackTracesUpdateContext);
982
985
  const confirm = (0, ConfirmationDialog_1.useConfirmationDialog)();
983
986
  const selectAsset = (0, use_select_asset_1.useSelectAsset)();
987
+ const selectComposition = (0, InitialCompositionLoader_1.useSelectComposition)();
988
+ const { compositions } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
984
989
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
985
990
  const resolveOriginalLocation = react_1.default.useCallback(async (resolveTarget) => {
986
991
  const stack = resolveTarget.sequence.getStack();
@@ -998,14 +1003,23 @@ const SelectedOutlineElement = ({ allDragTargets, allDragOutlines, allRotationDr
998
1003
  return originalLocation;
999
1004
  }, [updateResolvedStackTrace]);
1000
1005
  const onDoubleClickTarget = react_1.default.useCallback((doubleClickTarget, button) => {
1001
- const action = (0, selected_outline_measurement_1.getOutlineDoubleClickAction)({
1006
+ const connectedCompositions = (0, get_connected_compositions_1.getConnectedCompositions)({
1007
+ compositions,
1008
+ singleChildComponent: doubleClickTarget.sequence.singleChildComponent,
1009
+ });
1010
+ const action = (0, get_sequence_double_click_action_1.getSequenceDoubleClickAction)({
1002
1011
  button,
1003
1012
  canOpenInEditor: previewServerState.type === 'connected' &&
1004
1013
  Boolean(window.remotion_editorName),
1014
+ numberOfConnectedCompositions: connectedCompositions.length,
1005
1015
  });
1006
1016
  if (action === null) {
1007
1017
  return false;
1008
1018
  }
1019
+ if (action === 'open-connected-composition') {
1020
+ selectComposition(connectedCompositions[0], true);
1021
+ return true;
1022
+ }
1009
1023
  const openTargetInEditor = async () => {
1010
1024
  const originalLocation = await resolveOriginalLocation(doubleClickTarget);
1011
1025
  if (originalLocation === null) {
@@ -1017,7 +1031,12 @@ const SelectedOutlineElement = ({ allDragTargets, allDragOutlines, allRotationDr
1017
1031
  (0, NotificationCenter_1.showNotification)(err.message, 2000);
1018
1032
  });
1019
1033
  return true;
1020
- }, [previewServerState.type, resolveOriginalLocation]);
1034
+ }, [
1035
+ compositions,
1036
+ previewServerState.type,
1037
+ resolveOriginalLocation,
1038
+ selectComposition,
1039
+ ]);
1021
1040
  const onContextMenuOpen = react_1.default.useCallback(async () => {
1022
1041
  if (target === undefined || previewServerState.type !== 'connected') {
1023
1042
  return false;
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { type SelectedOutline } from './selected-outline-geometry';
3
3
  import { type SelectedOutlineTarget } from './selected-outline-types';
4
4
  export { applySelectedOutlineDragAxisLock, applySelectedOutlineTransformOriginAxisLock, compensateTranslateForTransformOrigin, getSelectedOutlineActiveSchema, getSelectedOutlineDragChanges, getSelectedOutlineDragValues, getSelectedOutlineKeyboardNudgeDelta, getSelectedOutlineKeyboardNudgeDeltas, getSelectedOutlineRotationDragChanges, getSelectedOutlineRotationDragStates, getSelectedOutlineRotationDragValues, getSelectedOutlineScaleDragChanges, getSelectedOutlineScaleDragStates, getSelectedOutlineScaleDragValues, getSelectedOutlineScaleEdgeInfo, getSelectedOutlineTransformOriginLockedAxis, isSelectedOutlineDragPastThreshold, selectedOutlineTransformOriginSnapThresholdPx, selectedOutlineUvSnapThresholdPx, snapSelectedOutlineRotationDeltaDegrees, snapSelectedOutlineTransformOriginUv, snapSelectedOutlineUv, } from './selected-outline-drag';
5
- export { getOutlineDoubleClickAction, getOutlineSelectionInteraction, getSelectedEffectFieldsBySequenceKey, getSelectedOutlineRotationCornerInfo, getSelectedOutlineRotationDeltaDegrees, getSelectedOutlineRotationPivot, getSelectedSequenceKeys, getSequencesWithSelectableOutlines, getTransformedSvgViewportPoints, } from './selected-outline-measurement';
5
+ export { getOutlineSelectionInteraction, getSelectedEffectFieldsBySequenceKey, getSelectedOutlineRotationCornerInfo, getSelectedOutlineRotationDeltaDegrees, getSelectedOutlineRotationPivot, getSelectedSequenceKeys, getSequencesWithSelectableOutlines, getTransformedSvgViewportPoints, } from './selected-outline-measurement';
6
6
  export { selectedOutlineDragThresholdPx } from './selected-outline-types';
7
7
  export type { SelectedOutlineDragState, SelectedOutlineRotationDragState, SelectedOutlineScaleDragState, } from './selected-outline-types';
8
8
  type OutlineSequenceParent = {
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.SelectedOutlineOverlay = exports.orderOutlinesForRendering = exports.selectedOutlineDragThresholdPx = exports.getTransformedSvgViewportPoints = exports.getSequencesWithSelectableOutlines = exports.getSelectedSequenceKeys = exports.getSelectedOutlineRotationPivot = exports.getSelectedOutlineRotationDeltaDegrees = exports.getSelectedOutlineRotationCornerInfo = exports.getSelectedEffectFieldsBySequenceKey = exports.getOutlineSelectionInteraction = exports.getOutlineDoubleClickAction = exports.snapSelectedOutlineUv = exports.snapSelectedOutlineTransformOriginUv = exports.snapSelectedOutlineRotationDeltaDegrees = exports.selectedOutlineUvSnapThresholdPx = exports.selectedOutlineTransformOriginSnapThresholdPx = exports.isSelectedOutlineDragPastThreshold = exports.getSelectedOutlineTransformOriginLockedAxis = exports.getSelectedOutlineScaleEdgeInfo = exports.getSelectedOutlineScaleDragValues = exports.getSelectedOutlineScaleDragStates = exports.getSelectedOutlineScaleDragChanges = exports.getSelectedOutlineRotationDragValues = exports.getSelectedOutlineRotationDragStates = exports.getSelectedOutlineRotationDragChanges = exports.getSelectedOutlineKeyboardNudgeDeltas = exports.getSelectedOutlineKeyboardNudgeDelta = exports.getSelectedOutlineDragValues = exports.getSelectedOutlineDragChanges = exports.getSelectedOutlineActiveSchema = exports.compensateTranslateForTransformOrigin = exports.applySelectedOutlineTransformOriginAxisLock = exports.applySelectedOutlineDragAxisLock = void 0;
36
+ exports.SelectedOutlineOverlay = exports.orderOutlinesForRendering = exports.selectedOutlineDragThresholdPx = exports.getTransformedSvgViewportPoints = exports.getSequencesWithSelectableOutlines = exports.getSelectedSequenceKeys = exports.getSelectedOutlineRotationPivot = exports.getSelectedOutlineRotationDeltaDegrees = exports.getSelectedOutlineRotationCornerInfo = exports.getSelectedEffectFieldsBySequenceKey = exports.getOutlineSelectionInteraction = exports.snapSelectedOutlineUv = exports.snapSelectedOutlineTransformOriginUv = exports.snapSelectedOutlineRotationDeltaDegrees = exports.selectedOutlineUvSnapThresholdPx = exports.selectedOutlineTransformOriginSnapThresholdPx = exports.isSelectedOutlineDragPastThreshold = exports.getSelectedOutlineTransformOriginLockedAxis = exports.getSelectedOutlineScaleEdgeInfo = exports.getSelectedOutlineScaleDragValues = exports.getSelectedOutlineScaleDragStates = exports.getSelectedOutlineScaleDragChanges = exports.getSelectedOutlineRotationDragValues = exports.getSelectedOutlineRotationDragStates = exports.getSelectedOutlineRotationDragChanges = exports.getSelectedOutlineKeyboardNudgeDeltas = exports.getSelectedOutlineKeyboardNudgeDelta = exports.getSelectedOutlineDragValues = exports.getSelectedOutlineDragChanges = exports.getSelectedOutlineActiveSchema = exports.compensateTranslateForTransformOrigin = exports.applySelectedOutlineTransformOriginAxisLock = exports.applySelectedOutlineDragAxisLock = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const player_1 = require("@remotion/player");
39
39
  const react_1 = __importStar(require("react"));
@@ -82,7 +82,6 @@ Object.defineProperty(exports, "snapSelectedOutlineRotationDeltaDegrees", { enum
82
82
  Object.defineProperty(exports, "snapSelectedOutlineTransformOriginUv", { enumerable: true, get: function () { return selected_outline_drag_2.snapSelectedOutlineTransformOriginUv; } });
83
83
  Object.defineProperty(exports, "snapSelectedOutlineUv", { enumerable: true, get: function () { return selected_outline_drag_2.snapSelectedOutlineUv; } });
84
84
  const selected_outline_measurement_2 = require("./selected-outline-measurement");
85
- Object.defineProperty(exports, "getOutlineDoubleClickAction", { enumerable: true, get: function () { return selected_outline_measurement_2.getOutlineDoubleClickAction; } });
86
85
  Object.defineProperty(exports, "getOutlineSelectionInteraction", { enumerable: true, get: function () { return selected_outline_measurement_2.getOutlineSelectionInteraction; } });
87
86
  Object.defineProperty(exports, "getSelectedEffectFieldsBySequenceKey", { enumerable: true, get: function () { return selected_outline_measurement_2.getSelectedEffectFieldsBySequenceKey; } });
88
87
  Object.defineProperty(exports, "getSelectedOutlineRotationCornerInfo", { enumerable: true, get: function () { return selected_outline_measurement_2.getSelectedOutlineRotationCornerInfo; } });
@@ -363,7 +362,7 @@ exports.orderOutlinesForRendering = orderOutlinesForRendering;
363
362
  const SelectedOutlineOverlay = ({ compositionHeight, compositionWidth, scale, translationX, translationY, }) => {
364
363
  const { selectedItems, selectItem } = (0, TimelineSelection_1.useTimelineSelection)();
365
364
  const { sequences } = (0, react_1.useContext)(remotion_1.Internals.SequenceManager);
366
- const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
365
+ const { canvasContent, compositions } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
367
366
  const { propStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
368
367
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
369
368
  const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
@@ -411,6 +410,7 @@ const SelectedOutlineOverlay = ({ compositionHeight, compositionWidth, scale, tr
411
410
  return (0, selected_outline_measurement_1.getSequencesWithSelectableOutlines)({
412
411
  sequences,
413
412
  overrideIdsToNodePaths: overrideIdToNodePathMappings,
413
+ compositions,
414
414
  }).map(({ key, keyframeDisplayOffset, nodePathInfo, sequence }) => {
415
415
  var _a, _b, _c, _d, _e, _f;
416
416
  if (sequence.refForOutline === null) {
@@ -629,6 +629,7 @@ const SelectedOutlineOverlay = ({ compositionHeight, compositionWidth, scale, tr
629
629
  previewServerState,
630
630
  selectedItems,
631
631
  sequences,
632
+ compositions,
632
633
  timelinePosition,
633
634
  ]);
634
635
  (0, react_1.useEffect)(() => {
@@ -204,6 +204,7 @@ const TimelineContextMenuArea = ({ children }) => {
204
204
  const TimelineInner = () => {
205
205
  var _a;
206
206
  const { sequences } = (0, react_1.useContext)(remotion_1.Internals.SequenceManager);
207
+ const { compositions } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
207
208
  const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
208
209
  const isStill = (0, is_current_selected_still_1.useIsStill)();
209
210
  const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
@@ -218,8 +219,14 @@ const TimelineInner = () => {
218
219
  return (0, calculate_timeline_1.calculateTimeline)({
219
220
  sequences,
220
221
  overrideIdsToNodePaths: overrideIdToNodePathMappings,
222
+ compositions,
221
223
  });
222
- }, [sequences, videoConfigIsNull, overrideIdToNodePathMappings]);
224
+ }, [
225
+ sequences,
226
+ videoConfigIsNull,
227
+ overrideIdToNodePathMappings,
228
+ compositions,
229
+ ]);
223
230
  const durationInFrames = (_a = videoConfig === null || videoConfig === void 0 ? void 0 : videoConfig.durationInFrames) !== null && _a !== void 0 ? _a : 0;
224
231
  const filtered = (0, react_1.useMemo)(() => {
225
232
  return timeline.filter((t) => (0, should_show_track_in_timeline_1.shouldShowTrackInTimeline)(t, durationInFrames));
@@ -9,9 +9,13 @@ const use_keybinding_1 = require("../../helpers/use-keybinding");
9
9
  const call_api_1 = require("../call-api");
10
10
  const ConfirmationDialog_1 = require("../ConfirmationDialog");
11
11
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
12
+ const call_add_keyframe_1 = require("./call-add-keyframe");
13
+ const call_delete_keyframe_1 = require("./call-delete-keyframe");
14
+ const call_update_keyframe_settings_1 = require("./call-update-keyframe-settings");
12
15
  const delete_selected_timeline_item_1 = require("./delete-selected-timeline-item");
13
16
  const effects_clipboard_1 = require("./effects-clipboard");
14
17
  const find_track_for_node_path_info_1 = require("./find-track-for-node-path-info");
18
+ const keyframe_clipboard_1 = require("./keyframe-clipboard");
15
19
  const save_effect_prop_1 = require("./save-effect-prop");
16
20
  const TimelineSelection_1 = require("./TimelineSelection");
17
21
  const update_selected_easing_1 = require("./update-selected-easing");
@@ -352,6 +356,9 @@ const getPasteEffectPropTarget = ({ selectedItems, payload, propStatuses, sequen
352
356
  exports.getPasteEffectPropTarget = getPasteEffectPropTarget;
353
357
  const TimelineClipboardKeybindings = () => {
354
358
  const keybindings = (0, use_keybinding_1.useKeybinding)();
359
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
360
+ const timelinePositionRef = (0, react_1.useRef)(timelinePosition);
361
+ timelinePositionRef.current = timelinePosition;
355
362
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
356
363
  const { canSelect } = (0, TimelineSelection_1.useTimelineSelection)();
357
364
  const currentSelection = (0, TimelineSelection_1.useCurrentTimelineSelectionStateAsRef)();
@@ -376,6 +383,30 @@ const TimelineClipboardKeybindings = () => {
376
383
  if (selectedItems.length === 0) {
377
384
  return;
378
385
  }
386
+ const keyframeSelections = selectedItems.filter((selection) => selection.type === 'keyframe');
387
+ if (keyframeSelections.length > 0) {
388
+ e.preventDefault();
389
+ if (selectedItems.some((selection) => selection.type !== 'keyframe' && selection.type !== 'easing')) {
390
+ (0, NotificationCenter_1.showNotification)('Select only keyframes and easings to copy', 3000);
391
+ return;
392
+ }
393
+ const payload = (0, keyframe_clipboard_1.getKeyframeClipboardDataFromSelections)({
394
+ selections: selectedItems,
395
+ sequences,
396
+ overrideIdsToNodePaths: overrideIdToNodePathMappings,
397
+ propStatuses,
398
+ });
399
+ if (payload === null) {
400
+ (0, NotificationCenter_1.showNotification)('Select a continuous keyframe range from one property to copy', 3000);
401
+ return;
402
+ }
403
+ navigator.clipboard
404
+ .writeText(makeClipboardText(payload))
405
+ .catch((err) => {
406
+ (0, NotificationCenter_1.showNotification)(`Could not copy keyframe: ${err.message}`, 2000);
407
+ });
408
+ return;
409
+ }
379
410
  const easingSelections = (0, update_selected_easing_1.getEasingSelections)(selectedItems);
380
411
  if (easingSelections.length > 0) {
381
412
  e.preventDefault();
@@ -543,6 +574,106 @@ const TimelineClipboardKeybindings = () => {
543
574
  .then(() => {
544
575
  const propStatuses = propStatusesRef.current;
545
576
  const sequences = sequencesRef.current;
577
+ const keyframeResult = (0, studio_shared_1.parseKeyframeClipboardDataResult)(text);
578
+ if (keyframeResult.status !== 'invalid') {
579
+ if (keyframeResult.status === 'unsupported-version') {
580
+ (0, NotificationCenter_1.showNotification)('Cannot paste keyframe copied from a different Remotion Studio version', 4000);
581
+ return;
582
+ }
583
+ const keyframeTarget = (0, keyframe_clipboard_1.getPasteKeyframeTarget)({
584
+ selectedItems,
585
+ payload: keyframeResult.data,
586
+ timelinePosition: timelinePositionRef.current,
587
+ sequences,
588
+ overrideIdsToNodePaths: overrideIdToNodePathMappings,
589
+ propStatuses,
590
+ });
591
+ if (keyframeTarget.type !== 'valid') {
592
+ switch (keyframeTarget.type) {
593
+ case 'none':
594
+ (0, NotificationCenter_1.showNotification)('Select a property or keyframe to paste onto', 3000);
595
+ return;
596
+ case 'multiple':
597
+ (0, NotificationCenter_1.showNotification)('Select one property or keyframe to paste onto', 3000);
598
+ return;
599
+ case 'uncopyable':
600
+ (0, NotificationCenter_1.showNotification)('Cannot paste onto a property that cannot be updated', 3000);
601
+ return;
602
+ case 'incompatible':
603
+ (0, NotificationCenter_1.showNotification)('The copied keyframe is not compatible with this property', 3000);
604
+ return;
605
+ default:
606
+ throw new Error(`Unexpected paste target: ${keyframeTarget}`);
607
+ }
608
+ }
609
+ const changes = keyframeTarget.keyframes.map((keyframe) => ({
610
+ fileName: keyframeTarget.fileName,
611
+ nodePath: keyframeTarget.nodePath,
612
+ fieldKey: keyframeTarget.fieldKey,
613
+ sourceFrame: keyframe.sourceFrame,
614
+ value: keyframe.value,
615
+ schema: keyframeTarget.schema,
616
+ }));
617
+ const { effectIndex } = keyframeTarget;
618
+ const deletions = keyframeTarget.keyframesToDelete.map((sourceFrame) => ({
619
+ fileName: keyframeTarget.fileName,
620
+ nodePath: keyframeTarget.nodePath,
621
+ fieldKey: keyframeTarget.fieldKey,
622
+ sourceFrame,
623
+ schema: keyframeTarget.schema,
624
+ }));
625
+ return (0, call_delete_keyframe_1.callDeleteKeyframes)({
626
+ sequenceKeyframes: effectIndex === null ? deletions : [],
627
+ effectKeyframes: effectIndex === null
628
+ ? []
629
+ : deletions.map((deletion) => ({
630
+ ...deletion,
631
+ effectIndex,
632
+ })),
633
+ setPropStatuses,
634
+ clientId,
635
+ })
636
+ .then(() => (0, call_add_keyframe_1.callAddKeyframes)({
637
+ sequenceKeyframes: effectIndex === null ? changes : [],
638
+ effectKeyframes: effectIndex === null
639
+ ? []
640
+ : changes.map((change) => ({ ...change, effectIndex })),
641
+ setPropStatuses,
642
+ clientId,
643
+ }))
644
+ .then(async () => {
645
+ for (const [index, easing] of keyframeTarget.easing.entries()) {
646
+ const settings = {
647
+ type: 'easing',
648
+ segmentIndex: keyframeTarget.firstEasingSegmentIndex + index,
649
+ easing,
650
+ };
651
+ if (effectIndex === null) {
652
+ await (0, call_update_keyframe_settings_1.callUpdateSequenceKeyframeSettings)({
653
+ fileName: keyframeTarget.fileName,
654
+ nodePath: keyframeTarget.nodePath,
655
+ fieldKey: keyframeTarget.fieldKey,
656
+ settings,
657
+ schema: keyframeTarget.schema,
658
+ setPropStatuses,
659
+ clientId,
660
+ });
661
+ }
662
+ else {
663
+ await (0, call_update_keyframe_settings_1.callUpdateEffectKeyframeSettings)({
664
+ fileName: keyframeTarget.fileName,
665
+ nodePath: keyframeTarget.nodePath,
666
+ effectIndex,
667
+ fieldKey: keyframeTarget.fieldKey,
668
+ settings,
669
+ schema: keyframeTarget.schema,
670
+ setPropStatuses,
671
+ clientId,
672
+ });
673
+ }
674
+ }
675
+ });
676
+ }
546
677
  const easingResult = (0, studio_shared_1.parseEasingClipboardDataResult)(text);
547
678
  if (easingResult.status !== 'invalid') {
548
679
  e.preventDefault();
@@ -685,7 +816,7 @@ const TimelineClipboardKeybindings = () => {
685
816
  });
686
817
  })
687
818
  .catch((err) => {
688
- (0, NotificationCenter_1.showNotification)(`Could not paste effects: ${err.message}`, 3000);
819
+ (0, NotificationCenter_1.showNotification)(`Could not paste: ${err.message}`, 3000);
689
820
  });
690
821
  };
691
822
  // Reading ClipboardEvent data avoids the permission prompt caused by
@@ -708,6 +839,7 @@ const TimelineClipboardKeybindings = () => {
708
839
  previewServerState,
709
840
  sequencesRef,
710
841
  setPropStatuses,
842
+ timelinePositionRef,
711
843
  ]);
712
844
  return null;
713
845
  };
@@ -12,7 +12,8 @@ const container = {
12
12
  const TimelineList = ({ timeline }) => {
13
13
  return (jsx_runtime_1.jsxs("div", { style: container, children: [
14
14
  jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePadding, {}), timeline.map((track, trackIndex) => {
15
- return (jsx_runtime_1.jsx("div", { children: jsx_runtime_1.jsx(TimelineSequenceItem_1.TimelineSequenceItem, { trackIndex: trackIndex, nestedDepth: track.depth, sequence: track.sequence, nodePathInfo: track.nodePathInfo, keyframeDisplayOffset: track.keyframeDisplayOffset, sequenceFrameOffset: track.sequenceFrameOffset }, track.sequence.id) }, track.sequence.id));
15
+ var _a;
16
+ return (jsx_runtime_1.jsx("div", { children: jsx_runtime_1.jsx(TimelineSequenceItem_1.TimelineSequenceItem, { trackIndex: trackIndex, connectedCompositions: (_a = track.connectedCompositions) !== null && _a !== void 0 ? _a : [], nestedDepth: track.depth, sequence: track.sequence, nodePathInfo: track.nodePathInfo, keyframeDisplayOffset: track.keyframeDisplayOffset, sequenceFrameOffset: track.sequenceFrameOffset }, track.sequence.id) }, track.sequence.id));
16
17
  })] }));
17
18
  };
18
19
  exports.TimelineList = TimelineList;
@@ -18,9 +18,7 @@ const inlineWrapper = {
18
18
  fontSize: 12,
19
19
  };
20
20
  const isTimelinePrimitiveFieldInfo = (field) => {
21
- return (field.typeName !== 'array' &&
22
- field.typeName !== 'hidden' &&
23
- field.fieldSchema.type !== 'array');
21
+ return field.typeName !== 'array' && field.fieldSchema.type !== 'array';
24
22
  };
25
23
  exports.isTimelinePrimitiveFieldInfo = isTimelinePrimitiveFieldInfo;
26
24
  const TimelinePrimitiveFieldValue = ({ field, onSave, onDragValueChange, onDragEnd, propStatus, effectiveValue, scaleLockNodePath, }) => {
@@ -221,10 +221,26 @@ const isTimelineSelectionCompatibleWithMarqueeKind = (item, kind) => {
221
221
  return item.type === 'keyframe' || item.type === 'easing';
222
222
  };
223
223
  const getTimelineMarqueeSelection = ({ candidates, lockedSelectionKind, marqueeRect, }) => {
224
- const intersectingCandidates = candidates.filter((candidate) => {
224
+ const geometricallyIntersectingCandidates = candidates.filter((candidate) => {
225
225
  return (getTimelineMarqueeSelectionKind(candidate.item) !== null &&
226
226
  (0, exports.timelineMarqueeRectsIntersect)(candidate.rect, marqueeRect));
227
227
  });
228
+ const intersectingKeyframes = new Set(geometricallyIntersectingCandidates.flatMap((candidate) => {
229
+ if (candidate.item.type !== 'keyframe') {
230
+ return [];
231
+ }
232
+ return [
233
+ `${(0, timeline_node_path_key_1.timelineNodePathInfoToKey)(candidate.item.nodePathInfo)}.${candidate.item.frame}`,
234
+ ];
235
+ }));
236
+ const intersectingCandidates = geometricallyIntersectingCandidates.filter((candidate) => {
237
+ if (candidate.item.type !== 'easing') {
238
+ return true;
239
+ }
240
+ const fieldKey = (0, timeline_node_path_key_1.timelineNodePathInfoToKey)(candidate.item.nodePathInfo);
241
+ return (intersectingKeyframes.has(`${fieldKey}.${candidate.item.fromFrame}`) &&
242
+ intersectingKeyframes.has(`${fieldKey}.${candidate.item.toFrame}`));
243
+ });
228
244
  const getFirstIntersectingSelectionKind = () => intersectingCandidates.length === 0
229
245
  ? null
230
246
  : getTimelineMarqueeSelectionKind(intersectingCandidates[0].item);
@@ -363,8 +379,6 @@ const getSelectableTimelineSequenceSelections = (tracks) => {
363
379
  });
364
380
  };
365
381
  exports.getSelectableTimelineSequenceSelections = getSelectableTimelineSequenceSelections;
366
- const canEditEasingForInterpolationFunction = (interpolationFunction) => interpolationFunction === 'interpolate' ||
367
- interpolationFunction === 'interpolateColors';
368
382
  const getTimelineTreeNodeCanEditEasing = ({ node, nodePathInfo, propStatuses, }) => {
369
383
  var _a;
370
384
  if (node.kind !== 'field' || node.field === null) {
@@ -373,7 +387,7 @@ const getTimelineTreeNodeCanEditEasing = ({ node, nodePathInfo, propStatuses, })
373
387
  if (node.field.kind === 'sequence-field') {
374
388
  const sequencePropStatus = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePathInfo.sequenceSubscriptionKey)) === null || _a === void 0 ? void 0 : _a[node.field.key];
375
389
  return ((sequencePropStatus === null || sequencePropStatus === void 0 ? void 0 : sequencePropStatus.status) === 'keyframed' &&
376
- canEditEasingForInterpolationFunction(sequencePropStatus.interpolationFunction));
390
+ (0, studio_shared_1.canEditEasingForInterpolationFunction)(sequencePropStatus.interpolationFunction));
377
391
  }
378
392
  const effectStatus = remotion_1.Internals.getEffectPropStatusesCtx({
379
393
  propStatuses,
@@ -384,7 +398,7 @@ const getTimelineTreeNodeCanEditEasing = ({ node, nodePathInfo, propStatuses, })
384
398
  ? effectStatus.props[node.field.key]
385
399
  : null;
386
400
  return ((effectPropStatus === null || effectPropStatus === void 0 ? void 0 : effectPropStatus.status) === 'keyframed' &&
387
- canEditEasingForInterpolationFunction(effectPropStatus.interpolationFunction));
401
+ (0, studio_shared_1.canEditEasingForInterpolationFunction)(effectPropStatus.interpolationFunction));
388
402
  };
389
403
  const getSelectableTimelineItems = ({ getDragOverrides, getEffectDragOverrides, getIsExpanded, propStatuses, selectedItems, timeline, timelinePosition, }) => {
390
404
  const selectedRowKeys = (0, timeline_expanded_filter_1.getSelectedTimelineExpandedRowKeys)(selectedItems);
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
- import type { TSequence } from 'remotion';
2
+ import type { _InternalTypes, TSequence } from 'remotion';
3
3
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
4
4
  export declare const TimelineSequenceItem: React.FC<{
5
5
  readonly sequence: TSequence;
6
+ readonly connectedCompositions: readonly _InternalTypes['AnyComposition'][];
6
7
  readonly nestedDepth: number;
7
8
  readonly nodePathInfo: SequenceNodePathInfo | null;
8
9
  readonly keyframeDisplayOffset: number;