@remotion/studio 4.0.508 → 4.0.509

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 (86) hide show
  1. package/dist/Studio.d.ts +5 -0
  2. package/dist/Studio.js +2 -2
  3. package/dist/components/Canvas.js +35 -5
  4. package/dist/components/ColorPicker/AlphaSlider.js +2 -2
  5. package/dist/components/ColorPicker/HueSlider.js +2 -2
  6. package/dist/components/ColorPicker/SaturationValueArea.js +2 -2
  7. package/dist/components/EditorGuides/Guide.js +2 -2
  8. package/dist/components/EditorRuler/index.js +2 -2
  9. package/dist/components/ExplorerPanel.js +19 -1
  10. package/dist/components/InspectorOpenInEditor.js +8 -5
  11. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +3 -3
  12. package/dist/components/Menu/MenuItem.js +2 -2
  13. package/dist/components/ModalContainer.js +1 -1
  14. package/dist/components/Modals.js +2 -9
  15. package/dist/components/NewComposition/InputDragger.js +2 -2
  16. package/dist/components/NewComposition/NewComposition.d.ts +2 -0
  17. package/dist/components/NewComposition/NewComposition.js +38 -6
  18. package/dist/components/NewComposition/get-new-composition-defaults.d.ts +1 -1
  19. package/dist/components/NewComposition/get-new-composition-defaults.js +9 -1
  20. package/dist/components/SelectedOutlineCanvasRotation.js +6 -4
  21. package/dist/components/SelectedOutlineCropControls.js +2 -2
  22. package/dist/components/SelectedOutlineElement.js +6 -2
  23. package/dist/components/SelectedOutlinePolygon.js +2 -2
  24. package/dist/components/SelectedOutlineRotationCornerHandle.d.ts +5 -0
  25. package/dist/components/SelectedOutlineRotationCornerHandle.js +4 -4
  26. package/dist/components/SelectedOutlineScaleEdgeLine.d.ts +1 -0
  27. package/dist/components/SelectedOutlineScaleEdgeLine.js +4 -4
  28. package/dist/components/SelectedOutlineTransformOriginHandle.js +2 -2
  29. package/dist/components/SelectedOutlineUvControls.js +8 -8
  30. package/dist/components/Splitter/SplitterHandle.js +2 -2
  31. package/dist/components/Tabs/index.d.ts +2 -0
  32. package/dist/components/Tabs/index.js +2 -2
  33. package/dist/components/Timeline/EasingEditorModal.js +2 -2
  34. package/dist/components/Timeline/SubscribeToNodePaths.js +1 -1
  35. package/dist/components/Timeline/Timeline.js +55 -1
  36. package/dist/components/Timeline/TimelineClipboardKeybindings.js +99 -35
  37. package/dist/components/Timeline/TimelineDragHandler.js +2 -2
  38. package/dist/components/Timeline/TimelineEffectPropItem.js +7 -0
  39. package/dist/components/Timeline/TimelineInOutDragHandler.js +2 -2
  40. package/dist/components/Timeline/TimelineLayerEye.js +2 -2
  41. package/dist/components/Timeline/TimelineSelection.js +2 -2
  42. package/dist/components/Timeline/TimelineSequenceItem.js +1 -24
  43. package/dist/components/Timeline/TimelineSequencePropItem.js +7 -1
  44. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +6 -6
  45. package/dist/components/Timeline/get-sequence-context-menu-items.js +1 -0
  46. package/dist/components/Timeline/keyframe-clipboard.d.ts +5 -1
  47. package/dist/components/Timeline/keyframe-clipboard.js +3 -2
  48. package/dist/components/Timeline/save-sequence-prop.js +16 -7
  49. package/dist/components/Timeline/sequence-prop-clipboard.d.ts +31 -0
  50. package/dist/components/Timeline/sequence-prop-clipboard.js +142 -0
  51. package/dist/components/Timeline/update-selected-easing.js +8 -0
  52. package/dist/components/Timeline/use-open-sequence-in-apps.js +3 -1
  53. package/dist/components/Timeline/use-resolved-stack-react-to-change.d.ts +1 -1
  54. package/dist/components/Timeline/use-resolved-stack-react-to-change.js +24 -3
  55. package/dist/components/Timeline/use-timeline-keyframe-drag.js +4 -4
  56. package/dist/components/folder-menu-items.js +1 -0
  57. package/dist/components/get-open-in-menu-items.d.ts +3 -1
  58. package/dist/components/get-open-in-menu-items.js +73 -49
  59. package/dist/components/import-assets.js +7 -0
  60. package/dist/components/root-composition-menu-items.js +1 -0
  61. package/dist/components/selected-outline-control-layout.d.ts +14 -0
  62. package/dist/components/selected-outline-control-layout.js +94 -0
  63. package/dist/components/use-default-editor-info.js +28 -3
  64. package/dist/esm/{chunk-zpn4m49r.js → chunk-jdn6nkbk.js} +5181 -4560
  65. package/dist/esm/{chunk-fgedsvhb.js → chunk-r46yxrjr.js} +1 -2
  66. package/dist/esm/internals.mjs +5180 -4559
  67. package/dist/esm/previewEntry.mjs +5072 -4451
  68. package/dist/esm/renderEntry.mjs +4 -2
  69. package/dist/helpers/get-canvas-capture-import.d.ts +7 -0
  70. package/dist/helpers/get-canvas-capture-import.js +43 -0
  71. package/dist/helpers/get-git-menu-item.d.ts +1 -1
  72. package/dist/helpers/get-git-menu-item.js +33 -3
  73. package/dist/helpers/inserted-element-selection.d.ts +12 -0
  74. package/dist/helpers/inserted-element-selection.js +29 -0
  75. package/dist/helpers/pointer-session.d.ts +6 -2
  76. package/dist/helpers/pointer-session.js +29 -12
  77. package/dist/helpers/use-create-composition.d.ts +15 -2
  78. package/dist/helpers/use-create-composition.js +11 -17
  79. package/dist/helpers/use-menu-structure.js +1 -0
  80. package/dist/icons/github.d.ts +4 -0
  81. package/dist/icons/github.js +11 -0
  82. package/dist/renderEntry.js +2 -2
  83. package/dist/state/modals.d.ts +9 -1
  84. package/dist/state/z-index.d.ts +0 -1
  85. package/dist/state/z-index.js +27 -33
  86. package/package.json +12 -12
