@remotion/studio 4.0.508 → 4.0.510

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 (117) hide show
  1. package/dist/Studio.d.ts +5 -0
  2. package/dist/Studio.js +2 -2
  3. package/dist/components/Canvas.js +41 -8
  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/CompositionSelectorItem.js +1 -1
  8. package/dist/components/EditorGuides/Guide.js +2 -2
  9. package/dist/components/EditorRuler/index.js +2 -2
  10. package/dist/components/ExplorerPanel.js +19 -1
  11. package/dist/components/InspectorOpenInEditor.js +19 -5
  12. package/dist/components/InspectorPanel/CompositionMetadata.js +23 -1
  13. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +3 -3
  14. package/dist/components/Menu/MenuItem.js +2 -2
  15. package/dist/components/ModalContainer.js +1 -1
  16. package/dist/components/Modals.js +2 -9
  17. package/dist/components/NewComposition/InputDragger.js +2 -2
  18. package/dist/components/NewComposition/NewComposition.d.ts +2 -0
  19. package/dist/components/NewComposition/NewComposition.js +38 -6
  20. package/dist/components/NewComposition/get-new-composition-defaults.d.ts +1 -1
  21. package/dist/components/NewComposition/get-new-composition-defaults.js +9 -1
  22. package/dist/components/QuickSwitcher/asset-search.js +1 -0
  23. package/dist/components/SelectedOutlineCanvasRotation.js +6 -4
  24. package/dist/components/SelectedOutlineCropControls.js +3 -3
  25. package/dist/components/SelectedOutlineElement.js +6 -2
  26. package/dist/components/SelectedOutlinePolygon.js +4 -3
  27. package/dist/components/SelectedOutlineRotationCornerHandle.d.ts +5 -0
  28. package/dist/components/SelectedOutlineRotationCornerHandle.js +4 -4
  29. package/dist/components/SelectedOutlineScaleEdgeLine.d.ts +1 -0
  30. package/dist/components/SelectedOutlineScaleEdgeLine.js +4 -4
  31. package/dist/components/SelectedOutlineTransformOriginHandle.js +2 -2
  32. package/dist/components/SelectedOutlineUvControls.js +8 -8
  33. package/dist/components/Splitter/SplitterHandle.js +2 -2
  34. package/dist/components/Tabs/index.d.ts +2 -0
  35. package/dist/components/Tabs/index.js +2 -2
  36. package/dist/components/Timeline/EasingEditorModal.d.ts +8 -0
  37. package/dist/components/Timeline/EasingEditorModal.js +10 -11
  38. package/dist/components/Timeline/SubscribeToNodePaths.js +1 -1
  39. package/dist/components/Timeline/Timeline.js +55 -1
  40. package/dist/components/Timeline/TimelineClipboardKeybindings.js +99 -35
  41. package/dist/components/Timeline/TimelineColorField.js +1 -6
  42. package/dist/components/Timeline/TimelineDragHandler.js +2 -2
  43. package/dist/components/Timeline/TimelineEffectItem.js +1 -1
  44. package/dist/components/Timeline/TimelineEffectPropItem.js +8 -1
  45. package/dist/components/Timeline/TimelineEnumField.js +1 -4
  46. package/dist/components/Timeline/TimelineExpandedRow.js +2 -2
  47. package/dist/components/Timeline/TimelineFieldRowContent.d.ts +2 -1
  48. package/dist/components/Timeline/TimelineFieldRowContent.js +18 -3
  49. package/dist/components/Timeline/TimelineFontFamilyField.js +1 -2
  50. package/dist/components/Timeline/TimelineInOutDragHandler.js +2 -2
  51. package/dist/components/Timeline/TimelineKeyframeEasingLine.js +3 -2
  52. package/dist/components/Timeline/TimelineLayerEye.js +2 -2
  53. package/dist/components/Timeline/TimelineNumberField.js +4 -2
  54. package/dist/components/Timeline/TimelineRotationField.js +3 -3
  55. package/dist/components/Timeline/TimelineRowChrome.d.ts +5 -0
  56. package/dist/components/Timeline/TimelineRowChrome.js +14 -9
  57. package/dist/components/Timeline/TimelineRowLayoutContext.d.ts +1 -0
  58. package/dist/components/Timeline/TimelineRowLayoutContext.js +4 -1
  59. package/dist/components/Timeline/TimelineScaleField.js +4 -0
  60. package/dist/components/Timeline/TimelineSelection.js +2 -2
  61. package/dist/components/Timeline/TimelineSequenceItem.js +2 -25
  62. package/dist/components/Timeline/TimelineSequencePropItem.js +8 -2
  63. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +2 -0
  64. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +69 -20
  65. package/dist/components/Timeline/TimelineTextContentField.js +1 -1
  66. package/dist/components/Timeline/get-sequence-context-menu-items.js +2 -0
  67. package/dist/components/Timeline/keyframe-clipboard.d.ts +5 -1
  68. package/dist/components/Timeline/keyframe-clipboard.js +3 -2
  69. package/dist/components/Timeline/save-sequence-prop.js +16 -7
  70. package/dist/components/Timeline/sequence-prop-clipboard.d.ts +31 -0
  71. package/dist/components/Timeline/sequence-prop-clipboard.js +142 -0
  72. package/dist/components/Timeline/split-selected-timeline-item.d.ts +0 -1
  73. package/dist/components/Timeline/split-selected-timeline-item.js +5 -13
  74. package/dist/components/Timeline/timeline-field-row-layout.js +2 -2
  75. package/dist/components/Timeline/timeline-field-utils.d.ts +1 -0
  76. package/dist/components/Timeline/timeline-field-utils.js +6 -1
  77. package/dist/components/Timeline/update-selected-easing.js +8 -0
  78. package/dist/components/Timeline/use-open-sequence-in-apps.js +3 -1
  79. package/dist/components/Timeline/use-resolved-stack-react-to-change.d.ts +1 -1
  80. package/dist/components/Timeline/use-resolved-stack-react-to-change.js +24 -3
  81. package/dist/components/Timeline/use-timeline-keyframe-drag.js +4 -4
  82. package/dist/components/UndoRedoButtons.js +5 -3
  83. package/dist/components/folder-menu-items.js +1 -0
  84. package/dist/components/get-open-in-menu-items.d.ts +4 -1
  85. package/dist/components/get-open-in-menu-items.js +99 -50
  86. package/dist/components/import-assets.js +7 -0
  87. package/dist/components/root-composition-menu-items.js +1 -0
  88. package/dist/components/selected-outline-control-layout.d.ts +14 -0
  89. package/dist/components/selected-outline-control-layout.js +94 -0
  90. package/dist/components/use-default-editor-info.js +28 -3
  91. package/dist/esm/{chunk-zpn4m49r.js → chunk-axbagh08.js} +6098 -5285
  92. package/dist/esm/{chunk-fgedsvhb.js → chunk-r46yxrjr.js} +1 -2
  93. package/dist/esm/internals.mjs +6097 -5284
  94. package/dist/esm/previewEntry.mjs +5989 -5176
  95. package/dist/esm/renderEntry.mjs +4 -2
  96. package/dist/helpers/get-canvas-capture-import.d.ts +7 -0
  97. package/dist/helpers/get-canvas-capture-import.js +43 -0
  98. package/dist/helpers/get-git-menu-item.d.ts +1 -1
  99. package/dist/helpers/get-git-menu-item.js +33 -3
  100. package/dist/helpers/inserted-element-selection.d.ts +12 -0
  101. package/dist/helpers/inserted-element-selection.js +29 -0
  102. package/dist/helpers/open-in-editor.d.ts +1 -0
  103. package/dist/helpers/open-in-editor.js +5 -1
  104. package/dist/helpers/pointer-session.d.ts +6 -2
  105. package/dist/helpers/pointer-session.js +29 -12
  106. package/dist/helpers/use-create-composition.d.ts +15 -2
  107. package/dist/helpers/use-create-composition.js +11 -17
  108. package/dist/helpers/use-menu-structure.js +1 -0
  109. package/dist/icons/git-client.d.ts +6 -0
  110. package/dist/icons/git-client.js +8 -0
  111. package/dist/icons/github.d.ts +4 -0
  112. package/dist/icons/github.js +11 -0
  113. package/dist/renderEntry.js +2 -2
  114. package/dist/state/modals.d.ts +9 -1
  115. package/dist/state/z-index.d.ts +0 -1
  116. package/dist/state/z-index.js +27 -33
  117. package/package.json +12 -12
