@remotion/studio 4.0.502 → 4.0.503

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 (121) hide show
  1. package/dist/components/AssetSelectorItem.js +2 -2
  2. package/dist/components/Canvas.js +34 -54
  3. package/dist/components/ColorPicker/AlphaSlider.js +14 -10
  4. package/dist/components/ColorPicker/HueSlider.js +14 -10
  5. package/dist/components/ColorPicker/SaturationValueArea.js +14 -12
  6. package/dist/components/CompositionContextButton.js +1 -1
  7. package/dist/components/ConfigureDefaultEditorModal.d.ts +2 -0
  8. package/dist/components/ConfigureDefaultEditorModal.js +151 -0
  9. package/dist/components/ConfirmationDialog.js +6 -3
  10. package/dist/components/ContextMenu.js +0 -2
  11. package/dist/components/Editor.js +1 -4
  12. package/dist/components/EditorGuides/Guide.js +48 -74
  13. package/dist/components/EditorRuler/Ruler.d.ts +1 -0
  14. package/dist/components/EditorRuler/Ruler.js +3 -1
  15. package/dist/components/EditorRuler/index.js +26 -23
  16. package/dist/components/ElementInstallConfirmation.d.ts +12 -0
  17. package/dist/components/ElementInstallConfirmation.js +205 -0
  18. package/dist/components/ForceSpecificCursor.js +14 -0
  19. package/dist/components/InlineAction.d.ts +2 -1
  20. package/dist/components/InlineAction.js +3 -3
  21. package/dist/components/InspectorLocationCopy.d.ts +1 -0
  22. package/dist/components/InspectorLocationCopy.js +7 -3
  23. package/dist/components/InspectorOpenInEditor.d.ts +5 -0
  24. package/dist/components/InspectorOpenInEditor.js +135 -0
  25. package/dist/components/InspectorPanel/AlignmentControls.js +1 -1
  26. package/dist/components/InspectorPanel/CompositionInspectorHeader.js +3 -3
  27. package/dist/components/InspectorPanel/CompositionMetadata.js +1 -1
  28. package/dist/components/InspectorPanel/KeyframeEasingNavigator.js +2 -2
  29. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +2 -2
  30. package/dist/components/InspectorSequenceSection.js +2 -2
  31. package/dist/components/Menu/MenuItem.js +13 -6
  32. package/dist/components/Menu/MenuSubItem.js +3 -1
  33. package/dist/components/MenuBuildIndicator.js +1 -1
  34. package/dist/components/MenuCompositionName.js +1 -1
  35. package/dist/components/MobilePanel.js +5 -1
  36. package/dist/components/ModalContainer.js +1 -1
  37. package/dist/components/ModalFooter.d.ts +1 -0
  38. package/dist/components/ModalFooter.js +2 -2
  39. package/dist/components/Modals.js +11 -2
  40. package/dist/components/NewComposition/InputDragger.js +19 -29
  41. package/dist/components/PreviewToolbarOverflowButton.js +1 -1
  42. package/dist/components/RenderModal/InlineEyeIcon.js +1 -1
  43. package/dist/components/RenderModal/InlineRemoveButton.js +1 -1
  44. package/dist/components/RenderModal/RenderModalOutputName.js +1 -1
  45. package/dist/components/RenderModal/SchemaEditor/SchemaResetButton.js +1 -1
  46. package/dist/components/RenderQueue/RenderQueueCopyToClipboard.js +1 -1
  47. package/dist/components/RenderQueue/RenderQueueDownloadItem.js +1 -1
  48. package/dist/components/RenderQueue/RenderQueueItemCancelButton.js +1 -1
  49. package/dist/components/RenderQueue/RenderQueueOpenInFolder.js +1 -1
  50. package/dist/components/RenderQueue/RenderQueueRemoveItem.js +1 -1
  51. package/dist/components/RenderQueue/RenderQueueRepeat.js +1 -1
  52. package/dist/components/SelectedOutlineCropControls.js +7 -6
  53. package/dist/components/SelectedOutlineElement.js +28 -26
  54. package/dist/components/SelectedOutlineUvControls.js +25 -24
  55. package/dist/components/ShowGuidesProvider.js +2 -0
  56. package/dist/components/SidebarCollapserControls.js +2 -2
  57. package/dist/components/SidebarRenderButton.js +1 -1
  58. package/dist/components/Splitter/SplitterHandle.js +17 -68
  59. package/dist/components/Timeline/EasingEditorModal.js +27 -19
  60. package/dist/components/Timeline/TimelineAssetField.js +1 -1
  61. package/dist/components/Timeline/TimelineDragHandler.js +38 -7
  62. package/dist/components/Timeline/TimelineInOutDragHandler.js +26 -11
  63. package/dist/components/Timeline/TimelineLayerEye.js +36 -4
  64. package/dist/components/Timeline/TimelineSelection.js +14 -21
  65. package/dist/components/Timeline/TimelineSequence.js +7 -3
  66. package/dist/components/Timeline/TimelineSequenceItem.js +24 -18
  67. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +1 -1
  68. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +76 -43
  69. package/dist/components/Timeline/TimelineStack/get-stack.js +7 -2
  70. package/dist/components/Timeline/get-sequence-context-menu-items.d.ts +4 -2
  71. package/dist/components/Timeline/get-sequence-context-menu-items.js +38 -2
  72. package/dist/components/Timeline/should-subscribe-to-source-file.d.ts +1 -0
  73. package/dist/components/Timeline/should-subscribe-to-source-file.js +11 -0
  74. package/dist/components/Timeline/use-open-sequence-in-editor.d.ts +3 -1
  75. package/dist/components/Timeline/use-open-sequence-in-editor.js +5 -2
  76. package/dist/components/Timeline/use-sequence-props-subscription.js +2 -0
  77. package/dist/components/Timeline/use-timeline-asset-drop.js +0 -4
  78. package/dist/components/Timeline/use-timeline-keyframe-drag.js +31 -16
  79. package/dist/components/UndoRedoButtons.js +1 -1
  80. package/dist/components/UpdateCheck.d.ts +2 -0
  81. package/dist/components/UpdateCheck.js +12 -7
  82. package/dist/components/UpdateModal/UpdateModal.js +26 -10
  83. package/dist/components/VisualControls/ClickableFileName.js +5 -2
  84. package/dist/components/composition-menu-items.js +1 -1
  85. package/dist/components/element-install-request.d.ts +3 -0
  86. package/dist/components/element-install-request.js +17 -0
  87. package/dist/components/folder-menu-items.js +1 -1
  88. package/dist/components/handle-drop.d.ts +2 -3
  89. package/dist/components/handle-drop.js +11 -4
  90. package/dist/components/import-assets.d.ts +5 -5
  91. package/dist/components/import-assets.js +4 -15
  92. package/dist/components/use-default-editor-info.d.ts +4 -0
  93. package/dist/components/use-default-editor-info.js +47 -0
  94. package/dist/error-overlay/remotion-overlay/OpenInEditor.js +1 -1
  95. package/dist/error-overlay/remotion-overlay/StackFrame.js +1 -1
  96. package/dist/esm/{chunk-fjv75ty4.js → chunk-bj1r1hh5.js} +7068 -6120
  97. package/dist/esm/internals.mjs +7068 -6120
  98. package/dist/esm/previewEntry.mjs +7077 -6129
  99. package/dist/esm/renderEntry.mjs +1 -1
  100. package/dist/helpers/inject-css.js +18 -44
  101. package/dist/helpers/open-in-editor.d.ts +3 -3
  102. package/dist/helpers/open-in-editor.js +10 -6
  103. package/dist/helpers/pointer-session.d.ts +9 -0
  104. package/dist/helpers/pointer-session.js +94 -0
  105. package/dist/helpers/use-menu-structure.js +24 -2
  106. package/dist/icons/custom-editor.d.ts +4 -0
  107. package/dist/icons/custom-editor.js +11 -0
  108. package/dist/icons/editor.d.ts +6 -0
  109. package/dist/icons/editor.js +52 -0
  110. package/dist/state/editor-guides.d.ts +1 -0
  111. package/dist/state/editor-guides.js +1 -0
  112. package/dist/state/modals.d.ts +2 -0
  113. package/dist/state/z-index.d.ts +1 -0
  114. package/dist/state/z-index.js +34 -18
  115. package/package.json +12 -13
  116. package/dist/components/StudioCanvasCapture.d.ts +0 -5
  117. package/dist/components/StudioCanvasCapture.js +0 -40
  118. package/dist/components/canvas-capture-enabled.d.ts +0 -1
  119. package/dist/components/canvas-capture-enabled.js +0 -4
  120. package/dist/components/use-element-overwrite-confirmation.d.ts +0 -2
  121. package/dist/components/use-element-overwrite-confirmation.js +0 -73