@@ -140,21 +140,6 @@ const sequenceReorderAfterLine = {
140
140
  ...sequenceReorderLineBase,
141
141
  top: -1,
142
142
  };
143
- const sequenceReorderRejectionStyle = {
144
- backgroundColor: colors_1.BLACK_ALPHA_85,
145
- border: colors_1.BORDER_WHITE_ALPHA_20,
146
- borderRadius: 4,
147
- color: colors_1.WHITE,
148
- fontSize: 11,
149
- lineHeight: 1.2,
150
- maxWidth: 260,
151
- padding: '3px 6px',
152
- pointerEvents: 'none',
153
- position: 'absolute',
154
- right: 6,
155
- top: 2,
156
- zIndex: 2,
157
- };
158
143
  const hasSequenceReorderDragType = (dataTransfer) => {
159
144
  return Array.from(dataTransfer.types).includes(SEQUENCE_REORDER_MIME_TYPE);
160
145
  };
@@ -208,7 +193,6 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
208
193
  const [effectDropHovered, setEffectDropHovered] = (0, react_1.useState)(false);
209
194
  const [isRenaming, setIsRenaming] = (0, react_1.useState)(false);
210
195
  const [sequenceDropIndicator, setSequenceDropIndicator] = (0, react_1.useState)(null);
211
- const [sequenceDropRejection, setSequenceDropRejection] = (0, react_1.useState)(null);
212
196
  const { canOpenInEditor, canConfigureApps, codingAgentInfo, editorInfo, openInCodingAgent, openInEditor, originalLocation, } = (0, use_open_sequence_in_apps_1.useOpenSequenceInApps)(sequence);
213
197
  const validatedLocation = (0, react_1.useMemo)(() => {
214
198
  var _a;
@@ -401,7 +385,6 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
401
385
  const onSequenceDragEnd = (0, react_1.useCallback)(() => {
402
386
  currentSequenceDrag = null;
403
387
  setSequenceDropIndicator(null);
404
- setSequenceDropRejection(null);
405
388
  }, []);
406
389
  const onSequenceDragOver = (0, react_1.useCallback)((e) => {
407
390
  if (!hasSequenceReorderDragType(e.dataTransfer)) {
@@ -410,12 +393,10 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
410
393
  const dropTarget = getSequenceDropTarget(e);
411
394
  if (!dropTarget) {
412
395
  setSequenceDropIndicator(null);
413
- setSequenceDropRejection(null);
414
396
  return;
415
397
  }
416
398
  if (dropTarget.type === 'invalid') {
417
399
  setSequenceDropIndicator(null);
418
- setSequenceDropRejection(dropTarget.reason);
419
400
  e.dataTransfer.dropEffect = 'none';
420
401
  return;
421
402
  }
@@ -423,14 +404,12 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
423
404
  e.stopPropagation();
424
405
  e.dataTransfer.dropEffect = 'move';
425
406
  setSequenceDropIndicator(dropTarget.position);
426
- setSequenceDropRejection(null);
427
407
  }, [getSequenceDropTarget]);
428
408
  const onSequenceDragLeave = (0, react_1.useCallback)((e) => {
429
409
  if (e.currentTarget.contains(e.relatedTarget)) {
430
410
  return;
431
411
  }
432
412
  setSequenceDropIndicator(null);
433
- setSequenceDropRejection(null);
434
413
  }, []);
435
414
  const onSequenceDrop = (0, react_1.useCallback)(async (e) => {
436
415
  if (!canReorderSequence ||
@@ -442,13 +421,11 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
442
421
  const dropTarget = getSequenceDropTarget(e);
443
422
  if (!dropTarget || dropTarget.type === 'invalid') {
444
423
  setSequenceDropIndicator(null);
445
- setSequenceDropRejection((dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.type) === 'invalid' ? dropTarget.reason : null);
446
424
  return;
447
425
  }
448
426
  e.preventDefault();
449
427
  e.stopPropagation();
450
428
  setSequenceDropIndicator(null);
451
- setSequenceDropRejection(null);
452
429
  currentSequenceDrag = null;
453
430
  try {
454
431
  const result = await (0, call_api_1.callApi)('/api/reorder-sequence', {
@@ -937,7 +914,7 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
937
914
  " ",
938
915
  jsx_runtime_1.jsx(TimelineMediaInfo_1.TimelineMediaInfo, { src: mediaSrc })
939
916
  ] })) : null] }) }));