@@ -1,18 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.splitSelectedTimelineItems = exports.shouldHandleTimelineSplitShortcut = exports.shouldHandleTimelineDuplicateShortcut = exports.splitTimelineSequenceFromSource = exports.getTimelineSequenceSplitEligibility = exports.getTimelineSequenceSplitUnsupportedReason = void 0;
3
+ exports.splitSelectedTimelineItems = exports.shouldHandleTimelineSplitShortcut = exports.shouldHandleTimelineDuplicateShortcut = exports.splitTimelineSequenceFromSource = exports.getTimelineSequenceSplitEligibility = void 0;
4
+ const studio_shared_1 = require("@remotion/studio-shared");
4
5
  const remotion_1 = require("remotion");
5
6
  const call_api_1 = require("../call-api");
6
7
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
7
8
  const find_track_for_node_path_info_1 = require("./find-track-for-node-path-info");
8
- const getTimelineSequenceSplitUnsupportedReason = (componentName) => {
9
- if (componentName === '<TransitionSeries.Sequence>' ||
10
- componentName === '<TransitionSeries.Overlay>') {
11
- return `${componentName} cannot be split from source`;
12
- }
13
- return null;
14
- };
15
- exports.getTimelineSequenceSplitUnsupportedReason = getTimelineSequenceSplitUnsupportedReason;
16
9
  const staticNumberish = (status) => {
17
10
  if (!status) {
18
11
  return true;
@@ -21,7 +14,6 @@ const staticNumberish = (status) => {
21
14
  (typeof status.codeValue === 'number' || status.codeValue === undefined));
22
15
  };
23
16
  const getTimelineSequenceSplitEligibility = ({ selection, sequence, splitFrame, propStatuses, }) => {
24
- var _a;
25
17
  if (selection.type !== 'sequence') {
26
18
  return {
27
19
  canSplit: false,
@@ -46,11 +38,10 @@ const getTimelineSequenceSplitEligibility = ({ selection, sequence, splitFrame,
46
38
  reason: 'Series.Sequence clips cannot be split from source',
47
39
  };
48
40
  }
49
- const unsupportedReason = (0, exports.getTimelineSequenceSplitUnsupportedReason)((_a = sequence.controls) === null || _a === void 0 ? void 0 : _a.componentName);
50
- if (unsupportedReason) {
41
+ if (!(0, studio_shared_1.hasSequenceTimingTraits)(selection.nodePathInfo.sequenceSubscriptionKey.sequenceKeys)) {
51
42
  return {
52
43
  canSplit: false,
53
- reason: unsupportedReason,
44
+ reason: 'Sequence does not expose timing traits that can be split',
54
45
  };
55
46
  }
56
47
  const { nodePathInfo } = selection;
@@ -101,6 +92,7 @@ const splitTimelineSequenceFromSource = ({ nodePathInfo, splitFrame, }) => {
101
92
  return (0, call_api_1.callApi)('/api/split-jsx-sequence', {
102
93
  fileName: nodePath.absolutePath,
103
94
  nodePath: nodePath.nodePath,
95
+ sequenceKeys: nodePath.sequenceKeys,
104
96
  splitFrame,
105
97
  })
106
98
  .then((result) => {
@@ -33,9 +33,9 @@ exports.timelineFieldValueColumnStyle = {
33
33
  };
34
34
  exports.timelineCompactStackedFieldValueColumnStyle = {
35
35
  ...exports.timelineFieldValueColumnStyle,
36
- marginBottom: -2,
36
+ marginBottom: -3,
37
37
  position: 'relative',
38
- top: -2,
38
+ top: -3,
39
39
  };
40
40
  exports.timelineStackedFieldContentStyle = {
41
41
  alignSelf: 'stretch',
@@ -11,3 +11,4 @@ export declare const formatTimelineNumber: ({ decimalPlaces, fixed, value, }: {
11
11
  }) => string;
12
12
  export declare const normalizeTimelineNumber: (value: number) => number;
13
13
  export declare const draggerStyle: React.CSSProperties;
14
+ export declare const leftAlignedDraggerStyle: React.CSSProperties;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.draggerStyle = exports.normalizeTimelineNumber = exports.formatTimelineNumber = exports.roundToDecimalPlaces = exports.getTimelineDisplayDecimalPlaces = exports.getDecimalPlaces = void 0;
3
+ exports.leftAlignedDraggerStyle = exports.draggerStyle = exports.normalizeTimelineNumber = exports.formatTimelineNumber = exports.roundToDecimalPlaces = exports.getTimelineDisplayDecimalPlaces = exports.getDecimalPlaces = void 0;
4
4
  const getDecimalPlaces = (num) => {
5
5
  const [coefficient, exponent] = String(num).toLowerCase().split('e');
6
6
  const decimalIndex = coefficient.indexOf('.');
@@ -35,3 +35,8 @@ exports.normalizeTimelineNumber = normalizeTimelineNumber;
35
35
  exports.draggerStyle = {
36
36
  width: 80,
37
37
  };
38
+ exports.leftAlignedDraggerStyle = {
39
+ paddingBottom: 2,
40
+ paddingLeft: 0,
41
+ paddingTop: 2,
42
+ };
@@ -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') {
@@ -69,6 +69,8 @@ const UndoRedoButtons = () => {
69
69
  });
70
70
  }, []);
71
71
  (0, react_1.useEffect)(() => {
72
+ // Visual controls such as the color picker commit edits while their popup
73
+ // remains open. Keep undo and redo available in that higher z-index context.
72
74
  const undo = keybindings.registerKeybinding({
73
75
  event: 'keydown',
74
76
  key: 'z',
@@ -83,7 +85,7 @@ const UndoRedoButtons = () => {
83
85
  },
84
86
  preventDefault: true,
85
87
  triggerIfInputFieldFocused: false,
86
- keepRegisteredWhenNotHighestContext: false,
88
+ keepRegisteredWhenNotHighestContext: true,
87
89
  });
88
90
  const redoWithShiftZ = keybindings.registerKeybinding({
89
91
  event: 'keydown',
@@ -99,7 +101,7 @@ const UndoRedoButtons = () => {
99
101
  },
100
102
  preventDefault: true,
101
103
  triggerIfInputFieldFocused: false,
102
- keepRegisteredWhenNotHighestContext: false,
104
+ keepRegisteredWhenNotHighestContext: true,
103
105
  });
104
106
  const redoWithY = is_mac_1.isMac
105
107
  ? null
@@ -114,7 +116,7 @@ const UndoRedoButtons = () => {
114
116
  },
115
117
  preventDefault: true,
116
118
  triggerIfInputFieldFocused: false,
117
- keepRegisteredWhenNotHighestContext: false,
119
+ keepRegisteredWhenNotHighestContext: true,
118
120
  });
119
121
  return () => {
120
122
  undo.unregister();
@@ -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, onOpenInGitClient, onOpenInTerminal, }: {
5
6
  readonly codingAgentInfo: GetDefaultCodingAgentInfoResponse | null;
6
7
  readonly editorDisabled: boolean;
7
8
  readonly editorInfo: GetDefaultEditorInfoResponse | null;
@@ -9,9 +10,11 @@ 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;
15
17
  readonly onOpenInFileExplorer: () => void;
18
+ readonly onOpenInGitClient: (gitClientId: "github-desktop") => void;
16
19
  readonly onOpenInTerminal: ((terminalId: TerminalId) => void) | null;
17
20
  }) => ComboboxValue[];
@@ -2,9 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getOpenInMenuItems = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const no_react_1 = require("remotion/no-react");
5
6
  const get_file_manager_name_1 = require("../helpers/get-file-manager-name");
7
+ const get_git_menu_item_1 = require("../helpers/get-git-menu-item");
6
8
  const editor_1 = require("../icons/editor");
7
9
  const finder_1 = require("../icons/finder");
10
+ const git_client_1 = require("../icons/git-client");
11
+ const github_1 = require("../icons/github");
8
12
  const terminal_1 = require("../icons/terminal");
9
13
  const CodingAgentIcon_1 = require("./CodingAgentIcon");
10
14
  const menuLabel = {
@@ -13,8 +17,8 @@ const menuLabel = {
13
17
  fontSize: 13,
14
18
  lineHeight: '16px',
15
19
  };
16
- const getOpenInMenuItems = ({ codingAgentInfo, editorDisabled, editorInfo, excludeCodingAgentId, excludeEditorId, fileManagerDisabled, folder, onConfigureApps, onOpenInCodingAgent, onOpenInEditor, onOpenInFileExplorer, onOpenInTerminal, }) => {
17
- var _a, _b, _c;
20
+ const getOpenInMenuItems = ({ codingAgentInfo, editorDisabled, editorInfo, excludeCodingAgentId, excludeEditorId, fileManagerDisabled, folder, location, onConfigureApps, onOpenInCodingAgent, onOpenInEditor, onOpenInFileExplorer, onOpenInGitClient, onOpenInTerminal, }) => {
21
+ var _a, _b, _c, _d;
18
22
  const showFinder = window.remotion_fileSystemPlatform === 'darwin';
19
23
  const fileManagerName = (0, get_file_manager_name_1.getFileManagerName)(window.remotion_fileSystemPlatform);
20
24
  const editors = ((_a = editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors) !== null && _a !== void 0 ? _a : [])
@@ -49,7 +53,53 @@ const getOpenInMenuItems = ({ codingAgentInfo, editorDisabled, editorInfo, exclu
49
53
  value: `coding-agent-${codingAgent.id}`,
50
54
  }));
51
55
  const terminals = folder ? ((_c = codingAgentInfo === null || codingAgentInfo === void 0 ? void 0 : codingAgentInfo.installedTerminals) !== null && _c !== void 0 ? _c : []) : [];
52
- const showSystemApps = showFinder || terminals.length > 0;
56
+ const gitClients = folder ? ((_d = codingAgentInfo === null || codingAgentInfo === void 0 ? void 0 : codingAgentInfo.installedGitClients) !== null && _d !== void 0 ? _d : []) : [];
57
+ const gitHubItem = window.remotion_gitSource
58
+ ? {
59
+ id: 'open-in-github',
60
+ keyHint: null,
61
+ label: jsx_runtime_1.jsx("span", { style: menuLabel, children: "GitHub.com" }),
62
+ leftItem: jsx_runtime_1.jsx(github_1.GitHubIcon, { size: 18 }),
63
+ onClick: () => {
64
+ const gitSource = window.remotion_gitSource;
65
+ if (!gitSource) {
66
+ return;
67
+ }
68
+ window.open(folder || !location
69
+ ? (0, get_git_menu_item_1.getGitSourceBranchUrl)(gitSource)
70
+ : (0, get_git_menu_item_1.getGitRefUrl)(gitSource, location, window.remotion_cwd), '_blank');
71
+ },
72
+ quickSwitcherLabel: null,
73
+ subMenu: null,
74
+ type: 'item',
75
+ value: 'github',
76
+ }
77
+ : null;
78
+ const systemApps = [
79
+ gitHubItem,
80
+ showFinder
81
+ ? {
82
+ disabled: fileManagerDisabled,
83
+ id: 'open-in-file-explorer',
84
+ keyHint: null,
85
+ label: jsx_runtime_1.jsx("span", { style: menuLabel, children: fileManagerName }),
86
+ leftItem: jsx_runtime_1.jsx(finder_1.FinderIcon, { size: 18 }),
87
+ onClick: () => {
88
+ if (!fileManagerDisabled) {
89
+ onOpenInFileExplorer();
90
+ }
91
+ },
92
+ quickSwitcherLabel: null,
93
+ subMenu: null,
94
+ type: 'item',
95
+ value: 'file-explorer',
96
+ }
97
+ : null,
98
+ ].filter(no_react_1.NoReactInternals.truthy);
99
+ const hasCategorizedApps = editors.length > 0 ||
100
+ codingAgents.length > 0 ||
101
+ terminals.length > 0 ||
102
+ gitClients.length > 0;
53
103
  return [
54
104
  ...(editors.length > 0
55
105
  ? [
@@ -71,61 +121,60 @@ const getOpenInMenuItems = ({ codingAgentInfo, editorDisabled, editorInfo, exclu
71
121
  ...codingAgents,
72
122
  ]
73
123
  : []),
74
- ...(showSystemApps
124
+ ...(terminals.length > 0
75
125
  ? [
76
- ...(terminals.length > 0
77
- ? [
78
- {
79
- type: 'section-header',
80
- id: 'terminal-header',
81
- label: 'Terminal',
82
- },
83
- ...terminals.map((terminal) => ({
84
- id: `open-in-terminal-${terminal.id}`,
85
- keyHint: null,
86
- label: jsx_runtime_1.jsx("span", { style: menuLabel, children: terminal.name }),
87
- leftItem: jsx_runtime_1.jsx(terminal_1.TerminalIcon, { terminalId: terminal.id, size: 18 }),
88
- onClick: () => onOpenInTerminal === null || onOpenInTerminal === void 0 ? void 0 : onOpenInTerminal(terminal.id),
89
- quickSwitcherLabel: null,
90
- subMenu: null,
91
- type: 'item',
92
- value: `terminal-${terminal.id}`,
93
- })),
94
- ]
95
- : []),
96
- ...(showFinder
126
+ {
127
+ type: 'section-header',
128
+ id: 'terminal-header',
129
+ label: 'Terminal',
130
+ },
131
+ ...terminals.map((terminal) => ({
132
+ id: `open-in-terminal-${terminal.id}`,
133
+ keyHint: null,
134
+ label: jsx_runtime_1.jsx("span", { style: menuLabel, children: terminal.name }),
135
+ leftItem: jsx_runtime_1.jsx(terminal_1.TerminalIcon, { terminalId: terminal.id, size: 18 }),
136
+ onClick: () => onOpenInTerminal === null || onOpenInTerminal === void 0 ? void 0 : onOpenInTerminal(terminal.id),
137
+ quickSwitcherLabel: null,
138
+ subMenu: null,
139
+ type: 'item',
140
+ value: `terminal-${terminal.id}`,
141
+ })),
142
+ ]
143
+ : []),
144
+ ...(gitClients.length > 0
145
+ ? [
146
+ {
147
+ type: 'section-header',
148
+ id: 'git-client-header',
149
+ label: 'Git Client',
150
+ },
151
+ ...gitClients.map((gitClient) => ({
152
+ id: `open-in-git-client-${gitClient.id}`,
153
+ keyHint: null,
154
+ label: jsx_runtime_1.jsx("span", { style: menuLabel, children: gitClient.name }),
155
+ leftItem: jsx_runtime_1.jsx(git_client_1.GitClientIcon, { gitClientId: gitClient.id, size: 18 }),
156
+ onClick: () => onOpenInGitClient(gitClient.id),
157
+ quickSwitcherLabel: null,
158
+ subMenu: null,
159
+ type: 'item',
160
+ value: `git-client-${gitClient.id}`,
161
+ })),
162
+ ]
163
+ : []),
164
+ ...(systemApps.length > 0
165
+ ? [
166
+ ...(hasCategorizedApps
97
167
  ? [
98
- ...(editors.length > 0 ||
99
- codingAgents.length > 0 ||
100
- terminals.length > 0
101
- ? [
102
- {
103
- type: 'divider',
104
- id: 'open-in-file-explorer-divider',
105
- },
106
- ]
107
- : []),
108
168
  {
109
- disabled: fileManagerDisabled,
110
- id: 'open-in-file-explorer',
111
- keyHint: null,
112
- label: jsx_runtime_1.jsx("span", { style: menuLabel, children: fileManagerName }),
113
- leftItem: jsx_runtime_1.jsx(finder_1.FinderIcon, { size: 18 }),
114
- onClick: () => {
115
- if (!fileManagerDisabled) {
116
- onOpenInFileExplorer();
117
- }
118
- },
119
- quickSwitcherLabel: null,
120
- subMenu: null,
121
- type: 'item',
122
- value: 'file-explorer',
169
+ type: 'divider',
170
+ id: 'open-in-system-apps-divider',
123
171
  },
124
172
  ]
125
173
  : []),
174
+ ...systemApps,
126
175
  ]
127
176
  : []),
128
- ...(editors.length > 0 || codingAgents.length > 0 || showSystemApps
177
+ ...(hasCategorizedApps || systemApps.length > 0
129
178
  ? [{ type: 'divider', id: 'open-in-settings-divider' }]
130
179
  : []),
131
180
  {
@@ -7,6 +7,7 @@ const no_react_1 = require("remotion/no-react");
7
7
  const get_static_files_1 = require("../api/get-static-files");
8
8
  const write_static_file_1 = require("../api/write-static-file");
9
9
  const clipboard_figma_1 = require("../helpers/clipboard-figma");
10
+ const inserted_element_selection_1 = require("../helpers/inserted-element-selection");
10
11
  const install_required_package_1 = require("../helpers/install-required-package");
11
12
  const use_media_metadata_1 = require("../helpers/use-media-metadata");
12
13
  const call_api_1 = require("./call-api");
@@ -504,6 +505,12 @@ const insertCompositionElement = async ({ compositionFile, compositionId, elemen
504
505
  (0, NotificationCenter_1.showNotification)(result.reason, 4000);
505
506
  return false;
506
507
  }
508
+ if (result.insertedNodePath !== null) {
509
+ (0, inserted_element_selection_1.requestInsertedElementSelection)({
510
+ compositionId,
511
+ nodePath: result.insertedNodePath,
512
+ });
513
+ }
507
514
  return true;
508
515
  };
509
516
  const downloadRemoteAsset = (url) => {
@@ -14,6 +14,7 @@ const getRootCompositionMenuItems = ({ connectionStatus, readOnlyStudio, setSele
14
14
  folderName: null,
15
15
  parentName: null,
16
16
  stack: null,
17
+ canvasCapture: null,
17
18
  });
18
19
  },
19
20
  quickSwitcherLabel: 'New composition...',
@@ -0,0 +1,14 @@
1
+ import type { OutlinePoint } from './selected-outline-geometry';
2
+ export type SelectedOutlineControlCorner = 'top-left' | 'top-right' | 'bottom-right' | 'bottom-left';
3
+ export declare const getSelectedOutlineControlLayout: (points: readonly [OutlinePoint, OutlinePoint, OutlinePoint, OutlinePoint]) => {
4
+ rotationCorners: {
5
+ corner: "bottom-left" | "bottom-right" | "top-left" | "top-right";
6
+ point: OutlinePoint;
7
+ }[];
8
+ rotationHandleRadius: number;
9
+ scaleEdges: ("bottom" | "left" | "right" | "top")[];
10
+ scaleHitWidth: {
11
+ horizontal: number;
12
+ vertical: number;
13
+ };
14
+ };
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSelectedOutlineControlLayout = void 0;
4
+ // Outline points are measured in overlay pixels, keeping these sizes independent of canvas zoom.
5
+ const handleSize = 8;
6
+ const targetHalfSize = 4.5;
7
+ const smallOutlineSize = handleSize * 4;
8
+ const tinyOutlineSize = handleSize * 2;
9
+ const distance = (from, to) => Math.hypot(to.x - from.x, to.y - from.y);
10
+ const normalize = (point) => {
11
+ const length = Math.hypot(point.x, point.y);
12
+ if (length < 0.001) {
13
+ return null;
14
+ }
15
+ return { x: point.x / length, y: point.y / length };
16
+ };
17
+ const getRotationHandlePoint = ({ corner, points, radius, }) => {
18
+ const [topLeft, topRight, bottomRight, bottomLeft] = points;
19
+ const { point, adjacent } = {
20
+ 'top-left': { point: topLeft, adjacent: [topRight, bottomLeft] },
21
+ 'top-right': { point: topRight, adjacent: [topLeft, bottomRight] },
22
+ 'bottom-right': { point: bottomRight, adjacent: [topRight, bottomLeft] },
23
+ 'bottom-left': { point: bottomLeft, adjacent: [topLeft, bottomRight] },
24
+ }[corner];
25
+ const firstDirection = normalize({
26
+ x: point.x - adjacent[0].x,
27
+ y: point.y - adjacent[0].y,
28
+ });
29
+ const secondDirection = normalize({
30
+ x: point.x - adjacent[1].x,
31
+ y: point.y - adjacent[1].y,
32
+ });
33
+ const outlineCenter = {
34
+ x: (topLeft.x + topRight.x + bottomRight.x + bottomLeft.x) / 4,
35
+ y: (topLeft.y + topRight.y + bottomRight.y + bottomLeft.y) / 4,
36
+ };
37
+ const fallbackDirection = normalize({
38
+ x: point.x - outlineCenter.x,
39
+ y: point.y - outlineCenter.y,
40
+ });
41
+ const direction = firstDirection === null || secondDirection === null
42
+ ? fallbackDirection
43
+ : normalize({
44
+ x: firstDirection.x + secondDirection.x,
45
+ y: firstDirection.y + secondDirection.y,
46
+ });
47
+ if (direction === null) {
48
+ return point;
49
+ }
50
+ return {
51
+ x: point.x + direction.x * radius,
52
+ y: point.y + direction.y * radius,
53
+ };
54
+ };
55
+ const getSelectedOutlineControlLayout = (points) => {
56
+ const [topLeft, topRight, bottomRight, bottomLeft] = points;
57
+ const horizontalExtent = (distance(topLeft, topRight) + distance(bottomLeft, bottomRight)) / 2;
58
+ const verticalExtent = (distance(topLeft, bottomLeft) + distance(topRight, bottomRight)) / 2;
59
+ const isSmallX = horizontalExtent < smallOutlineSize;
60
+ const isSmallY = verticalExtent < smallOutlineSize;
61
+ const isTinyX = horizontalExtent < tinyOutlineSize;
62
+ const isTinyY = verticalExtent < tinyOutlineSize;
63
+ const targetHalfSizeX = isSmallX ? targetHalfSize / 2 : targetHalfSize;
64
+ const targetHalfSizeY = isSmallY ? targetHalfSize / 2 : targetHalfSize;
65
+ const rotationHandleRadius = Math.max(targetHalfSizeX, targetHalfSizeY) * 1.5;
66
+ const scaleEdges = ['top', 'right', 'bottom', 'left'].filter((edge) => {
67
+ // Preserve one scale control per axis when opposite edge targets would overlap.
68
+ if (edge === 'top') {
69
+ return !isTinyY;
70
+ }
71
+ if (edge === 'left') {
72
+ return !isTinyX;
73
+ }
74
+ return true;
75
+ });
76
+ const rotationCorners = ['top-left', 'top-right', 'bottom-right', 'bottom-left'].map((corner) => ({
77
+ corner,
78
+ point: getRotationHandlePoint({
79
+ corner,
80
+ points,
81
+ radius: rotationHandleRadius,
82
+ }),
83
+ }));
84
+ return {
85
+ rotationCorners: isTinyX || isTinyY ? [] : rotationCorners,
86
+ rotationHandleRadius,
87
+ scaleEdges,
88
+ scaleHitWidth: {
89
+ horizontal: targetHalfSizeY * 2,
90
+ vertical: targetHalfSizeX * 2,
91
+ },
92
+ };
93
+ };
94
+ exports.getSelectedOutlineControlLayout = getSelectedOutlineControlLayout;
@@ -9,10 +9,35 @@ const canUseEditorPicker = (previewServerConnected) => {
9
9
  (0, browser_studio_operations_1.getBrowserStudioOperations)() === null);
10
10
  };
11
11
  exports.canUseEditorPicker = canUseEditorPicker;
12
+ const preferredFallbackEditorIds = [
13
+ 'zed',
14
+ 'vscode',
15
+ 'cursor',
16
+ ];
12
17
  const getPreferredEditorId = (editorInfo) => {
13
- var _a;
14
- var _b;
15
- return ((_b = (_a = editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors.find((editor) => editor.nameWithType === window.remotion_editorName)) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : null);
18
+ var _a, _b, _c;
19
+ var _d;
20
+ const runningEditorId = (_a = editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors.find((editor) => editor.nameWithType === window.remotion_editorName)) === null || _a === void 0 ? void 0 : _a.id;
21
+ if (runningEditorId) {
22
+ return runningEditorId;
23
+ }
24
+ if (window.remotion_editorName !== null) {
25
+ return null;
26
+ }
27
+ const configuredEditorId = (_b = editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors.find((editor) => editor.id === editorInfo.defaultEditor)) === null || _b === void 0 ? void 0 : _b.id;
28
+ if (configuredEditorId) {
29
+ return configuredEditorId;
30
+ }
31
+ return ((_d = (_c = editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors.slice().sort((a, b) => {
32
+ const aPriority = preferredFallbackEditorIds.indexOf(a.id);
33
+ const bPriority = preferredFallbackEditorIds.indexOf(b.id);
34
+ const normalizedAPriority = aPriority === -1 ? Number.POSITIVE_INFINITY : aPriority;
35
+ const normalizedBPriority = bPriority === -1 ? Number.POSITIVE_INFINITY : bPriority;
36
+ if (normalizedAPriority !== normalizedBPriority) {
37
+ return normalizedAPriority - normalizedBPriority;
38
+ }
39
+ return a.nameWithType.localeCompare(b.nameWithType);
40
+ }).at(0)) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : null);
16
41
  };
17
42
  exports.getPreferredEditorId = getPreferredEditorId;
18
43
  const useDefaultEditorInfo = (enabled) => {