@@ -212,7 +212,7 @@ var renderContent = (Root) => {
212
212
  renderToDOM(/* @__PURE__ */ jsx("div", {
213
213
  children: /* @__PURE__ */ jsx(DelayedSpinner, {})
214
214
  }));
215
- import("./chunk-fjv75ty4.js").then(({ StudioInternals }) => {
215
+ import("./chunk-bj1r1hh5.js").then(({ StudioInternals }) => {
216
216
  window.remotion_isStudio = true;
217
217
  window.remotion_isReadOnlyStudio = true;
218
218
  window.remotion_inputProps = "{}";
@@ -5,10 +5,8 @@ const remotion_1 = require("remotion");
5
5
  const scroll_to_default_props_path_1 = require("../components/RenderModal/SchemaEditor/scroll-to-default-props-path");
6
6
  const colors_1 = require("./colors");
7
7
  const makeDefaultGlobalCSS = () => {
8
- const unhoveredDragAreaFactor = 2;
9
- const fromMiddle = 50 / unhoveredDragAreaFactor;
10
- const hoveredDragAreaFactor = 6;
11
- const fromMiddleHovered = 50 / hoveredDragAreaFactor;
8
+ const dragAreaFactor = 2;
9
+ const fromMiddle = 50 / dragAreaFactor;
12
10
  return `
13
11
  html {
14
12
  --remotion-cli-internals-blue: ${colors_1.BLUE};
@@ -28,51 +26,27 @@ const makeDefaultGlobalCSS = () => {
28
26
  }
29
27
 
30
28
  .remotion-splitter-horizontal {
31
- transform: scaleY(${unhoveredDragAreaFactor});
32
- background: linear-gradient(
33
- to bottom,
34
- ${colors_1.TRANSPARENT} ${50 - fromMiddle}%,
35
- ${colors_1.BLACK} ${50 - fromMiddle}%,
36
- ${colors_1.BLACK} ${50 + fromMiddle}%,
37
- ${colors_1.TRANSPARENT} ${50 + fromMiddle}%
38
- );
39
- }
40
-
41
- .remotion-splitter-horizontal.remotion-splitter-active, .remotion-splitter-horizontal.remotion-splitter-hover {
42
- background: linear-gradient(
43
- to bottom,
44
- ${colors_1.TRANSPARENT} ${50 - fromMiddleHovered}%,
45
- var(--remotion-cli-internals-blue) ${50 - fromMiddleHovered}%,
46
- var(--remotion-cli-internals-blue) ${50 + fromMiddleHovered}%,
47
- ${colors_1.TRANSPARENT} ${50 + fromMiddleHovered}%
48
- );
49
29
  cursor: row-resize;
50
- transform: scaleY(${hoveredDragAreaFactor});
51
- z-index: 1000;
30
+ transform: scaleY(${dragAreaFactor});
31
+ background: linear-gradient(
32
+ to bottom,
33
+ ${colors_1.TRANSPARENT} ${50 - fromMiddle}%,
34
+ ${colors_1.BLACK} ${50 - fromMiddle}%,
35
+ ${colors_1.BLACK} ${50 + fromMiddle}%,
36
+ ${colors_1.TRANSPARENT} ${50 + fromMiddle}%
37
+ );
52
38
  }
53
39
 
54
40
  .remotion-splitter-vertical {
55
- transform: scaleX(${unhoveredDragAreaFactor});
56
- background: linear-gradient(
57
- to right,
58
- ${colors_1.TRANSPARENT} ${50 - fromMiddle}%,
59
- ${colors_1.BLACK} ${50 - fromMiddle}%,
60
- ${colors_1.BLACK} ${50 + fromMiddle}%,
61
- ${colors_1.TRANSPARENT} ${50 + fromMiddle}%
62
- );
63
- }
64
-
65
- .remotion-splitter-vertical.remotion-splitter-active, .remotion-splitter-vertical.remotion-splitter-hover {
66
- background: linear-gradient(
67
- to right,
68
- ${colors_1.TRANSPARENT} ${50 - fromMiddleHovered}%,
69
- var(--remotion-cli-internals-blue) ${50 - fromMiddleHovered}%,
70
- var(--remotion-cli-internals-blue) ${50 + fromMiddleHovered}%,
71
- ${colors_1.TRANSPARENT} ${50 + fromMiddleHovered}%
72
- );
73
- transform: scaleX(${hoveredDragAreaFactor});
74
41
  cursor: col-resize;
75
- z-index: 1000;
42
+ transform: scaleX(${dragAreaFactor});
43
+ background: linear-gradient(
44
+ to right,
45
+ ${colors_1.TRANSPARENT} ${50 - fromMiddle}%,
46
+ ${colors_1.BLACK} ${50 - fromMiddle}%,
47
+ ${colors_1.BLACK} ${50 + fromMiddle}%,
48
+ ${colors_1.TRANSPARENT} ${50 + fromMiddle}%
49
+ );
76
50
  }
77
51
 
78
52
  input::-webkit-outer-spin-button,
@@ -1,7 +1,7 @@
1
- import type { CompositionComponentInfoResponse, SymbolicatedStackFrame } from '@remotion/studio-shared';
1
+ import type { CompositionComponentInfoResponse, EditorPickerId, SymbolicatedStackFrame } from '@remotion/studio-shared';
2
2
  import type { CodePosition, OriginalPosition } from '../error-overlay/react-overlay/utils/get-source-map';
3
- export declare const openInEditor: (stack: SymbolicatedStackFrame) => Promise<import("@remotion/studio-shared").OpenInEditorResponse>;
4
- export declare const openOriginalPositionInEditor: (originalPosition: OriginalPosition) => Promise<void>;
3
+ export declare const openInEditor: (stack: SymbolicatedStackFrame, editorId: EditorPickerId | null) => Promise<import("@remotion/studio-shared").OpenInEditorResponse>;
4
+ export declare const openOriginalPositionInEditor: (originalPosition: OriginalPosition, editorId: EditorPickerId | null) => Promise<void>;
5
5
  export declare const openOriginalPositionInEditorAtProperty: ({ originalPosition, property, }: {
6
6
  originalPosition: CodePosition;
7
7
  property: string;
@@ -4,9 +4,10 @@ exports.openCompositionComponentInEditor = exports.preloadCompositionComponentIn
4
4
  const react_1 = require("react");
5
5
  const call_api_1 = require("../components/call-api");
6
6
  const browser_studio_operations_1 = require("./browser-studio-operations");
7
- const openInEditor = (stack) => {
7
+ const openInEditor = (stack, editorId) => {
8
8
  const { originalFileName, originalLineNumber, originalColumnNumber, originalFunctionName, originalScriptCode, } = stack;
9
9
  return (0, call_api_1.callApi)('/api/open-in-editor', {
10
+ editorId,
10
11
  stack: {
11
12
  originalFileName,
12
13
  originalLineNumber,
@@ -17,14 +18,17 @@ const openInEditor = (stack) => {
17
18
  });
18
19
  };
19
20
  exports.openInEditor = openInEditor;
20
- const openOriginalPositionInEditor = async (originalPosition) => {
21
- await (0, exports.openInEditor)({
21
+ const openOriginalPositionInEditor = async (originalPosition, editorId) => {
22
+ const response = await (0, exports.openInEditor)({
22
23
  originalColumnNumber: originalPosition.column,
23
24
  originalFileName: originalPosition.source,
24
25
  originalFunctionName: null,
25
26
  originalLineNumber: originalPosition.line,
26
27
  originalScriptCode: null,
27
- });
28
+ }, editorId);
29
+ if (!response.success) {
30
+ throw new Error('Could not open the file in the editor.');
31
+ }
28
32
  };
29
33
  exports.openOriginalPositionInEditor = openOriginalPositionInEditor;
30
34
  const openOriginalPositionInEditorAtProperty = async ({ originalPosition, property, }) => {
@@ -42,7 +46,7 @@ const openOriginalPositionInEditorAtProperty = async ({ originalPosition, proper
42
46
  source: originalPosition.source,
43
47
  line: position.lineNumber,
44
48
  column: position.columnNumber,
45
- });
49
+ }, null);
46
50
  };
47
51
  exports.openOriginalPositionInEditorAtProperty = openOriginalPositionInEditorAtProperty;
48
52
  const componentResolutionCache = new Map();
@@ -142,6 +146,6 @@ const openCompositionComponentInEditor = async ({ compositionFile, compositionId
142
146
  compositionFile,
143
147
  compositionId,
144
148
  });
145
- await (0, exports.openOriginalPositionInEditor)(info.location);
149
+ await (0, exports.openOriginalPositionInEditor)(info.location, null);
146
150
  };
147
151
  exports.openCompositionComponentInEditor = openCompositionComponentInEditor;
@@ -0,0 +1,9 @@
1
+ export type PointerSessionEndReason = 'pointerup' | 'pointercancel' | 'lostpointercapture' | 'blur' | 'visibilitychange' | 'buttons-released' | 'manual';
2
+ type PointerSessionEvent = Pick<PointerEvent, 'button' | 'pointerId'>;
3
+ export declare const startPointerSession: ({ event, target, onMove, onEnd, }: {
4
+ event: PointerSessionEvent;
5
+ target: Element;
6
+ onMove?: ((event: PointerEvent) => void) | undefined;
7
+ onEnd: (reason: PointerSessionEndReason, event: PointerEvent | null) => void;
8
+ }) => () => void;
9
+ export {};
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startPointerSession = void 0;
4
+ const getButtonMask = (button) => {
5
+ if (button === 0) {
6
+ return 1;
7
+ }
8
+ if (button === 1) {
9
+ return 4;
10
+ }
11
+ if (button === 2) {
12
+ return 2;
13
+ }
14
+ return 1 << button;
15
+ };
16
+ const startPointerSession = ({ event, target, onMove, onEnd, }) => {
17
+ var _a;
18
+ const { pointerId } = event;
19
+ const buttonMask = getButtonMask(event.button);
20
+ let ended = false;
21
+ const cleanup = () => {
22
+ var _a;
23
+ window.removeEventListener('pointermove', handleMove);
24
+ window.removeEventListener('pointerup', handleUp);
25
+ window.removeEventListener('pointercancel', handleCancel);
26
+ window.removeEventListener('blur', handleBlur);
27
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
28
+ target.removeEventListener('lostpointercapture', handleLostPointerCapture);
29
+ if ((_a = target.hasPointerCapture) === null || _a === void 0 ? void 0 : _a.call(target, pointerId)) {
30
+ try {
31
+ target.releasePointerCapture(pointerId);
32
+ }
33
+ catch (_b) {
34
+ // The browser may already have released capture.
35
+ }
36
+ }
37
+ };
38
+ const end = (reason, pointerEvent) => {
39
+ if (ended) {
40
+ return;
41
+ }
42
+ ended = true;
43
+ cleanup();
44
+ onEnd(reason, pointerEvent);
45
+ };
46
+ function handleMove(moveEvent) {
47
+ if (moveEvent.pointerId !== pointerId) {
48
+ return;
49
+ }
50
+ if ((moveEvent.buttons & buttonMask) === 0) {
51
+ end('buttons-released', moveEvent);
52
+ return;
53
+ }
54
+ onMove === null || onMove === void 0 ? void 0 : onMove(moveEvent);
55
+ }
56
+ function handleUp(upEvent) {
57
+ if (upEvent.pointerId === pointerId) {
58
+ end('pointerup', upEvent);
59
+ }
60
+ }
61
+ function handleCancel(cancelEvent) {
62
+ if (cancelEvent.pointerId === pointerId) {
63
+ end('pointercancel', cancelEvent);
64
+ }
65
+ }
66
+ function handleLostPointerCapture(lostEvent) {
67
+ const pointerEvent = lostEvent;
68
+ if (pointerEvent.pointerId === pointerId) {
69
+ end('lostpointercapture', pointerEvent);
70
+ }
71
+ }
72
+ function handleBlur() {
73
+ end('blur', null);
74
+ }
75
+ function handleVisibilityChange() {
76
+ if (document.visibilityState === 'hidden') {
77
+ end('visibilitychange', null);
78
+ }
79
+ }
80
+ try {
81
+ (_a = target.setPointerCapture) === null || _a === void 0 ? void 0 : _a.call(target, pointerId);
82
+ }
83
+ catch (_b) {
84
+ // Capture is best-effort for detached or browser-owned targets.
85
+ }
86
+ window.addEventListener('pointermove', handleMove);
87
+ window.addEventListener('pointerup', handleUp);
88
+ window.addEventListener('pointercancel', handleCancel);
89
+ window.addEventListener('blur', handleBlur);
90
+ document.addEventListener('visibilitychange', handleVisibilityChange);
91
+ target.addEventListener('lostpointercapture', handleLostPointerCapture);
92
+ return () => end('manual', null);
93
+ };
94
+ exports.startPointerSession = startPointerSession;
@@ -177,7 +177,7 @@ const getFileMenu = ({ readOnlyStudio, closeMenu, previewServerState, setSelecte
177
177
  originalColumnNumber: 1,
178
178
  originalFunctionName: null,
179
179
  originalScriptCode: null,
180
- })
180
+ }, null)
181
181
  .then(({ success }) => {
182
182
  if (!success) {
183
183
  (0, NotificationCenter_1.showNotification)(`Could not open ${window.remotion_editorName}`, 2000);
@@ -240,6 +240,9 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
240
240
  const { size, setSize } = (0, react_1.useContext)(remotion_1.Internals.PreviewSizeContext);
241
241
  const { canvasContent, compositions } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
242
242
  const { type } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx).previewServerState;
243
+ const canConfigureDefaultEditor = !readOnlyStudio &&
244
+ type === 'connected' &&
245
+ (0, browser_studio_operations_1.getBrowserStudioOperations)() === null;
243
246
  const { setSidebarCollapsedState, sidebarCollapsedStateLeft, sidebarCollapsedStateRight, } = (0, react_1.useContext)(sidebar_1.SidebarContext);
244
247
  const sizes = (0, react_1.useMemo)(() => (0, SizeSelector_1.getUniqueSizes)(size), [size]);
245
248
  const isFullscreenSupported = (0, check_fullscreen_support_1.checkFullscreenSupport)();
@@ -300,6 +303,24 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
300
303
  subMenu: null,
301
304
  quickSwitcherLabel: 'Help: Changelog',
302
305
  },
306
+ canConfigureDefaultEditor
307
+ ? {
308
+ id: 'default-editor',
309
+ value: 'default-editor',
310
+ label: 'Configure default editor...',
311
+ onClick: () => {
312
+ closeMenu();
313
+ setSelectedModal({
314
+ type: 'configure-default-editor',
315
+ });
316
+ },
317
+ type: 'item',
318
+ keyHint: null,
319
+ leftItem: null,
320
+ subMenu: null,
321
+ quickSwitcherLabel: 'Configure default editor...',
322
+ }
323
+ : null,
303
324
  {
304
325
  id: 'license',
305
326
  value: 'license',
@@ -352,7 +373,7 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
352
373
  subMenu: null,
353
374
  quickSwitcherLabel: 'Restart Studio Server',
354
375
  },
355
- ],
376
+ ].filter(no_react_1.NoReactInternals.truthy),
356
377
  quickSwitcherLabel: null,
357
378
  },
358
379
  getFileMenu({
@@ -957,6 +978,7 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
957
978
  }
958
979
  return struct;
959
980
  }, [
981
+ canConfigureDefaultEditor,
960
982
  readOnlyStudio,
961
983
  closeMenu,
962
984
  type,
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const CustomEditorIcon: React.FC<{
3
+ readonly size: number | null;
4
+ }>;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CustomEditorIcon = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const colors_1 = require("../helpers/colors");
6
+ const CustomEditorIcon = ({ size: sizeProp, }) => (jsx_runtime_1.jsx("svg", { focusable: "false", role: "img", viewBox: "0 0 24 24", style: {
7
+ width: sizeProp !== null && sizeProp !== void 0 ? sizeProp : 14,
8
+ height: sizeProp !== null && sizeProp !== void 0 ? sizeProp : 14,
9
+ flexShrink: 0,
10
+ }, children: jsx_runtime_1.jsx("path", { fill: "none", stroke: colors_1.CURRENT_COLOR, strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.8", d: "m8 8-4 4 4 4m8-8 4 4-4 4m-2-10-4 12" }) }));
11
+ exports.CustomEditorIcon = CustomEditorIcon;
@@ -0,0 +1,6 @@
1
+ import type { EditorPickerId } from '@remotion/studio-shared';
2
+ import React from 'react';
3
+ export declare const EditorIcon: React.FC<{
4
+ readonly editorId: EditorPickerId | null;
5
+ readonly size: number | null;
6
+ }>;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EditorIcon = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const colors_1 = require("../helpers/colors");
6
+ const custom_editor_1 = require("./custom-editor");
7
+ // Brand shapes adapted from:
8
+ // - OpenCode app icons (MIT): https://github.com/anomalyco/opencode/tree/dev/packages/ui/src/assets/icons/app
9
+ // - Simple Icons (CC0 1.0): https://github.com/simple-icons/simple-icons/tree/develop/icons
10
+ const iconStyle = (size) => ({
11
+ flexShrink: 0,
12
+ height: size,
13
+ width: size,
14
+ });
15
+ const VsCodeIcon = ({ size }) => (jsx_runtime_1.jsx("svg", { viewBox: "0 0 40 40", style: iconStyle(size), "aria-hidden": true, children: jsx_runtime_1.jsx("path", { fill: "#23A9F2", fillRule: "evenodd", clipRule: "evenodd", d: "M26.02 34.13c.23.09.48.13.72.12.25-.01.49-.07.71-.18l5.93-2.85c.31-.15.56-.38.74-.66.18-.29.28-.62.28-.96V10.25c0-.34-.1-.67-.28-.96-.18-.28-.43-.51-.74-.66l-5.93-2.85c-.34-.16-.71-.22-1.08-.15-.36.06-.7.23-.96.5L14.05 16.48 9.11 12.73a1.2 1.2 0 0 0-1.53.07L5.99 14.24a1.2 1.2 0 0 0 0 1.77l4.29 3.92-4.29 3.91a1.2 1.2 0 0 0 0 1.77l1.59 1.44a1.2 1.2 0 0 0 1.53.07l4.94-3.75 11.36 10.36c.17.17.38.31.61.4Zm1.18-20.74-8.61 6.54 8.61 6.53V13.39Z" }) }));
16
+ const CursorIcon = ({ size }) => (jsx_runtime_1.jsxs("svg", { viewBox: "0 0 40 40", style: iconStyle(size), "aria-hidden": true, children: [
17
+ jsx_runtime_1.jsx("rect", { x: "4", y: "4", width: "32", height: "32", rx: "7.625", fill: "#050505" }), jsx_runtime_1.jsx("path", { fill: "#fff", d: "m29.62 14.21-8.67-5.09a.89.89 0 0 0-.9 0l-8.67 5.09a.77.77 0 0 0-.38.66v10.26c0 .27.14.52.38.66l8.67 5.09c.28.16.62.16.9 0l8.67-5.09c.24-.14.38-.39.38-.66V14.87a.77.77 0 0 0-.38-.66Zm-.54 1.07L20.7 30.01a.11.11 0 0 1-.2-.06v-9.64c0-.19-.1-.37-.27-.47l-8.22-4.82a.11.11 0 0 1 .06-.21h16.74c.24 0 .39.27.27.47Z" })
18
+ ] }));
19
+ const WindsurfIcon = ({ size }) => (jsx_runtime_1.jsx("svg", { viewBox: "0 0 24 24", style: iconStyle(size), "aria-hidden": true, children: jsx_runtime_1.jsx("path", { fill: colors_1.CURRENT_COLOR, d: "M23.55 5.07a2.18 2.18 0 0 0-2.18 2.17v4.87c0 .97-.8 1.76-1.76 1.76-.57 0-1.14-.29-1.47-.77l-4.97-7.1a2.21 2.21 0 0 0-3.96 1.22v4.89c0 .97-.8 1.76-1.77 1.76-.57 0-1.13-.29-1.47-.77L.41 5.16A.22.22 0 0 0 0 5.29v4.24c0 .22.07.43.19.6l5.47 7.82c.33.46.8.81 1.35.93a2.15 2.15 0 0 0 2.65-2.1v-4.89c0-.97.79-1.76 1.76-1.76.57 0 1.14.29 1.47.77l4.98 7.1c.41.59 1.05.94 1.81.94a2.15 2.15 0 0 0 2.15-2.16v-4.89c0-.97.79-1.76 1.76-1.76h.19a.22.22 0 0 0 .22-.22V5.29a.22.22 0 0 0-.22-.22h-.23Z" }) }));
20
+ const ZedIcon = ({ size }) => (jsx_runtime_1.jsx("svg", { viewBox: "0 0 40 40", style: iconStyle(size), "aria-hidden": true, children: jsx_runtime_1.jsx("path", { fill: colors_1.CURRENT_COLOR, fillRule: "evenodd", clipRule: "evenodd", d: "M8.3 7.4a.9.9 0 0 0-.9.9v19.8H5.6V8.3a2.7 2.7 0 0 1 2.7-2.7h24.11c1.2 0 1.81 1.45.96 2.3L18.52 22.76h4.18V20.9h1.8v2.31c0 .75-.6 1.35-1.35 1.35h-6.43l-3.1 3.09h14.03V16.4h1.8v11.25c0 1-.8 1.8-1.8 1.8H11.82L8.67 32.6H31.7a.9.9 0 0 0 .9-.9V11.9h1.8v19.8a2.7 2.7 0 0 1-2.7 2.7H7.59c-1.2 0-1.81-1.45-.96-2.31L21.43 17.3H17.3v1.8h-1.8v-2.25c0-.75.6-1.35 1.35-1.35h6.38l3.15-3.15H12.35V23.6h-1.8V12.35c0-1 .8-1.8 1.8-1.8h15.83l3.15-3.15H8.3Z" }) }));
21
+ const VscodiumIcon = ({ size }) => (jsx_runtime_1.jsx("svg", { viewBox: "0 0 24 24", style: iconStyle(size), "aria-hidden": true, children: jsx_runtime_1.jsx("path", { fill: "#2F80ED", d: "M11.58.54a1.47 1.47 0 0 0-.44 2.03c2.43 3.76 3 6.6 2.75 9.08-1 4.75-3.18 5.72-5.09 5.72-1.86 0-1.36-3.07.03-3.96a5.3 5.3 0 0 1 2.73-.87 1.47 1.47 0 1 0 0-2.94c-.96 0-1.9.21-2.78.55.18-.85.25-1.76.02-2.74-.36-1.47-1.37-2.88-3.13-4.25a1.47 1.47 0 0 0-1.81 2.32c1.43 1.11 1.9 1.94 2.07 2.62.16.68.03 1.4-.3 2.4-.41 1.35-.9 2.56-1.1 3.71-.11.57-.12 1.19-.15 1.68-1.03-1-1.43-2.34-1.43-4.28a1.47 1.47 0 1 0-2.95 0c0 2.66.78 5.18 2.86 6.87 1.88 1.79 6.67 1.13 6.67 4.01 0 .81 1.19 1.21 2 1.21.84 0 1.89-.56 1.89-1.21 0-3.27 3.44-5.25 9.11-5.24A1.47 1.47 0 1 0 22.53 14.3c-.39 0-.77.01-1.14.03.64-1.49.92-3.13.86-4.9a1.47 1.47 0 1 0-2.95.1c.08 2.32-.01 4.39-1.74 5.48-.49.31-1.06.58-1.6.58.42-1.14.74-2.35.87-3.65.08-.83.09-1.82 0-2.59-.15-1.18-.33-2.53.12-3.55.4-.87 1.31-1.24 2.65-1.24a1.47 1.47 0 1 0 0-2.94c-1.98 0-3.48 1.04-4.34 2.3-.44-.95-.98-1.93-1.64-2.94a1.47 1.47 0 0 0-2.04-.44Z" }) }));
22
+ const WebStormIcon = ({ size }) => (jsx_runtime_1.jsxs("svg", { viewBox: "0 0 24 24", style: iconStyle(size), "aria-hidden": true, children: [
23
+ jsx_runtime_1.jsx("rect", { width: "24", height: "24", rx: "3", fill: "#07C3F2" }), jsx_runtime_1.jsx("path", { fill: "#050505", d: "M3 3h18v18H3z" }), jsx_runtime_1.jsx("path", { fill: "#fff", d: "M4.8 5.4h2.1l1.3 4.9 1.4-4.9h1.6l1.4 4.9 1.3-4.9h2.1l-2.5 8.7h-1.8l-1.3-4.8-1.4 4.8H7.3L4.8 5.4Zm10.8 7.3 1.1-1.4c.8.6 1.6 1 2.5 1 .7 0 1.2-.3 1.2-.8 0-.5-.3-.7-1.7-1.1-1.7-.4-2.8-.9-2.8-2.6 0-1.6 1.3-2.6 3-2.6 1.2 0 2.3.4 3.2 1.1l-1 1.5c-.8-.5-1.5-.8-2.2-.8-.7 0-1.1.3-1.1.7 0 .6.4.7 1.8 1.1 1.7.5 2.7 1.1 2.7 2.6 0 1.7-1.3 2.7-3.2 2.7-1.3 0-2.6-.5-3.5-1.4ZM4.7 18h8v1.3h-8V18Z" })
24
+ ] }));
25
+ const SublimeTextIcon = ({ size }) => (jsx_runtime_1.jsxs("svg", { viewBox: "0 0 40 40", style: iconStyle(size), "aria-hidden": true, children: [
26
+ jsx_runtime_1.jsx("path", { fill: "#FF9800", d: "M35.91 4.51c0-.37-.36-.59-.8-.48L4.8 11.44c-.44.11-.8.5-.8.87v7.58c0 .37.36.59.8.48l30.31-7.41c.44-.11.8-.5.8-.87V4.51Zm0 15.57c0-.38-.36-.59-.8-.49L4.8 27.01c-.44.1-.8.5-.8.87v7.57c0 .38.36.6.8.49l30.31-7.41c.44-.11.8-.5.8-.88v-7.57Z" }), jsx_runtime_1.jsx("path", { fill: "#F28C00", d: "M4 19.84c0 .37.36.76.8.87l30.32 7.41c.44.11.8-.11.8-.48v-7.58c0-.37-.36-.76-.8-.87L4.8 11.78c-.44-.11-.8.11-.8.48v7.58Z" })
27
+ ] }));
28
+ const EditorIcon = ({ editorId, size: sizeProp }) => {
29
+ const size = sizeProp !== null && sizeProp !== void 0 ? sizeProp : 14;
30
+ switch (editorId) {
31
+ case 'vscode':
32
+ return jsx_runtime_1.jsx(VsCodeIcon, { size: size });
33
+ case 'cursor':
34
+ return jsx_runtime_1.jsx(CursorIcon, { size: size });
35
+ case 'windsurf':
36
+ return jsx_runtime_1.jsx(WindsurfIcon, { size: size });
37
+ case 'zed':
38
+ return jsx_runtime_1.jsx(ZedIcon, { size: size });
39
+ case 'vscodium':
40
+ return jsx_runtime_1.jsx(VscodiumIcon, { size: size });
41
+ case 'webstorm':
42
+ return jsx_runtime_1.jsx(WebStormIcon, { size: size });
43
+ case 'sublime-text':
44
+ return jsx_runtime_1.jsx(SublimeTextIcon, { size: size });
45
+ case 'custom':
46
+ case null:
47
+ return jsx_runtime_1.jsx(custom_editor_1.CustomEditorIcon, { size: size });
48
+ default:
49
+ return null;
50
+ }
51
+ };
52
+ exports.EditorIcon = EditorIcon;
@@ -11,6 +11,7 @@ export type GuideState = {
11
11
  guidesList: Guide[];
12
12
  setGuidesList: (cb: (prevState: Guide[]) => Guide[]) => void;
13
13
  draggingGuideId: string | null;
14
+ moveGuidePointerRef: React.RefObject<((event: PointerEvent) => void) | null>;
14
15
  setDraggingGuideId: (cb: (prevState: string | null) => string | null) => void;
15
16
  setHoveredGuideId: (cb: (prevState: string | null) => string | null) => void;
16
17
  hoveredGuideId: string | null;
@@ -26,6 +26,7 @@ exports.EditorShowGuidesContext = (0, react_1.createContext)({
26
26
  guidesList: [],
27
27
  setGuidesList: () => undefined,
28
28
  draggingGuideId: null,
29
+ moveGuidePointerRef: { current: null },
29
30
  setDraggingGuideId: () => undefined,
30
31
  shouldCreateGuideRef: { current: false },
31
32
  shouldDeleteGuideRef: { current: false },
@@ -146,6 +146,8 @@ export type ModalState = {
146
146
  } | {
147
147
  type: 'configure-license';
148
148
  initialPublicLicenseKey: string | null;
149
+ } | {
150
+ type: 'configure-default-editor';
149
151
  } | RenderModalState | WebRenderModalState | {
150
152
  type: 'render-progress';
151
153
  jobId: string;
@@ -5,6 +5,7 @@ export declare const HigherZIndex: React.FC<{
5
5
  readonly children: React.ReactNode;
6
6
  readonly disabled?: boolean;
7
7
  readonly outsideClickButton?: 'any' | 'primary';
8
+ readonly stackOnHighest?: boolean;
8
9
  }>;
9
10
  export declare const useZIndex: () => {
10
11
  currentZIndex: number;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useZIndex = exports.HigherZIndex = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
+ const pointer_session_1 = require("../helpers/pointer-session");
6
7
  const use_keybinding_1 = require("../helpers/use-keybinding");
7
8
  const highest_z_index_1 = require("./highest-z-index");
8
9
  const input_dragger_click_lock_1 = require("./input-dragger-click-lock");
@@ -31,13 +32,22 @@ const EscapeHook = ({ onEscape }) => {
31
32
  }, [keybindings, onEscape]);
32
33
  return null;
33
34
  };
34
- const HigherZIndex = ({ children, onEscape, onOutsideClick, disabled, outsideClickButton = 'any', }) => {
35
+ const HigherZIndex = ({ children, onEscape, onOutsideClick, disabled, outsideClickButton = 'any', stackOnHighest = false, }) => {
36
+ var _a;
35
37
  const context = (0, react_1.useContext)(ZIndexContext);
36
38
  const highestContext = (0, react_1.useContext)(highest_z_index_1.HighestZIndexContext);
37
39
  const containerRef = (0, react_1.useRef)(null);
40
+ const stackedIndex = (0, react_1.useRef)(null);
41
+ if (disabled || !stackOnHighest) {
42
+ stackedIndex.current = null;
43
+ }
44
+ else if (stackedIndex.current === null) {
45
+ stackedIndex.current =
46
+ Math.max(context.currentIndex, highestContext.highestIndex) + 1;
47
+ }
38
48
  const currentIndex = disabled
39
49
  ? context.currentIndex
40
- : context.currentIndex + 1;
50
+ : ((_a = stackedIndex.current) !== null && _a !== void 0 ? _a : context.currentIndex + 1);
41
51
  (0, react_1.useEffect)(() => {
42
52
  if (disabled) {
43
53
  return;
@@ -49,7 +59,7 @@ const HigherZIndex = ({ children, onEscape, onOutsideClick, disabled, outsideCli
49
59
  if (disabled) {
50
60
  return;
51
61
  }
52
- let onUp = null;
62
+ let endPointerSession = null;
53
63
  const listener = (downEvent) => {
54
64
  var _a;
55
65
  if (outsideClickButton === 'primary' && downEvent.button !== 0) {
@@ -59,16 +69,25 @@ const HigherZIndex = ({ children, onEscape, onOutsideClick, disabled, outsideCli
59
69
  if (!outsideClick) {
60
70
  return;
61
71
  }
62
- onUp = (upEvent) => {
63
- if (highestContext.highestIndex === currentIndex &&
64
- !(0, input_dragger_click_lock_1.getClickLock)() &&
65
- // Don't trigger if that click removed that node
66
- document.contains(upEvent.target)) {
67
- upEvent.stopPropagation();
68
- onOutsideClick(upEvent.target);
69
- }
70
- };
71
- window.addEventListener('pointerup', onUp, { once: true });
72
+ endPointerSession === null || endPointerSession === void 0 ? void 0 : endPointerSession();
73
+ endPointerSession = (0, pointer_session_1.startPointerSession)({
74
+ event: downEvent,
75
+ target: downEvent.target,
76
+ onEnd: (reason, upEvent) => {
77
+ var _a;
78
+ endPointerSession = null;
79
+ if ((reason === 'pointerup' || reason === 'buttons-released') &&
80
+ upEvent &&
81
+ highestContext.highestIndex === currentIndex &&
82
+ !(0, input_dragger_click_lock_1.getClickLock)()) {
83
+ const target = (_a = document.elementFromPoint(upEvent.clientX, upEvent.clientY)) !== null && _a !== void 0 ? _a : upEvent.target;
84
+ if (document.contains(target)) {
85
+ upEvent.stopPropagation();
86
+ onOutsideClick(target);
87
+ }
88
+ }
89
+ },
90
+ });
72
91
  };
73
92
  // If a menu is opened, then this component will also still receive the pointerdown event.
74
93
  // However we may not interpret it as a outside click, so we need to wait for the next tick
@@ -79,11 +98,8 @@ const HigherZIndex = ({ children, onEscape, onOutsideClick, disabled, outsideCli
79
98
  window.addEventListener('pointerdown', listener, true);
80
99
  });
81
100
  return () => {
82
- if (onUp) {
83
- // @ts-expect-error
84
- window.removeEventListener('pointerup', onUp, { once: true });
85
- }
86
- onUp = null;
101
+ endPointerSession === null || endPointerSession === void 0 ? void 0 : endPointerSession();
102
+ endPointerSession = null;
87
103
  return window.removeEventListener('pointerdown', listener, true);
88
104
  };
89
105
  }, [
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio"
4
4
  },
5
5
  "name": "@remotion/studio",
6
- "version": "4.0.502",
6
+ "version": "4.0.503",
7
7
  "description": "APIs for interacting with the Remotion Studio",
8
8
  "main": "dist",
9
9
  "scripts": {
@@ -24,18 +24,17 @@
24
24
  "react-dom": ">=16.8.0"
25
25
  },
26
26
  "dependencies": {
27
- "@remotion/studio-protocol": "4.0.502",
27
+ "@remotion/studio-protocol": "4.0.503",
28
28
  "semver": "7.5.3",
29
- "remotion": "4.0.502",
30
- "@remotion/canvas-capture": "4.0.502",
31
- "@remotion/captions": "4.0.502",
32
- "@remotion/player": "4.0.502",
33
- "@remotion/media-utils": "4.0.502",
34
- "@remotion/renderer": "4.0.502",
35
- "@remotion/web-renderer": "4.0.502",
36
- "@remotion/studio-shared": "4.0.502",
37
- "@remotion/timeline-utils": "4.0.502",
38
- "@remotion/zod-types": "4.0.502",
29
+ "remotion": "4.0.503",
30
+ "@remotion/captions": "4.0.503",
31
+ "@remotion/player": "4.0.503",
32
+ "@remotion/media-utils": "4.0.503",
33
+ "@remotion/renderer": "4.0.503",
34
+ "@remotion/web-renderer": "4.0.503",
35
+ "@remotion/studio-shared": "4.0.503",
36
+ "@remotion/timeline-utils": "4.0.503",
37
+ "@remotion/zod-types": "4.0.503",
39
38
  "@jridgewell/trace-mapping": "0.3.31",
40
39
  "mediabunny": "1.50.8",
41
40
  "memfs": "3.4.3",
@@ -46,7 +45,7 @@
46
45
  "react": "19.2.3",
47
46
  "react-dom": "19.2.3",
48
47
  "@types/semver": "7.5.3",
49
- "@remotion/eslint-config-internal": "4.0.502",
48
+ "@remotion/eslint-config-internal": "4.0.503",
50
49
  "eslint": "9.19.0",
51
50
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
52
51
  },
@@ -1,5 +0,0 @@
1
- import React from 'react';
2
- export declare const StudioCanvasCapture: React.FC<{
3
- readonly children: React.ReactNode;
4
- readonly density: number;
5
- }>;
@@ -1,40 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.StudioCanvasCapture = void 0;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
- const canvas_capture_1 = require("@remotion/canvas-capture");
6
- const react_1 = require("react");
7
- const use_keybinding_1 = require("../helpers/use-keybinding");
8
- const logCaptureError = (message, err) => {
9
- // eslint-disable-next-line no-console
10
- console.error(message, err instanceof Error ? err.message : String(err));
11
- };
12
- const StudioCanvasCapture = ({ children, density }) => {
13
- const captureRef = (0, react_1.useRef)(null);
14
- const isSupported = (0, react_1.useMemo)(() => (0, canvas_capture_1.isHtmlInCanvasAvailable)(), []);
15
- const keybindings = (0, use_keybinding_1.useKeybinding)();
16
- (0, react_1.useEffect)(() => {
17
- if (!isSupported) {
18
- return;
19
- }
20
- const binding = keybindings.registerKeybinding({
21
- event: 'keydown',
22
- key: 'p',
23
- commandCtrlKey: true,
24
- callback: () => {
25
- var _a;
26
- (_a = captureRef.current) === null || _a === void 0 ? void 0 : _a.toggleRecording().catch((err) => {
27
- logCaptureError('Could not toggle Studio canvas recording:', err);
28
- });
29
- },
30
- preventDefault: true,
31
- triggerIfInputFieldFocused: true,
32
- keepRegisteredWhenNotHighestContext: true,
33
- });
34
- return () => {
35
- binding.unregister();
36
- };
37
- }, [isSupported, keybindings]);
38
- return (jsx_runtime_1.jsx(canvas_capture_1.HtmlInCanvasCapture, { ref: captureRef, density: density, filename: "remotion-studio-canvas-recording.webm", children: children }));
39
- };
40
- exports.StudioCanvasCapture = StudioCanvasCapture;
@@ -1 +0,0 @@
1
- export declare const CANVAS_CAPTURE_ENABLED = false;
@@ -1,4 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CANVAS_CAPTURE_ENABLED = void 0;
4
- exports.CANVAS_CAPTURE_ENABLED = false;
@@ -1,2 +0,0 @@
1
- import type { InsertElementFileConflict } from '@remotion/studio-shared';
2
- export declare const useElementOverwriteConfirmation: () => (conflict: InsertElementFileConflict) => Promise<boolean>;