940
- const draggableTrackRow = canHandleSequenceDrag ? (jsx_runtime_1.jsxs("div", { draggable: canReorderSequence, onDragStart: onSequenceDragStart, onDragEnd: onSequenceDragEnd, onDragOver: onSequenceDragOver, onDragLeave: onSequenceDragLeave, onDrop: onSequenceDrop, style: sequenceReorderWrapper, children: [sequenceReorderLineStyle ? (jsx_runtime_1.jsx("div", { style: sequenceReorderLineStyle })) : null, sequenceDropRejection ? (jsx_runtime_1.jsx("div", { style: sequenceReorderRejectionStyle, children: sequenceDropRejection })) : null, trackRow] })) : (trackRow);
917
+ const draggableTrackRow = canHandleSequenceDrag ? (jsx_runtime_1.jsxs("div", { draggable: canReorderSequence, onDragStart: onSequenceDragStart, onDragEnd: onSequenceDragEnd, onDragOver: onSequenceDragOver, onDragLeave: onSequenceDragLeave, onDrop: onSequenceDrop, style: sequenceReorderWrapper, children: [sequenceReorderLineStyle ? (jsx_runtime_1.jsx("div", { style: sequenceReorderLineStyle })) : null, trackRow] })) : (trackRow);
941
918
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [previewConnected || window.remotion_isReadOnlyStudio ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { getItems: getContextMenuItems, children: draggableTrackRow })) : (draggableTrackRow), previewConnected &&
942
919
  (0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
943
920
  isExpanded &&
@@ -207,8 +207,14 @@ const TimelineSequenceKeyframedValueUnmemoized = (props) => {
207
207
  status: propStatus,
208
208
  frame: sourceFrame,
209
209
  value,
210
+ defaultEasing: (0, studio_shared_1.isSchemaFieldHoldOnly)({
211
+ schema,
212
+ key: field.key,
213
+ })
214
+ ? { type: 'step1' }
215
+ : undefined,
210
216
  }));
211
- }, [propStatus, field.key, nodePath, setDragOverrides]);
217
+ }, [propStatus, field.key, nodePath, schema, setDragOverrides]);
212
218
  const onKeyframedDragEnd = (0, react_1.useCallback)(() => {
213
219
  clearDragOverrides(nodePath);
214
220
  }, [clearDragOverrides, nodePath]);
