@remotion/studio 4.0.505 → 4.0.506

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 (115) hide show
  1. package/dist/api/install-package.d.ts +2 -3
  2. package/dist/api/install-package.js +1 -3
  3. package/dist/api/visual-control.d.ts +3 -0
  4. package/dist/api/visual-control.js +3 -0
  5. package/dist/components/AssetSelectorItem.js +1 -1
  6. package/dist/components/Canvas.js +2 -0
  7. package/dist/components/CompositionSelector.js +1 -1
  8. package/dist/components/CompositionSelectorItem.js +1 -1
  9. package/dist/components/ConfigureDefaultEditorModal.d.ts +3 -1
  10. package/dist/components/ConfigureDefaultEditorModal.js +90 -32
  11. package/dist/components/ConfigureLicenseModal.d.ts +2 -1
  12. package/dist/components/ConfigureLicenseModal.js +40 -32
  13. package/dist/components/ConfirmationDialog.js +2 -2
  14. package/dist/components/Editor.js +2 -0
  15. package/dist/components/EffectPickerModal.js +1 -1
  16. package/dist/components/GlobalKeybindings.js +3 -2
  17. package/dist/components/InlineCaptionInspector.d.ts +2 -2
  18. package/dist/components/InlineDropdown.d.ts +2 -1
  19. package/dist/components/InlineDropdown.js +10 -4
  20. package/dist/components/InspectorOpenInEditor.d.ts +1 -0
  21. package/dist/components/InspectorOpenInEditor.js +33 -9
  22. package/dist/components/InspectorPanel/AlignmentControls.js +5 -2
  23. package/dist/components/InspectorPanel/CompositionInspector.js +15 -1
  24. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +1 -1
  25. package/dist/components/InspectorPanel/EasingInspector.js +7 -4
  26. package/dist/components/InspectorPanel/KeyframeInspector.js +5 -1
  27. package/dist/components/InspectorPanel/common.d.ts +1 -0
  28. package/dist/components/InspectorPanel/common.js +2 -2
  29. package/dist/components/InspectorPanel/use-composition-actions.js +4 -1
  30. package/dist/components/InspectorSequenceSection.js +4 -4
  31. package/dist/components/InstallPackage.js +1 -1
  32. package/dist/components/MenuBuildIndicator.js +1 -0
  33. package/dist/components/MenuToolbar.js +1 -1
  34. package/dist/components/ModalFooter.d.ts +1 -0
  35. package/dist/components/ModalFooter.js +6 -2
  36. package/dist/components/ModalHeader.js +1 -1
  37. package/dist/components/Modals.js +18 -7
  38. package/dist/components/ModalsProvider.js +5 -6
  39. package/dist/components/NewComposition/CodemodFooter.js +1 -1
  40. package/dist/components/NewComposition/DismissableModal.js +1 -1
  41. package/dist/components/NewComposition/RenameStaticFile.js +1 -1
  42. package/dist/components/OverrideInputProps.js +1 -1
  43. package/dist/components/PlayPause.js +2 -1
  44. package/dist/components/PlaybackKeyboardShortcutsManager.js +7 -5
  45. package/dist/components/PreviewToolbarOverflowButton.js +4 -2
  46. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.js +1 -1
  47. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +1 -1
  48. package/dist/components/RenderButton.d.ts +3 -3
  49. package/dist/components/RenderButton.js +42 -7
  50. package/dist/components/RenderModal/RenderStatusModal.js +1 -1
  51. package/dist/components/RenderModal/ServerRenderModal.js +1 -1
  52. package/dist/components/RenderModal/WebRenderModal.js +3 -2
  53. package/dist/components/RenderQueue/RenderQueueError.js +1 -1
  54. package/dist/components/RenderQueue/RenderQueueItemStatus.js +1 -1
  55. package/dist/components/RenderQueue/RenderQueueProgressMessage.js +1 -1
  56. package/dist/components/RenderQueue/RenderQueueRepeat.js +1 -1
  57. package/dist/components/SelectedOutlineElement.js +1 -1
  58. package/dist/components/SelectedOutlineOverlay.js +62 -19
  59. package/dist/components/SettingsModal.d.ts +7 -0
  60. package/dist/components/SettingsModal.js +50 -0
  61. package/dist/components/SettingsModalFooter.d.ts +4 -0
  62. package/dist/components/SettingsModalFooter.js +46 -0
  63. package/dist/components/SidebarRenderButton.js +1 -1
  64. package/dist/components/SvgImportDialog.js +2 -2
  65. package/dist/components/TimeValue.js +1 -1
  66. package/dist/components/Timeline/Timeline.js +1 -0
  67. package/dist/components/Timeline/TimelineAssetField.js +1 -1
  68. package/dist/components/Timeline/TimelineDragHandler.js +3 -3
  69. package/dist/components/Timeline/TimelineEffectPropItem.js +5 -3
  70. package/dist/components/Timeline/TimelineExpandedRow.d.ts +4 -2
  71. package/dist/components/Timeline/TimelineExpandedRow.js +2 -2
  72. package/dist/components/Timeline/TimelineFontFamilyField.js +3 -1
  73. package/dist/components/Timeline/TimelineKeyframeControls.js +1 -0
  74. package/dist/components/Timeline/TimelineSelection.js +1 -0
  75. package/dist/components/Timeline/TimelineSequenceItem.js +28 -34
  76. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +1 -1
  77. package/dist/components/Timeline/reset-selected-timeline-props.js +1 -1
  78. package/dist/components/Timeline/should-subscribe-to-sequence-props.d.ts +1 -1
  79. package/dist/components/Timeline/timeline-asset-link.d.ts +2 -2
  80. package/dist/components/Timeline/timeline-asset-link.js +2 -2
  81. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +4 -0
  82. package/dist/components/Timeline/use-timeline-asset-drop.js +1 -0
  83. package/dist/components/Timeline/use-timeline-expanded-tree.d.ts +1 -0
  84. package/dist/components/Timeline/use-timeline-expanded-tree.js +5 -0
  85. package/dist/components/Timeline/use-timeline-height.js +20 -0
  86. package/dist/components/TimelineInOutToggle.js +5 -1
  87. package/dist/components/TopPanel.js +16 -0
  88. package/dist/components/UpdateCheck.js +1 -1
  89. package/dist/components/effect-drag-and-drop.js +1 -1
  90. package/dist/components/handle-drop.d.ts +2 -1
  91. package/dist/components/handle-drop.js +12 -2
  92. package/dist/components/import-assets.d.ts +18 -6
  93. package/dist/components/import-assets.js +76 -32
  94. package/dist/esm/{chunk-7pgk8h5m.js → chunk-b49ec3nz.js} +8334 -7701
  95. package/dist/esm/internals.mjs +8334 -7701
  96. package/dist/esm/previewEntry.mjs +8343 -7710
  97. package/dist/esm/renderEntry.mjs +1 -1
  98. package/dist/helpers/client-id.d.ts +3 -1
  99. package/dist/helpers/client-id.js +21 -4
  100. package/dist/helpers/install-required-package.d.ts +3 -3
  101. package/dist/helpers/install-required-package.js +1 -6
  102. package/dist/helpers/studio-fit-padding.d.ts +1 -1
  103. package/dist/helpers/studio-fit-padding.js +1 -1
  104. package/dist/helpers/timeline-layout.d.ts +2 -1
  105. package/dist/helpers/timeline-layout.js +5 -2
  106. package/dist/helpers/use-menu-structure.js +23 -33
  107. package/dist/helpers/use-runtime-values.d.ts +11 -0
  108. package/dist/helpers/use-runtime-values.js +76 -0
  109. package/dist/icons/apps.d.ts +2 -0
  110. package/dist/icons/apps.js +7 -0
  111. package/dist/icons/browse-elements.d.ts +4 -0
  112. package/dist/icons/browse-elements.js +10 -0
  113. package/dist/state/modals.d.ts +5 -6
  114. package/dist/state/modals.js +5 -3
  115. package/package.json +12 -12