@@ -729,9 +729,9 @@ const TimelineSequenceLeftEdgeDragHandleInner = ({ nodePathInfo, windowWidth, ti
729
729
  if (!activeDragState) {
730
730
  return;
731
731
  }
732
- return (0, pointer_session_1.startPointerSession)({
732
+ return (0, pointer_session_1.startCapturedPointerSession)({
733
733
  event: activeDragState,
734
- target: activeDragState.target,
734
+ captureTarget: activeDragState.target,
735
735
  onMove,
736
736
  onEnd: (reason, endEvent) => {
737
737
  if ((reason === 'pointerup' || reason === 'buttons-released') &&
@@ -953,9 +953,9 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
953
953
  if (!activeDragState) {
954
954
  return;
955
955
  }
956
- return (0, pointer_session_1.startPointerSession)({
956
+ return (0, pointer_session_1.startCapturedPointerSession)({
957
957
  event: activeDragState,
958
- target: activeDragState.target,
958
+ captureTarget: activeDragState.target,
959
959
  onMove,
960
960
  onEnd: (reason, endEvent) => {
961
961
  if ((reason === 'pointerup' || reason === 'buttons-released') &&
@@ -1136,9 +1136,9 @@ const TimelineSequenceRightEdgeDragHandleInner = ({ nodePathInfo, windowWidth, t
1136
1136
  if (!activeDragState) {
1137
1137
  return;
1138
1138
  }
1139
- return (0, pointer_session_1.startPointerSession)({
1139
+ return (0, pointer_session_1.startCapturedPointerSession)({
1140
1140
  event: activeDragState,
1141
- target: activeDragState.target,
1141
+ captureTarget: activeDragState.target,
1142
1142
  onMove,
1143
1143
  onEnd: (reason, endEvent) => {
1144
1144
  if ((reason === 'pointerup' || reason === 'buttons-released') &&
@@ -50,6 +50,7 @@ const getSequenceContextMenuItems = ({ assetLinkInfo, canOpenInEditor, deleteDis
50
50
  excludeEditorId: defaultEditorId,
51
51
  fileManagerDisabled: !(originalLocation === null || originalLocation === void 0 ? void 0 : originalLocation.source),
52
52
  folder: false,
53
+ location: originalLocation,
53
54
  onConfigureApps,
54
55
  onOpenInCodingAgent: openInCodingAgentWithContext,
55
56
  onOpenInEditor: openInEditor,
@@ -1,4 +1,4 @@
1
- import type { KeyframeClipboardData } from '@remotion/studio-shared';
1
+ import type { KeyframeClipboardData, KeyframeClipboardFieldType } from '@remotion/studio-shared';
2
2
  import { type InteractivitySchema, type OverrideIdToNodePaths, type PropStatuses, type SequencePropsSubscriptionKey, type TSequence } from 'remotion';
3
3
  import type { TimelineSelection } from './TimelineSelection';
4
4
  export declare const getKeyframeClipboardDataFromSelections: ({ selections, sequences, overrideIdsToNodePaths, propStatuses, }: {
@@ -24,6 +24,10 @@ export type PasteKeyframeTarget = {
24
24
  } | {
25
25
  readonly type: 'none' | 'multiple' | 'uncopyable' | 'incompatible';
26
26
  };
27
+ export declare const isKeyframeValueCompatible: ({ value, fieldType, }: {
28
+ readonly value: unknown;
29
+ readonly fieldType: KeyframeClipboardFieldType | null;
30
+ }) => boolean;
27
31
  export declare const getPasteKeyframeTarget: ({ selectedItems, payload, timelinePosition, sequences, overrideIdsToNodePaths, propStatuses, }: {
28
32
  readonly selectedItems: readonly TimelineSelection[];
29
33
  readonly payload: KeyframeClipboardData;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getPasteKeyframeTarget = exports.getKeyframeClipboardDataFromSelections = void 0;
3
+ exports.getPasteKeyframeTarget = exports.isKeyframeValueCompatible = exports.getKeyframeClipboardDataFromSelections = void 0;
4
4
  const studio_shared_1 = require("@remotion/studio-shared");
5
5
  const remotion_1 = require("remotion");
6
6
  const find_track_for_node_path_info_1 = require("./find-track-for-node-path-info");
@@ -217,6 +217,7 @@ const isKeyframeValueCompatible = ({ value, fieldType, }) => {
217
217
  }
218
218
  return typeof value === 'string';
219
219
  };
220
+ exports.isKeyframeValueCompatible = isKeyframeValueCompatible;
220
221
  const getPasteKeyframeTarget = ({ selectedItems, payload, timelinePosition, sequences, overrideIdsToNodePaths, propStatuses, }) => {
221
222
  var _a, _b, _c;
222
223
  if (selectedItems.length === 0) {
@@ -270,7 +271,7 @@ const getPasteKeyframeTarget = ({ selectedItems, payload, timelinePosition, sequ
270
271
  ].sort((first, second) => first - second);
271
272
  const firstEasingSegmentIndex = finalFrames.indexOf(firstFrame);
272
273
  if (resolved.fieldType !== payload.fieldType ||
273
- payload.keyframes.some((keyframe) => !isKeyframeValueCompatible({
274
+ payload.keyframes.some((keyframe) => !(0, exports.isKeyframeValueCompatible)({
274
275
  value: keyframe.value,
275
276
  fieldType: payload.fieldType,
276
277
  }))) {
@@ -36,6 +36,7 @@ const saveInlineCaptionPatches = ({ fileName, nodePath, schema, patches, nextCap
36
36
  };
37
37
  exports.saveInlineCaptionPatches = saveInlineCaptionPatches;
38
38
  const saveSequenceProps = ({ changes, addedKeyframes, movedKeyframes, setPropStatuses, clientId, undoLabel, redoLabel, }) => {
39
+ var _a;
39
40
  const keyframesToAdd = addedKeyframes === null ? [] : addedKeyframes;
40
41
  const sequenceKeyframes = movedKeyframes === null ? [] : movedKeyframes.sequenceKeyframes;
41
42
  const effectKeyframes = movedKeyframes === null ? [] : movedKeyframes.effectKeyframes;
@@ -56,13 +57,18 @@ const saveSequenceProps = ({ changes, addedKeyframes, movedKeyframes, setPropSta
56
57
  return (0, save_prop_queue_1.enqueueSavePropChange)({
57
58
  nodePath: change.nodePath,
58
59
  setPropStatuses,
59
- applyOptimistic: (prev) => (0, studio_shared_1.optimisticUpdateForPropStatuses)({
60
- previous: prev,
61
- fieldKey: change.fieldKey,
62
- value: change.value,
63
- defaultValue: change.defaultValue,
64
- schema: change.schema,
65
- }),
60
+ applyOptimistic: (prev) => {
61
+ var _a;
62
+ return ((_a = change.sourceEdit) === null || _a === void 0 ? void 0 : _a.type) === 'clipboard-param'
63
+ ? prev
64
+ : (0, studio_shared_1.optimisticUpdateForPropStatuses)({
65
+ previous: prev,
66
+ fieldKey: change.fieldKey,
67
+ value: change.value,
68
+ defaultValue: change.defaultValue,
69
+ schema: change.schema,
70
+ });
71
+ },
66
72
  apiCall: () => {
67
73
  var _a;
68
74
  return (0, sequence_props_api_1.saveSequenceProps)({
@@ -102,6 +108,9 @@ const saveSequenceProps = ({ changes, addedKeyframes, movedKeyframes, setPropSta
102
108
  }));
103
109
  }
104
110
  for (const change of changes) {
111
+ if (((_a = change.sourceEdit) === null || _a === void 0 ? void 0 : _a.type) === 'clipboard-param') {
112
+ continue;
113
+ }
105
114
  setPropStatuses(change.nodePath, (prev) => (0, studio_shared_1.optimisticUpdateForPropStatuses)({
106
115
  previous: prev,
107
116
  fieldKey: change.fieldKey,
@@ -0,0 +1,31 @@
1
+ import { type EffectClipboardParam, type SequencePropClipboardData } from '@remotion/studio-shared';
2
+ import { type CanUpdateSequencePropStatus, type InteractivitySchema, type OverrideIdToNodePaths, type PropStatuses, type SequencePropsSubscriptionKey, type TSequence } from 'remotion';
3
+ import type { TimelineSelection } from './TimelineSelection';
4
+ export declare const propStatusToClipboardParam: (prop: CanUpdateSequencePropStatus) => EffectClipboardParam | null;
5
+ export declare const getSequencePropClipboardDataFromSelection: ({ selection, propStatuses, sequences, overrideIdsToNodePaths, }: {
6
+ readonly selection: TimelineSelection;
7
+ readonly propStatuses: PropStatuses;
8
+ readonly sequences: TSequence[];
9
+ readonly overrideIdsToNodePaths: OverrideIdToNodePaths;
10
+ }) => SequencePropClipboardData | null;
11
+ type PasteSequencePropEditTarget = {
12
+ readonly fileName: string;
13
+ readonly nodePath: SequencePropsSubscriptionKey;
14
+ readonly fieldKey: string;
15
+ readonly defaultValue: string | null;
16
+ readonly schema: InteractivitySchema;
17
+ };
18
+ export type PasteSequencePropTarget = {
19
+ readonly type: 'valid';
20
+ readonly targets: PasteSequencePropEditTarget[];
21
+ } | {
22
+ readonly type: 'none' | 'prop-mismatch' | 'uncopyable' | 'incompatible';
23
+ };
24
+ export declare const getPasteSequencePropTarget: ({ selectedItems, payload, propStatuses, sequences, overrideIdsToNodePaths, }: {
25
+ readonly selectedItems: readonly TimelineSelection[];
26
+ readonly payload: SequencePropClipboardData;
27
+ readonly propStatuses: PropStatuses;
28
+ readonly sequences: TSequence[];
29
+ readonly overrideIdsToNodePaths: OverrideIdToNodePaths;
30
+ }) => PasteSequencePropTarget;
31
+ export {};
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPasteSequencePropTarget = exports.getSequencePropClipboardDataFromSelection = exports.propStatusToClipboardParam = 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 keyframe_clipboard_1 = require("./keyframe-clipboard");
8
+ const propStatusToClipboardParam = (prop) => {
9
+ if (prop.status === 'computed') {
10
+ return null;
11
+ }
12
+ if (prop.status === 'static') {
13
+ if (prop.codeValue === undefined) {
14
+ return null;
15
+ }
16
+ return { type: 'static', value: prop.codeValue };
17
+ }
18
+ if (!(0, studio_shared_1.isKeyframeInterpolationFunction)(prop.interpolationFunction)) {
19
+ return null;
20
+ }
21
+ return {
22
+ type: 'keyframed',
23
+ interpolationFunction: prop.interpolationFunction,
24
+ keyframes: prop.keyframes,
25
+ easing: prop.easing,
26
+ clamping: prop.clamping,
27
+ ...(prop.output === undefined || prop.output === 'linear'
28
+ ? {}
29
+ : { output: prop.output }),
30
+ ...(prop.posterize === undefined ? {} : { posterize: prop.posterize }),
31
+ };
32
+ };
33
+ exports.propStatusToClipboardParam = propStatusToClipboardParam;
34
+ const getSequencePropClipboardDataFromSelection = ({ selection, propStatuses, sequences, overrideIdsToNodePaths, }) => {
35
+ var _a, _b;
36
+ var _c;
37
+ if (selection.type !== 'sequence-prop') {
38
+ return null;
39
+ }
40
+ const track = (0, find_track_for_node_path_info_1.findTrackForNodePathInfo)({
41
+ sequences,
42
+ overrideIdsToNodePaths,
43
+ nodePathInfo: selection.nodePathInfo,
44
+ });
45
+ if (!(track === null || track === void 0 ? void 0 : track.sequence.controls)) {
46
+ return null;
47
+ }
48
+ const field = remotion_1.Internals.getFlatSchemaWithAllKeys(track.sequence.controls.schema)[selection.key];
49
+ if (!field || !(0, studio_shared_1.isKeyframeClipboardFieldType)(field.type)) {
50
+ return null;
51
+ }
52
+ const propStatus = (_b = remotion_1.Internals.getPropStatusesCtx(propStatuses, (_c = (_a = track.nodePathInfo) === null || _a === void 0 ? void 0 : _a.sequenceSubscriptionKey) !== null && _c !== void 0 ? _c : selection.nodePathInfo.sequenceSubscriptionKey)) === null || _b === void 0 ? void 0 : _b[selection.key];
53
+ if (!propStatus) {
54
+ return null;
55
+ }
56
+ const param = (0, exports.propStatusToClipboardParam)(propStatus);
57
+ if (param === null) {
58
+ return null;
59
+ }
60
+ return {
61
+ type: 'sequence-prop',
62
+ version: 1,
63
+ remotionClipboard: 'sequence-prop',
64
+ key: selection.key,
65
+ fieldType: field.type,
66
+ param,
67
+ };
68
+ };
69
+ exports.getSequencePropClipboardDataFromSelection = getSequencePropClipboardDataFromSelection;
70
+ const getPasteTargetForSelection = ({ selection, payload, propStatuses, sequences, overrideIdsToNodePaths, }) => {
71
+ var _a;
72
+ if (selection.type !== 'sequence-prop' && selection.type !== 'sequence') {
73
+ return { type: 'none' };
74
+ }
75
+ const fieldKey = selection.type === 'sequence-prop' ? selection.key : payload.key;
76
+ if (fieldKey !== payload.key) {
77
+ return { type: 'prop-mismatch' };
78
+ }
79
+ const track = (0, find_track_for_node_path_info_1.findTrackForNodePathInfo)({
80
+ sequences,
81
+ overrideIdsToNodePaths,
82
+ nodePathInfo: selection.nodePathInfo,
83
+ });
84
+ if (!(track === null || track === void 0 ? void 0 : track.sequence.controls) || !track.nodePathInfo) {
85
+ return { type: 'uncopyable' };
86
+ }
87
+ const { schema } = track.sequence.controls;
88
+ const field = remotion_1.Internals.getFlatSchemaWithAllKeys(schema)[fieldKey];
89
+ if (!field || field.type !== payload.fieldType) {
90
+ return { type: 'incompatible' };
91
+ }
92
+ const nodePath = track.nodePathInfo.sequenceSubscriptionKey;
93
+ const propStatus = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a[fieldKey];
94
+ if (!propStatus || propStatus.status === 'computed') {
95
+ return { type: 'uncopyable' };
96
+ }
97
+ const values = payload.param.type === 'static'
98
+ ? [payload.param.value]
99
+ : payload.param.keyframes.map((keyframe) => keyframe.value);
100
+ if (values.some((value) => !(0, keyframe_clipboard_1.isKeyframeValueCompatible)({ value, fieldType: payload.fieldType }))) {
101
+ return { type: 'incompatible' };
102
+ }
103
+ return {
104
+ type: 'valid',
105
+ target: {
106
+ fileName: nodePath.absolutePath,
107
+ nodePath,
108
+ fieldKey,
109
+ defaultValue: field.default === undefined ? null : JSON.stringify(field.default),
110
+ schema,
111
+ },
112
+ };
113
+ };
114
+ const getPasteSequencePropTarget = ({ selectedItems, payload, propStatuses, sequences, overrideIdsToNodePaths, }) => {
115
+ if (selectedItems.length === 0) {
116
+ return { type: 'none' };
117
+ }
118
+ const targets = [];
119
+ for (const selection of selectedItems) {
120
+ const result = getPasteTargetForSelection({
121
+ selection,
122
+ payload,
123
+ propStatuses,
124
+ sequences,
125
+ overrideIdsToNodePaths,
126
+ });
127
+ if (result.type !== 'valid') {
128
+ return result;
129
+ }
130
+ targets.push(result.target);
131
+ }
132
+ return {
133
+ type: 'valid',
134
+ targets: [
135
+ ...new Map(targets.map((target) => [
136
+ remotion_1.Internals.makeSequencePropsSubscriptionKey(target.nodePath),
137
+ target,
138
+ ])).values(),
139
+ ],
140
+ };
141
+ };
142
+ exports.getPasteSequencePropTarget = getPasteSequencePropTarget;
@@ -33,6 +33,10 @@ const getSelectedEasingUpdate = ({ selection, sequences, overrideIdsToNodePaths,
33
33
  }
34
34
  const sequencePropStatus = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a[field.fieldKey];
35
35
  if ((sequencePropStatus === null || sequencePropStatus === void 0 ? void 0 : sequencePropStatus.status) !== 'keyframed' ||
36
+ (0, studio_shared_1.isSchemaFieldHoldOnly)({
37
+ schema: sequence.controls.schema,
38
+ key: field.fieldKey,
39
+ }) ||
36
40
  !(0, studio_shared_1.canEditEasingForInterpolationFunction)(sequencePropStatus.interpolationFunction)) {
37
41
  return null;
38
42
  }
@@ -60,6 +64,10 @@ const getSelectedEasingUpdate = ({ selection, sequences, overrideIdsToNodePaths,
60
64
  ? effectStatus.props[field.fieldKey]
61
65
  : null;
62
66
  if ((effectPropStatus === null || effectPropStatus === void 0 ? void 0 : effectPropStatus.status) !== 'keyframed' ||
67
+ (0, studio_shared_1.isSchemaFieldHoldOnly)({
68
+ schema: effect.schema,
69
+ key: field.fieldKey,
70
+ }) ||
63
71
  !(0, studio_shared_1.canEditEasingForInterpolationFunction)(effectPropStatus.interpolationFunction)) {
64
72
  return null;
65
73
  }
@@ -8,9 +8,11 @@ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
8
8
  const use_default_editor_info_1 = require("../use-default-editor-info");
9
9
  const use_resolved_stack_react_to_change_1 = require("./use-resolved-stack-react-to-change");
10
10
  const useOpenSequenceInApps = (sequence) => {
11
+ var _a;
12
+ var _b;
11
13
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
12
14
  const previewConnected = previewServerState.type === 'connected';
13
- const { resolvedLocation: originalLocation } = (0, use_resolved_stack_react_to_change_1.useResolveStackAndReactToChange)(sequence.getStack);
15
+ const { resolvedLocation: originalLocation } = (0, use_resolved_stack_react_to_change_1.useResolveStackAndReactToChange)(sequence.getStack, (_b = (_a = sequence.controls) === null || _a === void 0 ? void 0 : _a.overrideId) !== null && _b !== void 0 ? _b : sequence.id);
14
16
  const editorPickerAvailable = (0, use_default_editor_info_1.canUseEditorPicker)(previewConnected);
15
17
  const editorInfo = (0, use_default_editor_info_1.useDefaultEditorInfo)(editorPickerAvailable);
16
18
  const codingAgentInfo = (0, use_default_editor_info_1.useDefaultCodingAgentInfo)(editorPickerAvailable);
@@ -1,5 +1,5 @@
1
1
  import type { ResolvedStackLocation } from 'remotion';
2
- export declare const useResolveStackAndReactToChange: (getStack: () => string | null) => {
2
+ export declare const useResolveStackAndReactToChange: (getStack: () => string | null, sequenceIdentity: string) => {
3
3
  preferMappedNodePath: boolean;
4
4
  resolvedLocation: ResolvedStackLocation | null;
5
5
  stack: string | null;
@@ -17,7 +17,7 @@ const matchesSourceLocation = (event, location) => {
17
17
  event.line === location.line &&
18
18
  event.column === ((_a = location.column) !== null && _a !== void 0 ? _a : 0));
19
19
  };
20
- const useResolveStackAndReactToChange = (getStack) => {
20
+ const useResolveStackAndReactToChange = (getStack, sequenceIdentity) => {
21
21
  const { subscribeToEvent } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
22
22
  const { fastRefreshes } = (0, react_1.useContext)(fast_refresh_context_1.FastRefreshContext);
23
23
  const [stackState, setStackState] = (0, react_1.useState)(() => ({
@@ -25,13 +25,34 @@ const useResolveStackAndReactToChange = (getStack) => {
25
25
  preferMappedNodePath: true,
26
26
  }));
27
27
  const resolvedLocationFromStack = (0, use_resolved_stack_1.useResolvedStack)(stackState.stack);
28
- const resolvedLocation = (0, use_resolved_stack_1.hasResolvedStack)(stackState.stack)
28
+ const stackIsResolved = (0, use_resolved_stack_1.hasResolvedStack)(stackState.stack);
29
+ const lastResolvedLocation = (0, react_1.useRef)(resolvedLocationFromStack);
30
+ if (stackIsResolved) {
31
+ lastResolvedLocation.current = resolvedLocationFromStack;
32
+ }
33
+ const resolvedLocation = stackIsResolved
29
34
  ? resolvedLocationFromStack
30
- : null;
35
+ : stackState.preferMappedNodePath
36
+ ? null
37
+ : lastResolvedLocation.current;
31
38
  const resolvedLocationRef = (0, react_1.useRef)(resolvedLocation);
32
39
  resolvedLocationRef.current = resolvedLocation;
33
40
  const getStackRef = (0, react_1.useRef)(getStack);
34
41
  getStackRef.current = getStack;
42
+ (0, react_1.useEffect)(() => {
43
+ const newStack = getStackRef.current();
44
+ setStackState((current) => {
45
+ if (newStack === current.stack) {
46
+ return current;
47
+ }
48
+ return {
49
+ stack: newStack,
50
+ // A different identity means a different selected sequence. Its existing
51
+ // node path mapping is still preferred.
52
+ preferMappedNodePath: true,
53
+ };
54
+ });
55
+ }, [sequenceIdentity]);
35
56
  (0, react_1.useEffect)(() => {
36
57
  if (fastRefreshes === 0) {
37
58
  return;
@@ -436,9 +436,9 @@ const useTimelineKeyframeDrag = ({ frame, nodePathInfo, onSelect, selectable, se
436
436
  clearActiveOverrides();
437
437
  clearDraggedKeyframes();
438
438
  };
439
- stopPointerSession = (0, pointer_session_1.startPointerSession)({
439
+ stopPointerSession = (0, pointer_session_1.startCapturedPointerSession)({
440
440
  event: e,
441
- target: e.currentTarget,
441
+ captureTarget: e.currentTarget,
442
442
  onMove: onPointerMove,
443
443
  onEnd: (reason) => {
444
444
  if (reason === 'pointerup' || reason === 'buttons-released') {
@@ -643,9 +643,9 @@ const useTimelineEasingKeyframeDrag = ({ onSelect, selectable, selected, selecti
643
643
  clearActiveOverrides();
644
644
  clearDraggedKeyframes();
645
645
  };
646
- stopPointerSession = (0, pointer_session_1.startPointerSession)({
646
+ stopPointerSession = (0, pointer_session_1.startCapturedPointerSession)({
647
647
  event: e,
648
- target: e.currentTarget,
648
+ captureTarget: e.currentTarget,
649
649
  onMove: onPointerMove,
650
650
  onEnd: (reason) => {
651
651
  if (reason === 'pointerup' || reason === 'buttons-released') {
@@ -88,6 +88,7 @@ const getFolderMenuItems = ({ closeMenu, connectionStatus, folder, readOnlyStudi
88
88
  folderName: folder.name,
89
89
  parentName: folder.parent,
90
90
  stack: folder.stack,
91
+ canvasCapture: null,
91
92
  });
92
93
  },
93
94
  quickSwitcherLabel: 'New composition in folder...',
@@ -1,7 +1,8 @@
1
1
  import type { TerminalId } from '@remotion/studio-shared';
2
2
  import type { EditorPickerId, GetDefaultCodingAgentInfoResponse, GetDefaultEditorInfoResponse } from '@remotion/studio-shared';
3
+ import type { OriginalPosition } from '../error-overlay/react-overlay/utils/get-source-map';
3
4
  import type { ComboboxValue } from './NewComposition/ComboBox';
4
- export declare const getOpenInMenuItems: ({ codingAgentInfo, editorDisabled, editorInfo, excludeCodingAgentId, excludeEditorId, fileManagerDisabled, folder, onConfigureApps, onOpenInCodingAgent, onOpenInEditor, onOpenInFileExplorer, onOpenInTerminal, }: {
5
+ export declare const getOpenInMenuItems: ({ codingAgentInfo, editorDisabled, editorInfo, excludeCodingAgentId, excludeEditorId, fileManagerDisabled, folder, location, onConfigureApps, onOpenInCodingAgent, onOpenInEditor, onOpenInFileExplorer, onOpenInTerminal, }: {
5
6
  readonly codingAgentInfo: GetDefaultCodingAgentInfoResponse | null;
6
7
  readonly editorDisabled: boolean;
7
8
  readonly editorInfo: GetDefaultEditorInfoResponse | null;
@@ -9,6 +10,7 @@ export declare const getOpenInMenuItems: ({ codingAgentInfo, editorDisabled, edi
9
10
  readonly excludeEditorId: EditorPickerId | null;
10
11
  readonly fileManagerDisabled: boolean;
11
12
  readonly folder: boolean;
13
+ readonly location: OriginalPosition | null;
12
14
  readonly onConfigureApps: () => void;
13
15
  readonly onOpenInCodingAgent: (codingAgentId: "claude-code" | "codex" | "copilot" | "cursor", codingAgentName: string) => void;
14
16
  readonly onOpenInEditor: (editorId: EditorPickerId) => void;