@@ -212,7 +212,7 @@ var renderContent = (Root) => {
212
212
  renderToDOM(/* @__PURE__ */ jsx("div", {
213
213
  children: /* @__PURE__ */ jsx(DelayedSpinner, {})
214
214
  }));
215
- import("./chunk-7pgk8h5m.js").then(({ StudioInternals }) => {
215
+ import("./chunk-b49ec3nz.js").then(({ StudioInternals }) => {
216
216
  window.remotion_isStudio = true;
217
217
  window.remotion_isReadOnlyStudio = true;
218
218
  window.remotion_inputProps = "{}";
@@ -1,12 +1,14 @@
1
- import type { EventSourceEvent } from '@remotion/studio-shared';
1
+ import { type EventSourceEvent } from '@remotion/studio-shared';
2
2
  import React from 'react';
3
3
  import { type PreviewServerConnectionState } from './preview-server-events';
4
4
  type Context = {
5
5
  previewServerState: PreviewServerConnectionState;
6
+ configFileChangeRevision: number;
6
7
  subscribeToEvent: (type: EventSourceEvent['type'], listener: (event: EventSourceEvent) => void) => () => void;
7
8
  };
8
9
  export declare const StudioServerConnectionCtx: React.Context<Context>;
9
10
  export declare const PreviewServerConnection: React.FC<{
10
11
  readonly children: React.ReactNode;
11
12
  }>;
13
+ export declare const useStudioConfigRevision: () => number;
12
14
  export {};
@@ -36,8 +36,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.PreviewServerConnection = exports.StudioServerConnectionCtx = void 0;
39
+ exports.useStudioConfigRevision = exports.PreviewServerConnection = exports.StudioServerConnectionCtx = void 0;
40
40
  const jsx_runtime_1 = require("react/jsx-runtime");
41
+ const studio_shared_1 = require("@remotion/studio-shared");
41
42
  const react_1 = __importStar(require("react"));
42
43
  const remotion_1 = require("remotion");
43
44
  const NotificationCenter_1 = require("../components/Notifications/NotificationCenter");
@@ -49,6 +50,7 @@ exports.StudioServerConnectionCtx = react_1.default.createContext({
49
50
  previewServerState: {
50
51
  type: 'init',
51
52
  },
53
+ configFileChangeRevision: 0,
52
54
  subscribeToEvent: () => {
53
55
  throw new Error('Context not initalized');
54
56
  },
@@ -68,14 +70,24 @@ const PreviewServerConnection = ({ children }) => {
68
70
  const [state, setState] = react_1.default.useState({
69
71
  type: 'init',
70
72
  });
73
+ const [configFileChangeRevision, setConfigFileChangeRevision] = react_1.default.useState(0);
71
74
  (0, react_1.useEffect)(() => {
72
75
  const handleEvent = (newEvent) => {
73
76
  var _a, _b;
74
77
  if (newEvent.type === 'new-input-props' ||
75
- newEvent.type === 'new-env-variables' ||
76
- newEvent.type === 'config-file-changed') {
78
+ newEvent.type === 'new-env-variables') {
77
79
  (0, url_state_1.reloadUrl)();
78
80
  }
81
+ if (newEvent.type === 'config-file-changed') {
82
+ window.remotion_renderDefaults = newEvent.renderDefaults;
83
+ window.remotion_studioConfig = newEvent.studioRuntimeConfig;
84
+ window.remotion_editorName = newEvent.editorName;
85
+ setConfigFileChangeRevision((revision) => revision + 1);
86
+ (0, NotificationCenter_1.showNotification)((0, studio_shared_1.getConfigFileChangeMessage)(newEvent.changeType), 4000);
87
+ }
88
+ if (newEvent.type === 'config-file-reload-failed') {
89
+ (0, NotificationCenter_1.showNotification)(newEvent.errorMessage, 4000);
90
+ }
79
91
  if (newEvent.type === 'init') {
80
92
  latestUndoRedoEvent.current = {
81
93
  type: 'undo-redo-stack-changed',
@@ -131,9 +143,14 @@ const PreviewServerConnection = ({ children }) => {
131
143
  const context = (0, react_1.useMemo)(() => {
132
144
  return {
133
145
  previewServerState: state,
146
+ configFileChangeRevision,
134
147
  subscribeToEvent,
135
148
  };
136
- }, [state, subscribeToEvent]);
149
+ }, [configFileChangeRevision, state, subscribeToEvent]);
137
150
  return (jsx_runtime_1.jsx(exports.StudioServerConnectionCtx.Provider, { value: context, children: children }));
138
151
  };
139
152
  exports.PreviewServerConnection = PreviewServerConnection;
153
+ const useStudioConfigRevision = () => {
154
+ return react_1.default.useContext(exports.StudioServerConnectionCtx).configFileChangeRevision;
155
+ };
156
+ exports.useStudioConfigRevision = useStudioConfigRevision;
@@ -1,3 +1,3 @@
1
- import type { ElementDependency } from '@remotion/studio-protocol';
2
- export declare const getMissingPackages: (dependencies: (string | ElementDependency)[]) => ElementDependency[];
3
- export declare const installRequiredPackages: (dependencies: (string | ElementDependency)[]) => Promise<void>;
1
+ import type { PackageInstallSpec } from '@remotion/studio-shared';
2
+ export declare const getMissingPackages: (dependencies: readonly PackageInstallSpec[]) => PackageInstallSpec[];
3
+ export declare const installRequiredPackages: (dependencies: readonly PackageInstallSpec[]) => Promise<void>;
@@ -4,12 +4,7 @@ exports.installRequiredPackages = exports.getMissingPackages = void 0;
4
4
  const install_package_1 = require("../api/install-package");
5
5
  const NotificationCenter_1 = require("../components/Notifications/NotificationCenter");
6
6
  let installQueue = Promise.resolve();
7
- const uniqueDependencies = (dependencies) => Array.from(new Map(dependencies.map((dependency) => {
8
- const normalized = typeof dependency === 'string'
9
- ? { name: dependency, version: null }
10
- : dependency;
11
- return [normalized.name, normalized];
12
- })).values());
7
+ const uniqueDependencies = (dependencies) => Array.from(new Map(dependencies.map((dependency) => [dependency.name, dependency])).values());
13
8
  const getMissingPackages = (dependencies) => {
14
9
  var _a;
15
10
  const installedPackages = (_a = window.remotion_installedPackages) !== null && _a !== void 0 ? _a : [];
@@ -1,5 +1,5 @@
1
1
  import type { Size } from '@remotion/player';
2
- export declare const STUDIO_FIT_PADDING = 16;
2
+ export declare const STUDIO_FIT_PADDING = 8;
3
3
  type CanvasSize = {
4
4
  readonly width: number;
5
5
  readonly height: number;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.calculateStudioCanvasTransformation = exports.calculateStudioScale = exports.getStudioCurrentScaleContext = exports.getStudioPaddedCanvasSize = exports.STUDIO_FIT_PADDING = void 0;
4
4
  const player_1 = require("@remotion/player");
5
5
  const remotion_1 = require("remotion");
6
- exports.STUDIO_FIT_PADDING = 16;
6
+ exports.STUDIO_FIT_PADDING = 8;
7
7
  const getPadding = (length) => {
8
8
  return Math.min(exports.STUDIO_FIT_PADDING, Math.max(0, (length - 1) / 2));
9
9
  };
@@ -31,7 +31,7 @@ export type TimelineTreeNode = {
31
31
  readonly label: string;
32
32
  readonly field: AnySchemaFieldInfo | null;
33
33
  };
34
- export declare const buildTimelineTree: ({ sequence, nodePathInfo, getDragOverrides, getEffectDragOverrides, propStatuses, includeTextContent, includeSourceControls, }: {
34
+ export declare const buildTimelineTree: ({ sequence, nodePathInfo, getDragOverrides, getEffectDragOverrides, propStatuses, includeTextContent, includeSourceControls, runtimeValues, }: {
35
35
  sequence: TSequence;
36
36
  nodePathInfo: SequenceNodePathInfo;
37
37
  getDragOverrides: GetDragOverrides;
@@ -39,6 +39,7 @@ export declare const buildTimelineTree: ({ sequence, nodePathInfo, getDragOverri
39
39
  propStatuses: PropStatuses;
40
40
  includeTextContent: boolean;
41
41
  includeSourceControls: boolean;
42
+ runtimeValues: Readonly<Record<string, unknown>> | null;
42
43
  }) => TimelineTreeNode[];
43
44
  export type FlatTreeRow = {
44
45
  readonly node: TimelineTreeNode;
@@ -14,13 +14,15 @@ exports.TIMELINE_ITEM_BORDER_BOTTOM = 1;
14
14
  exports.TIMELINE_TRACK_EXPANDED_HEIGHT = 100;
15
15
  exports.TREE_GROUP_ROW_HEIGHT = 22;
16
16
  exports.EXPANDED_SECTION_PADDING_RIGHT = 10;
17
- const buildTimelineTree = ({ sequence, nodePathInfo, getDragOverrides, getEffectDragOverrides, propStatuses, includeTextContent, includeSourceControls, }) => {
17
+ const buildTimelineTree = ({ sequence, nodePathInfo, getDragOverrides, getEffectDragOverrides, propStatuses, includeTextContent, includeSourceControls, runtimeValues, }) => {
18
18
  var _a;
19
19
  const roots = [];
20
20
  const { sequenceSubscriptionKey, index, auxiliaryKeys, supportsEffects } = nodePathInfo;
21
21
  const controlFields = (0, studio_shared_1.getFieldsToShow)({
22
22
  schema: sequence.controls.schema,
23
- currentRuntimeValueDotNotation: sequence.controls.currentRuntimeValueDotNotation,
23
+ currentRuntimeValueDotNotation: runtimeValues !== null
24
+ ? runtimeValues
25
+ : sequence.controls.runtimeValues.getSnapshot(),
24
26
  getDragOverrides,
25
27
  propStatuses,
26
28
  nodePath: sequenceSubscriptionKey,
@@ -140,6 +142,7 @@ const getExpandedTrackHeight = ({ sequence, nodePathInfo, getIsExpanded, propSta
140
142
  propStatuses,
141
143
  includeTextContent: false,
142
144
  includeSourceControls: false,
145
+ runtimeValues: null,
143
146
  });
144
147
  const flat = (0, exports.flattenVisibleTreeNodes)({ nodes: tree, getIsExpanded });
145
148
  if (flat.length === 0) {
@@ -43,7 +43,7 @@ const inheritColor = {
43
43
  color: 'inherit',
44
44
  };
45
45
  const ICON_SIZE = 14;
46
- const getFileMenu = ({ readOnlyStudio, closeMenu, previewServerState, setSelectedModal, }) => {
46
+ const getFileMenu = ({ readOnlyStudio, closeMenu, editorName, previewServerState, setSelectedModal, }) => {
47
47
  const fileManagerName = (0, get_file_manager_name_1.getFileManagerName)(window.remotion_fileSystemPlatform);
48
48
  const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
49
49
  const downloadProject = browserStudioOperations === null || browserStudioOperations === void 0 ? void 0 : browserStudioOperations.downloadProject;
@@ -144,11 +144,11 @@ const getFileMenu = ({ readOnlyStudio, closeMenu, previewServerState, setSelecte
144
144
  id: 'open-project-divider',
145
145
  }
146
146
  : null,
147
- window.remotion_editorName && !readOnlyStudio
147
+ editorName && !readOnlyStudio
148
148
  ? {
149
149
  id: 'open-in-editor',
150
150
  value: 'open-in-editor',
151
- label: `Open in ${window.remotion_editorName}`,
151
+ label: `Open in ${editorName}`,
152
152
  onClick: async () => {
153
153
  await (0, open_in_editor_1.openInEditor)({
154
154
  originalFileName: `${window.remotion_cwd}`,
@@ -159,13 +159,13 @@ const getFileMenu = ({ readOnlyStudio, closeMenu, previewServerState, setSelecte
159
159
  }, null)
160
160
  .then(({ success }) => {
161
161
  if (!success) {
162
- (0, NotificationCenter_1.showNotification)(`Could not open ${window.remotion_editorName}`, 2000);
162
+ (0, NotificationCenter_1.showNotification)(`Could not open ${editorName}`, 2000);
163
163
  }
164
164
  })
165
165
  .catch((err) => {
166
166
  // eslint-disable-next-line no-console
167
167
  console.error(err);
168
- (0, NotificationCenter_1.showNotification)(`Could not open ${window.remotion_editorName}`, 2000);
168
+ (0, NotificationCenter_1.showNotification)(`Could not open ${editorName}`, 2000);
169
169
  });
170
170
  },
171
171
  type: 'item',
@@ -254,7 +254,7 @@ const getRenderMenuItems = ({ closeMenu, previewServerState, readOnlyStudio, })
254
254
  };
255
255
  const useMenuStructure = (closeMenu, readOnlyStudio) => {
256
256
  var _a;
257
- const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
257
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.SetSelectedModalContext);
258
258
  const { checkerboard, setCheckerboard } = (0, react_1.useContext)(checkerboard_1.CheckerboardContext);
259
259
  const { editorZoomGestures, setEditorZoomGestures } = (0, react_1.useContext)(editor_zoom_gestures_1.EditorZoomGesturesContext);
260
260
  const { editorShowRulers, setEditorShowRulers } = (0, react_1.useContext)(editor_rulers_1.EditorShowRulersContext);
@@ -263,6 +263,9 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
263
263
  const { size, setSize } = (0, react_1.useContext)(remotion_1.Internals.PreviewSizeContext);
264
264
  const { canvasContent, compositions } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
265
265
  const { type } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx).previewServerState;
266
+ const editorName = window.remotion_editorName;
267
+ const keyboardShortcutsDisabled = (0, use_keybinding_1.areKeyboardShortcutsDisabled)();
268
+ const studioAskAIEnabled = (0, studio_runtime_config_1.getStudioAskAIEnabled)();
266
269
  const canConfigureDefaultEditor = !readOnlyStudio &&
267
270
  type === 'connected' &&
268
271
  (0, browser_studio_operations_1.getBrowserStudioOperations)() === null;
@@ -326,34 +329,17 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
326
329
  subMenu: null,
327
330
  quickSwitcherLabel: 'Help: Changelog',
328
331
  },
329
- canConfigureDefaultEditor
330
- ? {
331
- id: 'default-editor',
332
- value: 'default-editor',
333
- label: 'Configure default editor...',
334
- onClick: () => {
335
- closeMenu();
336
- setSelectedModal({
337
- type: 'configure-default-editor',
338
- });
339
- },
340
- type: 'item',
341
- keyHint: null,
342
- leftItem: null,
343
- subMenu: null,
344
- quickSwitcherLabel: 'Configure default editor...',
345
- }
346
- : null,
347
332
  {
348
- id: 'license',
349
- value: 'license',
350
- label: 'Configure License...',
333
+ id: 'settings',
334
+ value: 'settings',
335
+ label: 'Settings...',
351
336
  onClick: () => {
352
337
  var _a;
353
338
  var _b;
354
339
  closeMenu();
355
340
  setSelectedModal({
356
- type: 'configure-license',
341
+ type: 'settings',
342
+ initialTab: canConfigureDefaultEditor ? 'apps' : 'license',
357
343
  initialPublicLicenseKey: (_b = (_a = window.remotion_renderDefaults) === null || _a === void 0 ? void 0 : _a.publicLicenseKey) !== null && _b !== void 0 ? _b : null,
358
344
  });
359
345
  },
@@ -361,7 +347,7 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
361
347
  keyHint: null,
362
348
  leftItem: null,
363
349
  subMenu: null,
364
- quickSwitcherLabel: 'Configure License...',
350
+ quickSwitcherLabel: 'Settings...',
365
351
  disabled: readOnlyStudio || type !== 'connected',
366
352
  },
367
353
  {
@@ -402,6 +388,7 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
402
388
  getFileMenu({
403
389
  readOnlyStudio,
404
390
  closeMenu,
391
+ editorName,
405
392
  previewServerState: type,
406
393
  setSelectedModal,
407
394
  }),
@@ -489,7 +476,7 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
489
476
  },
490
477
  {
491
478
  id: 'enable-snapping',
492
- keyHint: (0, use_keybinding_1.areKeyboardShortcutsDisabled)() ? null : 'Shift+M',
479
+ keyHint: keyboardShortcutsDisabled ? null : 'Shift+M',
493
480
  label: 'Enable Snapping',
494
481
  onClick: () => {
495
482
  closeMenu();
@@ -776,7 +763,7 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
776
763
  label: 'Tools',
777
764
  leaveLeftPadding: false,
778
765
  items: [
779
- (0, studio_runtime_config_1.getStudioAskAIEnabled)()
766
+ studioAskAIEnabled
780
767
  ? {
781
768
  id: 'ask-ai',
782
769
  value: 'ask-ai',
@@ -839,7 +826,7 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
839
826
  {
840
827
  id: 'shortcuts',
841
828
  value: 'shortcuts',
842
- label: (0, use_keybinding_1.areKeyboardShortcutsDisabled)()
829
+ label: keyboardShortcutsDisabled
843
830
  ? 'Shortcuts (disabled)'
844
831
  : 'Shortcuts',
845
832
  onClick: () => {
@@ -856,7 +843,7 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
856
843
  leftItem: null,
857
844
  subMenu: null,
858
845
  type: 'item',
859
- quickSwitcherLabel: (0, use_keybinding_1.areKeyboardShortcutsDisabled)()
846
+ quickSwitcherLabel: keyboardShortcutsDisabled
860
847
  ? 'Show all Keyboard Shortcuts (disabled)'
861
848
  : 'Show all Keyboard Shortcuts',
862
849
  },
@@ -1025,6 +1012,9 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
1025
1012
  isFullscreenSupported,
1026
1013
  remotion_packageManager,
1027
1014
  mobileLayout,
1015
+ editorName,
1016
+ keyboardShortcutsDisabled,
1017
+ studioAskAIEnabled,
1028
1018
  size.size,
1029
1019
  setSize,
1030
1020
  setEditorZoomGestures,
@@ -0,0 +1,11 @@
1
+ import type { SequenceRegistrationControls } from 'remotion';
2
+ type RuntimeValueSelectorResult = string | number | boolean | bigint | symbol | null | undefined;
3
+ export declare const useRuntimeValues: (controls: SequenceRegistrationControls | null) => Readonly<Record<string, unknown>>;
4
+ export declare const useRuntimeValue: (controls: SequenceRegistrationControls | null, key: string) => unknown;
5
+ export declare const useRuntimeValueSelector: <T extends RuntimeValueSelectorResult>({ controls, selector, isEqual, }: {
6
+ controls: SequenceRegistrationControls | null;
7
+ selector: (values: Readonly<Record<string, unknown>>) => T;
8
+ isEqual?: ((first: T, second: T) => boolean) | undefined;
9
+ }) => T;
10
+ export declare const useRuntimeValueSnapshots: (controls: readonly SequenceRegistrationControls[]) => readonly Readonly<Record<string, unknown>>[];
11
+ export {};
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useRuntimeValueSnapshots = exports.useRuntimeValueSelector = exports.useRuntimeValue = exports.useRuntimeValues = void 0;
4
+ const react_1 = require("react");
5
+ const EMPTY_RUNTIME_VALUES = {};
6
+ const EMPTY_RUNTIME_VALUE_STORE = {
7
+ getSnapshot: () => EMPTY_RUNTIME_VALUES,
8
+ subscribe: () => () => undefined,
9
+ };
10
+ const useRuntimeValues = (controls) => {
11
+ var _a;
12
+ const store = (_a = controls === null || controls === void 0 ? void 0 : controls.runtimeValues) !== null && _a !== void 0 ? _a : EMPTY_RUNTIME_VALUE_STORE;
13
+ return (0, react_1.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
14
+ };
15
+ exports.useRuntimeValues = useRuntimeValues;
16
+ const useRuntimeValue = (controls, key) => {
17
+ var _a;
18
+ const store = (_a = controls === null || controls === void 0 ? void 0 : controls.runtimeValues) !== null && _a !== void 0 ? _a : EMPTY_RUNTIME_VALUE_STORE;
19
+ const getSnapshot = (0, react_1.useCallback)(() => store.getSnapshot()[key], [key, store]);
20
+ return (0, react_1.useSyncExternalStore)(store.subscribe, getSnapshot, getSnapshot);
21
+ };
22
+ exports.useRuntimeValue = useRuntimeValue;
23
+ const useRuntimeValueSelector = ({ controls, selector, isEqual = Object.is, }) => {
24
+ var _a;
25
+ const store = (_a = controls === null || controls === void 0 ? void 0 : controls.runtimeValues) !== null && _a !== void 0 ? _a : EMPTY_RUNTIME_VALUE_STORE;
26
+ const selectedStore = (0, react_1.useMemo)(() => {
27
+ let lastSource = store.getSnapshot();
28
+ let lastSelection = selector(lastSource);
29
+ const getSnapshot = () => {
30
+ const nextSource = store.getSnapshot();
31
+ if (nextSource === lastSource) {
32
+ return lastSelection;
33
+ }
34
+ lastSource = nextSource;
35
+ const nextSelection = selector(nextSource);
36
+ if (!isEqual(lastSelection, nextSelection)) {
37
+ lastSelection = nextSelection;
38
+ }
39
+ return lastSelection;
40
+ };
41
+ return {
42
+ getSnapshot,
43
+ subscribe: store.subscribe,
44
+ };
45
+ }, [isEqual, selector, store]);
46
+ return (0, react_1.useSyncExternalStore)(selectedStore.subscribe, selectedStore.getSnapshot, selectedStore.getSnapshot);
47
+ };
48
+ exports.useRuntimeValueSelector = useRuntimeValueSelector;
49
+ const useRuntimeValueSnapshots = (controls) => {
50
+ const stores = (0, react_1.useMemo)(() => controls.map((control) => control.runtimeValues), [controls]);
51
+ const aggregateStore = (0, react_1.useMemo)(() => {
52
+ let lastSnapshots = stores.map((store) => store.getSnapshot());
53
+ const getSnapshot = () => {
54
+ const nextSnapshots = stores.map((store) => store.getSnapshot());
55
+ if (nextSnapshots.length === lastSnapshots.length &&
56
+ nextSnapshots.every((snapshot, index) => snapshot === lastSnapshots[index])) {
57
+ return lastSnapshots;
58
+ }
59
+ lastSnapshots = nextSnapshots;
60
+ return lastSnapshots;
61
+ };
62
+ return {
63
+ getSnapshot,
64
+ subscribe: (listener) => {
65
+ const unsubscribers = stores.map((store) => store.subscribe(listener));
66
+ return () => {
67
+ for (const unsubscribe of unsubscribers) {
68
+ unsubscribe();
69
+ }
70
+ };
71
+ },
72
+ };
73
+ }, [stores]);
74
+ return (0, react_1.useSyncExternalStore)(aggregateStore.subscribe, aggregateStore.getSnapshot, aggregateStore.getSnapshot);
75
+ };
76
+ exports.useRuntimeValueSnapshots = useRuntimeValueSnapshots;
@@ -0,0 +1,2 @@
1
+ import type { SVGProps } from 'react';
2
+ export declare const AppsIcon: ({ color, ...props }: SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppsIcon = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const colors_1 = require("../helpers/colors");
6
+ const AppsIcon = ({ color, ...props }) => (jsx_runtime_1.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 640 640", ...props, children: jsx_runtime_1.jsx("path", { fill: color !== null && color !== void 0 ? color : colors_1.CURRENT_COLOR_LOWERCASE, d: "M144 128C135.2 128 128 135.2 128 144L128 240C128 248.8 135.2 256 144 256L240 256C248.8 256 256 248.8 256 240L256 144C256 135.2 248.8 128 240 128L144 128zM96 144C96 117.5 117.5 96 144 96L240 96C266.5 96 288 117.5 288 144L288 240C288 266.5 266.5 288 240 288L144 288C117.5 288 96 266.5 96 240L96 144zM144 384C135.2 384 128 391.2 128 400L128 496C128 504.8 135.2 512 144 512L240 512C248.8 512 256 504.8 256 496L256 400C256 391.2 248.8 384 240 384L144 384zM96 400C96 373.5 117.5 352 144 352L240 352C266.5 352 288 373.5 288 400L288 496C288 522.5 266.5 544 240 544L144 544C117.5 544 96 522.5 96 496L96 400zM496 128L400 128C391.2 128 384 135.2 384 144L384 240C384 248.8 391.2 256 400 256L496 256C504.8 256 512 248.8 512 240L512 144C512 135.2 504.8 128 496 128zM400 96L496 96C522.5 96 544 117.5 544 144L544 240C544 266.5 522.5 288 496 288L400 288C373.5 288 352 266.5 352 240L352 144C352 117.5 373.5 96 400 96zM400 384C391.2 384 384 391.2 384 400L384 496C384 504.8 391.2 512 400 512L496 512C504.8 512 512 504.8 512 496L512 400C512 391.2 504.8 384 496 384L400 384zM352 400C352 373.5 373.5 352 400 352L496 352C522.5 352 544 373.5 544 400L544 496C544 522.5 522.5 544 496 544L400 544C373.5 544 352 522.5 352 496L352 400z" }) }));
7
+ exports.AppsIcon = AppsIcon;
@@ -0,0 +1,4 @@
1
+ import type { SVGProps } from 'react';
2
+ export declare const BrowseElementsIcon: React.FC<SVGProps<SVGSVGElement> & {
3
+ readonly color: string;
4
+ }>;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BrowseElementsIcon = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ // Font Awesome Pro v7.3.1, Copyright 2026 Fonticons, Inc.
6
+ // https://fontawesome.com/license (Commercial License)
7
+ const BrowseElementsIcon = ({ color, ...props }) => {
8
+ return (jsx_runtime_1.jsx("svg", { ...props, xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 640 640", children: jsx_runtime_1.jsx("path", { fill: color, d: "M320 96L224 256L416 256L320 96zM320 64C331.2 64 341.7 69.9 347.4 79.5L443.4 239.5C449.3 249.4 449.5 261.7 443.8 271.7C438.1 281.7 427.5 288 416 288L224 288C212.5 288 201.8 281.8 196.2 271.8C190.6 261.8 190.7 249.5 196.6 239.6L292.6 79.6C298.3 69.9 308.8 64 320 64zM192 528C236.2 528 272 492.2 272 448C272 403.8 236.2 368 192 368C147.8 368 112 403.8 112 448C112 492.2 147.8 528 192 528zM192 336C253.9 336 304 386.1 304 448C304 509.9 253.9 560 192 560C130.1 560 80 509.9 80 448C80 386.1 130.1 336 192 336zM504 384L392 384C387.6 384 384 387.6 384 392L384 504C384 508.4 387.6 512 392 512L504 512C508.4 512 512 508.4 512 504L512 392C512 387.6 508.4 384 504 384zM392 352L504 352C526.1 352 544 369.9 544 392L544 504C544 526.1 526.1 544 504 544L392 544C369.9 544 352 526.1 352 504L352 392C352 369.9 369.9 352 392 352z" }) }));
9
+ };
10
+ exports.BrowseElementsIcon = BrowseElementsIcon;
@@ -144,10 +144,9 @@ export type ModalState = {
144
144
  } | {
145
145
  type: 'input-props-override';
146
146
  } | {
147
- type: 'configure-license';
147
+ type: 'settings';
148
+ initialTab: 'apps' | 'license';
148
149
  initialPublicLicenseKey: string | null;
149
- } | {
150
- type: 'configure-default-editor';
151
150
  } | RenderModalState | WebRenderModalState | {
152
151
  type: 'render-progress';
153
152
  jobId: string;
@@ -172,8 +171,8 @@ export type ModalState = {
172
171
  onSelected: (composition: _InternalTypes['AnyComposition']) => void;
173
172
  } | null;
174
173
  } | AddEffectModalState | ConfirmationDialogState | SvgImportDialogState;
175
- export type ModalContextType = {
176
- selectedModal: ModalState | null;
174
+ export type SetSelectedModalContextType = {
177
175
  setSelectedModal: React.Dispatch<React.SetStateAction<ModalState | null>>;
178
176
  };
179
- export declare const ModalsContext: React.Context<ModalContextType>;
177
+ export declare const SelectedModalContext: React.Context<ModalState | null>;
178
+ export declare const SetSelectedModalContext: React.Context<SetSelectedModalContextType>;
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ModalsContext = void 0;
3
+ exports.SetSelectedModalContext = exports.SelectedModalContext = void 0;
4
4
  const react_1 = require("react");
5
- exports.ModalsContext = (0, react_1.createContext)({
6
- selectedModal: null,
5
+ // Keep modal state separate from its stable setter so opening a modal only
6
+ // updates consumers that need to render the selected modal.
7
+ exports.SelectedModalContext = (0, react_1.createContext)(null);
8
+ exports.SetSelectedModalContext = (0, react_1.createContext)({
7
9
  setSelectedModal: () => undefined,
8
10
  });
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.505",
6
+ "version": "4.0.506",
7
7
  "description": "APIs for interacting with the Remotion Studio",
8
8
  "main": "dist",
9
9
  "scripts": {
@@ -24,17 +24,17 @@
24
24
  "react-dom": ">=16.8.0"
25
25
  },
26
26
  "dependencies": {
27
- "@remotion/studio-protocol": "4.0.505",
27
+ "@remotion/studio-protocol": "4.0.506",
28
28
  "semver": "7.5.3",
29
- "remotion": "4.0.505",
30
- "@remotion/captions": "4.0.505",
31
- "@remotion/player": "4.0.505",
32
- "@remotion/media-utils": "4.0.505",
33
- "@remotion/renderer": "4.0.505",
34
- "@remotion/web-renderer": "4.0.505",
35
- "@remotion/studio-shared": "4.0.505",
36
- "@remotion/timeline-utils": "4.0.505",
37
- "@remotion/zod-types": "4.0.505",
29
+ "remotion": "4.0.506",
30
+ "@remotion/captions": "4.0.506",
31
+ "@remotion/player": "4.0.506",
32
+ "@remotion/media-utils": "4.0.506",
33
+ "@remotion/renderer": "4.0.506",
34
+ "@remotion/web-renderer": "4.0.506",
35
+ "@remotion/studio-shared": "4.0.506",
36
+ "@remotion/timeline-utils": "4.0.506",
37
+ "@remotion/zod-types": "4.0.506",
38
38
  "@jridgewell/trace-mapping": "0.3.31",
39
39
  "mediabunny": "1.50.8",
40
40
  "memfs": "3.4.3",
@@ -45,7 +45,7 @@
45
45
  "react": "19.2.3",
46
46
  "react-dom": "19.2.3",
47
47
  "@types/semver": "7.5.3",
48
- "@remotion/eslint-config-internal": "4.0.505",
48
+ "@remotion/eslint-config-internal": "4.0.506",
49
49
  "eslint": "9.19.0",
50
50
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
51
51
  },