@remotion/studio 4.0.506 → 4.0.507

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 (119) hide show
  1. package/dist/api/copy-render-output-to-asset.d.ts +4 -0
  2. package/dist/api/copy-render-output-to-asset.js +11 -0
  3. package/dist/components/AssetSelector.js +19 -4
  4. package/dist/components/AssetSelectorItem.js +2 -2
  5. package/dist/components/CodingAgentIcon.d.ts +4 -0
  6. package/dist/components/CodingAgentIcon.js +17 -0
  7. package/dist/components/ConfigureDefaultEditorModal.d.ts +1 -3
  8. package/dist/components/ConfigureDefaultEditorModal.js +67 -77
  9. package/dist/components/ConfigureLicenseModal.d.ts +1 -4
  10. package/dist/components/ConfigureLicenseModal.js +89 -81
  11. package/dist/components/ContextMenu.js +10 -8
  12. package/dist/components/EditorContexts.js +6 -5
  13. package/dist/components/ExpandedTracksProvider.js +10 -53
  14. package/dist/components/InspectorLocationCopy.js +8 -8
  15. package/dist/components/InspectorOpenInEditor.d.ts +1 -0
  16. package/dist/components/InspectorOpenInEditor.js +39 -49
  17. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +3 -0
  18. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +22 -4
  19. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +1 -1
  20. package/dist/components/Menu/MenuSectionHeader.d.ts +4 -0
  21. package/dist/components/Menu/MenuSectionHeader.js +20 -0
  22. package/dist/components/Menu/SubMenu.js +13 -2
  23. package/dist/components/Menu/menu-tree-context.d.ts +3 -0
  24. package/dist/components/Menu/menu-tree-context.js +13 -0
  25. package/dist/components/NewComposition/ComboBox.d.ts +6 -1
  26. package/dist/components/NewComposition/MenuContent.js +27 -19
  27. package/dist/components/NewComposition/menu-typeahead.js +2 -2
  28. package/dist/components/Preview.js +29 -4
  29. package/dist/components/RenderModal/SchemaEditor/ZodEnumEditor.d.ts +1 -0
  30. package/dist/components/RenderModal/SchemaEditor/ZodEnumEditor.js +2 -2
  31. package/dist/components/RenderModal/SchemaEditor/ZodOrNullishEditor.js +3 -3
  32. package/dist/components/RenderModal/SchemaEditor/ZodSwitch.js +1 -1
  33. package/dist/components/RenderModal/ServerRenderModal.js +4 -0
  34. package/dist/components/RenderQueue/RenderQueueItem.js +8 -2
  35. package/dist/components/RenderQueue/actions.d.ts +4 -2
  36. package/dist/components/RenderQueue/actions.js +4 -2
  37. package/dist/components/RenderQueue/index.js +3 -4
  38. package/dist/components/RenderQueue/use-render-output-file-drag.d.ts +8 -0
  39. package/dist/components/RenderQueue/use-render-output-file-drag.js +121 -0
  40. package/dist/components/SegmentedControl.js +0 -1
  41. package/dist/components/SelectedOutlineElement.d.ts +14 -17
  42. package/dist/components/SelectedOutlineElement.js +112 -930
  43. package/dist/components/SelectedOutlineKeyboardControls.d.ts +7 -0
  44. package/dist/components/SelectedOutlineKeyboardControls.js +261 -0
  45. package/dist/components/SelectedOutlineOverlay.d.ts +6 -13
  46. package/dist/components/SelectedOutlineOverlay.js +349 -864
  47. package/dist/components/SelectedOutlinePolygon.d.ts +25 -0
  48. package/dist/components/SelectedOutlinePolygon.js +359 -0
  49. package/dist/components/SelectedOutlineRenderer.d.ts +18 -0
  50. package/dist/components/SelectedOutlineRenderer.js +208 -0
  51. package/dist/components/SelectedOutlineRotationCornerHandle.d.ts +16 -0
  52. package/dist/components/SelectedOutlineRotationCornerHandle.js +269 -0
  53. package/dist/components/SelectedOutlineScaleEdgeLine.d.ts +16 -0
  54. package/dist/components/SelectedOutlineScaleEdgeLine.js +211 -0
  55. package/dist/components/SelectedOutlineSnapIndicators.d.ts +9 -0
  56. package/dist/components/SelectedOutlineSnapIndicators.js +29 -0
  57. package/dist/components/SelectedOutlineTransformOriginHandle.d.ts +9 -0
  58. package/dist/components/SelectedOutlineTransformOriginHandle.js +286 -0
  59. package/dist/components/SelectedOutlineUvControls.d.ts +3 -9
  60. package/dist/components/SelectedOutlineUvControls.js +57 -12
  61. package/dist/components/SettingsContext.d.ts +15 -0
  62. package/dist/components/SettingsContext.js +116 -0
  63. package/dist/components/SettingsModal.js +10 -4
  64. package/dist/components/SettingsModalFooter.d.ts +1 -3
  65. package/dist/components/SettingsModalFooter.js +4 -6
  66. package/dist/components/ShowOutlinesProvider.js +2 -3
  67. package/dist/components/Timeline/EasingEditorModal.js +66 -22
  68. package/dist/components/Timeline/Timeline.js +22 -5
  69. package/dist/components/Timeline/TimelineDuplicateCount.d.ts +4 -0
  70. package/dist/components/Timeline/TimelineDuplicateCount.js +28 -0
  71. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +3 -23
  72. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.d.ts +4 -2
  73. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.js +11 -1
  74. package/dist/components/Timeline/TimelineSequence.js +28 -25
  75. package/dist/components/Timeline/TimelineSequenceItem.js +49 -27
  76. package/dist/components/Timeline/TimelineTrack.js +2 -1
  77. package/dist/components/Timeline/get-sequence-context-menu-items.d.ts +6 -3
  78. package/dist/components/Timeline/get-sequence-context-menu-items.js +58 -53
  79. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +36 -4
  80. package/dist/components/Timeline/{use-open-sequence-in-editor.d.ts → use-open-sequence-in-apps.d.ts} +4 -1
  81. package/dist/components/Timeline/{use-open-sequence-in-editor.js → use-open-sequence-in-apps.js} +20 -4
  82. package/dist/components/Timeline/use-timeline-expanded-tree.d.ts +4 -0
  83. package/dist/components/Timeline/use-timeline-expanded-tree.js +45 -1
  84. package/dist/components/get-open-in-menu-items.d.ts +12 -0
  85. package/dist/components/get-open-in-menu-items.js +83 -0
  86. package/dist/components/selected-outline-measurement.d.ts +2 -2
  87. package/dist/components/selected-outline-order.d.ts +12 -0
  88. package/dist/components/selected-outline-order.js +251 -0
  89. package/dist/components/selected-outline-types.d.ts +9 -10
  90. package/dist/components/svg-point-to-client-point.d.ts +2 -0
  91. package/dist/components/svg-point-to-client-point.js +10 -0
  92. package/dist/components/use-auto-save-config.d.ts +8 -0
  93. package/dist/components/use-auto-save-config.js +74 -0
  94. package/dist/components/use-default-editor-info.d.ts +1 -0
  95. package/dist/components/use-default-editor-info.js +10 -30
  96. package/dist/esm/{chunk-jefhcs5z.js → chunk-fgedsvhb.js} +1 -2
  97. package/dist/esm/{chunk-b49ec3nz.js → chunk-ptnd65a9.js} +10602 -9364
  98. package/dist/esm/internals.mjs +10601 -9363
  99. package/dist/esm/previewEntry.mjs +10462 -9224
  100. package/dist/esm/renderEntry.mjs +2 -2
  101. package/dist/helpers/are-sequence-node-path-infos-equal.d.ts +2 -0
  102. package/dist/helpers/are-sequence-node-path-infos-equal.js +27 -0
  103. package/dist/helpers/calculate-timeline.js +3 -3
  104. package/dist/helpers/client-id.js +8 -1
  105. package/dist/helpers/format-file-location.d.ts +1 -1
  106. package/dist/helpers/format-file-location.js +3 -3
  107. package/dist/helpers/migrate-expanded-tracks-for-subscription-key.js +3 -3
  108. package/dist/helpers/open-in-editor.d.ts +1 -0
  109. package/dist/helpers/open-in-editor.js +5 -1
  110. package/dist/helpers/studio-runtime-config.js +3 -0
  111. package/dist/helpers/timeline-node-path-key.d.ts +2 -0
  112. package/dist/helpers/timeline-node-path-key.js +3 -1
  113. package/dist/helpers/use-asset-drag-events.d.ts +2 -1
  114. package/dist/helpers/use-asset-drag-events.js +14 -6
  115. package/dist/helpers/use-menu-structure.js +2 -2
  116. package/dist/helpers/use-runtime-values.d.ts +1 -3
  117. package/dist/state/timeline-sequence-hover.d.ts +9 -3
  118. package/dist/state/timeline-sequence-hover.js +63 -12
  119. package/package.json +12 -12
@@ -44,6 +44,7 @@ const react_dom_1 = __importDefault(require("react-dom"));
44
44
  const mobile_layout_1 = require("../helpers/mobile-layout");
45
45
  const noop_1 = require("../helpers/noop");
46
46
  const z_index_1 = require("../state/z-index");
47
+ const menu_tree_context_1 = require("./Menu/menu-tree-context");
47
48
  const portals_1 = require("./Menu/portals");
48
49
  const styles_1 = require("./Menu/styles");
49
50
  const MenuContent_1 = require("./NewComposition/MenuContent");
@@ -70,8 +71,7 @@ const notifyContextMenuOpened = (id) => {
70
71
  detail: id,
71
72
  }));
72
73
  };
73
- const ContextMenuPortal = ({ sizeSource, currentZIndex, onHide, opened }) => {
74
- const menuRef = (0, react_1.useRef)(null);
74
+ const ContextMenuPortal = ({ menuTreeId, sizeSource, currentZIndex, onHide, opened }) => {
75
75
  const size = player_1.PlayerInternals.useElementSize(sizeSource, {
76
76
  triggerOnWindowResize: true,
77
77
  shouldApplyCssTransforms: true,
@@ -138,11 +138,11 @@ const ContextMenuPortal = ({ sizeSource, currentZIndex, onHide, opened }) => {
138
138
  }, []);
139
139
  (0, react_1.useEffect)(() => {
140
140
  const dismissWithoutClickThrough = (event) => {
141
- var _a;
142
141
  if (event.button !== 0) {
143
142
  return;
144
143
  }
145
- if ((_a = menuRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target)) {
144
+ const target = event.target;
145
+ if ((0, menu_tree_context_1.isNodeInMenuTree)(target, menuTreeId)) {
146
146
  return;
147
147
  }
148
148
  event.preventDefault();
@@ -154,7 +154,7 @@ const ContextMenuPortal = ({ sizeSource, currentZIndex, onHide, opened }) => {
154
154
  return () => {
155
155
  window.removeEventListener('pointerdown', dismissWithoutClickThrough, true);
156
156
  };
157
- }, [onHide]);
157
+ }, [menuTreeId, onHide]);
158
158
  // Prevent deselection of a selected item
159
159
  const onMenuPointerDown = (0, react_1.useCallback)((e) => {
160
160
  e.stopPropagation();
@@ -162,11 +162,12 @@ const ContextMenuPortal = ({ sizeSource, currentZIndex, onHide, opened }) => {
162
162
  if (!portalStyle) {
163
163
  return null;
164
164
  }
165
- return react_dom_1.default.createPortal(jsx_runtime_1.jsx("div", { style: contextMenuFullScreenOverlay, children: jsx_runtime_1.jsx("div", { style: contextMenuOuterPortal, className: "css-reset", children: jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onOutsideClick: onHide, onEscape: onHide, outsideClickButton: "primary", children: jsx_runtime_1.jsx("div", { ref: menuRef, style: portalStyle, onPointerDown: onMenuPointerDown, children: jsx_runtime_1.jsx(MenuContent_1.MenuContent, { onNextMenu: noop_1.noop, onPreviousMenu: noop_1.noop, values: opened.values, onHide: onHide, leaveLeftSpace: true, preselectIndex: false, topItemCanBeUnselected: false, fixedHeight: null }) }) }) }) }), (0, portals_1.getPortal)(currentZIndex));
165
+ return react_dom_1.default.createPortal(jsx_runtime_1.jsx("div", { style: contextMenuFullScreenOverlay, children: jsx_runtime_1.jsx("div", { style: contextMenuOuterPortal, className: "css-reset", children: jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onOutsideClick: onHide, onEscape: onHide, outsideClickButton: "primary", children: jsx_runtime_1.jsx("div", { "data-remotion-menu-tree-id": menuTreeId, style: portalStyle, onPointerDown: onMenuPointerDown, children: jsx_runtime_1.jsx(menu_tree_context_1.MenuTreeContext.Provider, { value: menuTreeId, children: jsx_runtime_1.jsx(MenuContent_1.MenuContent, { onNextMenu: noop_1.noop, onPreviousMenu: noop_1.noop, values: opened.values, onHide: onHide, leaveLeftSpace: true, preselectIndex: false, topItemCanBeUnselected: false, fixedHeight: null }) }) }) }) }) }), (0, portals_1.getPortal)(currentZIndex));
166
166
  };
167
167
  exports.ContextMenu = react_1.default.forwardRef(({ children, getItems, style = undefined, className = undefined, onPointerDown = undefined, }, forwardedRef) => {
168
168
  const ref = (0, react_1.useRef)(null);
169
169
  const idRef = (0, react_1.useRef)(nextContextMenuId++);
170
+ const menuTreeIdRef = (0, react_1.useRef)((0, menu_tree_context_1.getNextMenuTreeId)());
170
171
  const invocationRef = (0, react_1.useRef)(0);
171
172
  const getItemsRef = (0, react_1.useRef)(getItems);
172
173
  getItemsRef.current = getItems;
@@ -232,11 +233,12 @@ exports.ContextMenu = react_1.default.forwardRef(({ children, getItems, style =
232
233
  };
233
234
  }, [onHide]);
234
235
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
235
- jsx_runtime_1.jsx("div", { ref: setRef, onContextMenu: () => false, style: style, className: className, onPointerDown: onPointerDown, children: children }), opened.type === 'open' ? (jsx_runtime_1.jsx(ContextMenuPortal, { sizeSource: ref, currentZIndex: currentZIndex, onHide: onHide, opened: opened })) : null] }));
236
+ jsx_runtime_1.jsx("div", { ref: setRef, onContextMenu: () => false, style: style, className: className, onPointerDown: onPointerDown, children: children }), opened.type === 'open' ? (jsx_runtime_1.jsx(ContextMenuPortal, { menuTreeId: menuTreeIdRef.current, sizeSource: ref, currentZIndex: currentZIndex, onHide: onHide, opened: opened })) : null] }));
236
237
  });
237
238
  exports.ContextMenu.displayName = 'ContextMenu';
238
239
  const ContextMenuForTarget = ({ triggerRef, getItems }) => {
239
240
  const idRef = (0, react_1.useRef)(nextContextMenuId++);
241
+ const menuTreeIdRef = (0, react_1.useRef)((0, menu_tree_context_1.getNextMenuTreeId)());
240
242
  const invocationRef = (0, react_1.useRef)(0);
241
243
  const getItemsRef = (0, react_1.useRef)(getItems);
242
244
  getItemsRef.current = getItems;
@@ -297,6 +299,6 @@ const ContextMenuForTarget = ({ triggerRef, getItems }) => {
297
299
  window.removeEventListener(contextMenuOpenedEvent, onOtherContextMenuOpened);
298
300
  };
299
301
  }, [onHide]);
300
- return opened.type === 'open' ? (jsx_runtime_1.jsx(ContextMenuPortal, { sizeSource: body, currentZIndex: currentZIndex, onHide: onHide, opened: opened })) : null;
302
+ return opened.type === 'open' ? (jsx_runtime_1.jsx(ContextMenuPortal, { menuTreeId: menuTreeIdRef.current, sizeSource: body, currentZIndex: currentZIndex, onHide: onHide, opened: opened })) : null;
301
303
  };
302
304
  exports.ContextMenuForTarget = ContextMenuForTarget;
@@ -18,6 +18,7 @@ const ModalsProvider_1 = require("./ModalsProvider");
18
18
  const ClientRenderQueueProcessor_1 = require("./RenderQueue/ClientRenderQueueProcessor");
19
19
  const context_1 = require("./RenderQueue/context");
20
20
  const SetTimelineInOutProvider_1 = require("./SetTimelineInOutProvider");
21
+ const SettingsContext_1 = require("./SettingsContext");
21
22
  const ShowGuidesProvider_1 = require("./ShowGuidesProvider");
22
23
  const ShowOutlinesProvider_1 = require("./ShowOutlinesProvider");
23
24
  const ShowRulersProvider_1 = require("./ShowRulersProvider");
@@ -25,10 +26,10 @@ const SnappingProvider_1 = require("./SnappingProvider");
25
26
  const VisualControlsUndoSync_1 = require("./VisualControls/VisualControlsUndoSync");
26
27
  const ZoomGesturesProvider_1 = require("./ZoomGesturesProvider");
27
28
  const EditorContexts = ({ children }) => {
28
- return (jsx_runtime_1.jsx(get_zod_if_possible_1.ZodProvider, { children: jsx_runtime_1.jsx(VisualControls_1.VisualControlsProvider, { children: jsx_runtime_1.jsxs(client_id_1.PreviewServerConnection, { children: [
29
- jsx_runtime_1.jsx(VisualControlsUndoSync_1.VisualControlsUndoSync, {}), jsx_runtime_1.jsxs(context_1.RenderQueueContextProvider, { children: [
30
- jsx_runtime_1.jsx(ClientRenderQueueProcessor_1.ClientRenderQueueProcessor, {}), jsx_runtime_1.jsx(keybindings_1.KeybindingContextProvider, { children: jsx_runtime_1.jsx(CheckerboardProvider_1.CheckerboardProvider, { children: jsx_runtime_1.jsx(ZoomGesturesProvider_1.ZoomGesturesProvider, { children: jsx_runtime_1.jsx(ShowRulersProvider_1.ShowRulersProvider, { children: jsx_runtime_1.jsx(ShowGuidesProvider_1.ShowGuidesProvider, { children: jsx_runtime_1.jsx(ShowOutlinesProvider_1.ShowOutlinesProvider, { children: jsx_runtime_1.jsx(SnappingProvider_1.SnappingProvider, { children: jsx_runtime_1.jsx(preview_size_1.PreviewSizeProvider, { children: jsx_runtime_1.jsx(ModalsProvider_1.ModalsProvider, { children: jsx_runtime_1.jsx(MediaVolumeProvider_1.MediaVolumeProvider, { children: jsx_runtime_1.jsx(player_1.PlayerInternals.PlayerEmitterProvider, { currentPlaybackRate: null, children: jsx_runtime_1.jsx(sidebar_1.SidebarContextProvider, { children: jsx_runtime_1.jsx(folders_1.FolderContextProvider, { children: jsx_runtime_1.jsx(highest_z_index_1.HighestZIndexProvider, { children: jsx_runtime_1.jsx(SetTimelineInOutProvider_1.SetTimelineInOutProvider, { children: jsx_runtime_1.jsx(ExpandedTracksProvider_1.ExpandedTracksProvider, { children: children }) }) }) }) }) }) }) }) }) }) }) }) }) }) }) })
31
- ] })
32
- ] }) }) }));
29
+ return (jsx_runtime_1.jsx(get_zod_if_possible_1.ZodProvider, { children: jsx_runtime_1.jsx(VisualControls_1.VisualControlsProvider, { children: jsx_runtime_1.jsx(client_id_1.PreviewServerConnection, { children: jsx_runtime_1.jsxs(SettingsContext_1.SettingsProvider, { children: [
30
+ jsx_runtime_1.jsx(VisualControlsUndoSync_1.VisualControlsUndoSync, {}), jsx_runtime_1.jsxs(context_1.RenderQueueContextProvider, { children: [
31
+ jsx_runtime_1.jsx(ClientRenderQueueProcessor_1.ClientRenderQueueProcessor, {}), jsx_runtime_1.jsx(keybindings_1.KeybindingContextProvider, { children: jsx_runtime_1.jsx(CheckerboardProvider_1.CheckerboardProvider, { children: jsx_runtime_1.jsx(ZoomGesturesProvider_1.ZoomGesturesProvider, { children: jsx_runtime_1.jsx(ShowRulersProvider_1.ShowRulersProvider, { children: jsx_runtime_1.jsx(ShowGuidesProvider_1.ShowGuidesProvider, { children: jsx_runtime_1.jsx(ShowOutlinesProvider_1.ShowOutlinesProvider, { children: jsx_runtime_1.jsx(SnappingProvider_1.SnappingProvider, { children: jsx_runtime_1.jsx(preview_size_1.PreviewSizeProvider, { children: jsx_runtime_1.jsx(ModalsProvider_1.ModalsProvider, { children: jsx_runtime_1.jsx(MediaVolumeProvider_1.MediaVolumeProvider, { children: jsx_runtime_1.jsx(player_1.PlayerInternals.PlayerEmitterProvider, { currentPlaybackRate: null, children: jsx_runtime_1.jsx(sidebar_1.SidebarContextProvider, { children: jsx_runtime_1.jsx(folders_1.FolderContextProvider, { children: jsx_runtime_1.jsx(highest_z_index_1.HighestZIndexProvider, { children: jsx_runtime_1.jsx(SetTimelineInOutProvider_1.SetTimelineInOutProvider, { children: jsx_runtime_1.jsx(ExpandedTracksProvider_1.ExpandedTracksProvider, { children: children }) }) }) }) }) }) }) }) }) }) }) }) }) }) }) })
32
+ ] })
33
+ ] }) }) }) }));
33
34
  };
34
35
  exports.EditorContexts = EditorContexts;
@@ -4,46 +4,11 @@ exports.ExpandedTracksProvider = exports.ExpandedTracksSetterContext = exports.E
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const migrate_expanded_tracks_for_subscription_key_1 = require("../helpers/migrate-expanded-tracks-for-subscription-key");
7
+ const persist_boolean_map_1 = require("../helpers/persist-boolean-map");
7
8
  const timeline_node_path_key_1 = require("../helpers/timeline-node-path-key");
8
- const SESSION_STORAGE_KEY = 'remotion.editor.expandedTracks';
9
- const onlyCollapsedTrackValues = (state) => {
10
- const result = {};
11
- for (const [key, value] of Object.entries(state)) {
12
- if (value === false) {
13
- result[key] = false;
14
- }
15
- }
16
- return result;
17
- };
9
+ const SESSION_STORAGE_KEY = 'remotion.editor.expandedTracks.v2';
18
10
  const loadExpandedTracks = () => {
19
- if (typeof window === 'undefined') {
20
- return {};
21
- }
22
- try {
23
- const raw = window.sessionStorage.getItem(SESSION_STORAGE_KEY);
24
- if (raw === null) {
25
- return {};
26
- }
27
- const parsed = JSON.parse(raw);
28
- if (!parsed || typeof parsed !== 'object') {
29
- return {};
30
- }
31
- return onlyCollapsedTrackValues(parsed);
32
- }
33
- catch (_a) {
34
- return {};
35
- }
36
- };
37
- const persistExpandedTracks = (state) => {
38
- if (typeof window === 'undefined') {
39
- return;
40
- }
41
- try {
42
- window.sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(onlyCollapsedTrackValues(state)));
43
- }
44
- catch (_a) {
45
- // Ignore quota errors or disabled storage.
46
- }
11
+ return (0, persist_boolean_map_1.loadPersistedBooleanMap)(SESSION_STORAGE_KEY);
47
12
  };
48
13
  exports.ExpandedTracksGetterContext = (0, react_1.createContext)({
49
14
  getIsExpanded: () => {
@@ -78,31 +43,23 @@ const ExpandedTracksProvider = ({ children }) => {
78
43
  let changed = false;
79
44
  const next = { ...prev };
80
45
  for (const key of keysToExpand) {
81
- if (next[key] === false) {
82
- delete next[key];
46
+ if (!next[key]) {
47
+ next[key] = true;
83
48
  changed = true;
84
49
  }
85
50
  }
86
51
  if (!changed) {
87
52
  return prev;
88
53
  }
89
- persistExpandedTracks(next);
54
+ (0, persist_boolean_map_1.persistBooleanMap)(SESSION_STORAGE_KEY, next);
90
55
  return next;
91
56
  });
92
57
  }, []);
93
58
  const toggleTrack = (0, react_1.useCallback)((nodePathInfo) => {
94
59
  setExpandedTracks((prev) => {
95
- var _a;
96
60
  const key = (0, timeline_node_path_key_1.timelineNodePathInfoToKey)(nodePathInfo);
97
- const next = { ...prev };
98
- const isExpanded = (_a = next[key]) !== null && _a !== void 0 ? _a : true;
99
- if (isExpanded) {
100
- next[key] = false;
101
- }
102
- else {
103
- delete next[key];
104
- }
105
- persistExpandedTracks(next);
61
+ const next = (0, persist_boolean_map_1.toggleBooleanMapKey)(prev, key);
62
+ (0, persist_boolean_map_1.persistBooleanMap)(SESSION_STORAGE_KEY, next);
106
63
  return next;
107
64
  });
108
65
  }, []);
@@ -112,14 +69,14 @@ const ExpandedTracksProvider = ({ children }) => {
112
69
  if (!next) {
113
70
  return prev;
114
71
  }
115
- persistExpandedTracks(next);
72
+ (0, persist_boolean_map_1.persistBooleanMap)(SESSION_STORAGE_KEY, next);
116
73
  return next;
117
74
  });
118
75
  }, []);
119
76
  const getterValue = (0, react_1.useMemo)(() => ({
120
77
  getIsExpanded: (nodePathInfo) => {
121
78
  var _a;
122
- return (_a = expandedTracks[(0, timeline_node_path_key_1.timelineNodePathInfoToKey)(nodePathInfo)]) !== null && _a !== void 0 ? _a : true;
79
+ return (_a = expandedTracks[(0, timeline_node_path_key_1.timelineNodePathInfoToKey)(nodePathInfo)]) !== null && _a !== void 0 ? _a : false;
123
80
  },
124
81
  }), [expandedTracks]);
125
82
  const setterValue = (0, react_1.useMemo)(() => ({
@@ -38,8 +38,8 @@ const icon = {
38
38
  const InspectorLocationCopy = ({ children, location, name, openInEditorLocation }) => {
39
39
  const [hovered, setHovered] = (0, react_1.useState)(false);
40
40
  const [focusedWithin, setFocusedWithin] = (0, react_1.useState)(false);
41
- const textToCopy = (0, react_1.useMemo)(() => {
42
- return (0, format_file_location_1.formatLocationForAgents)({
41
+ const contextForAgents = (0, react_1.useMemo)(() => {
42
+ return (0, format_file_location_1.formatContextForAgents)({
43
43
  location,
44
44
  name,
45
45
  root: window.remotion_cwd,
@@ -50,20 +50,20 @@ const InspectorLocationCopy = ({ children, location, name, openInEditorLocation
50
50
  }, []);
51
51
  const onCopy = (0, react_1.useCallback)((event) => {
52
52
  event.stopPropagation();
53
- if (!textToCopy) {
53
+ if (!contextForAgents) {
54
54
  return;
55
55
  }
56
- navigator.clipboard.writeText(textToCopy).catch((err) => {
56
+ navigator.clipboard.writeText(contextForAgents).catch((err) => {
57
57
  (0, NotificationCenter_1.showNotification)(`Could not copy to clipboard: ${err.message}`, 2000);
58
58
  });
59
- }, [textToCopy]);
59
+ }, [contextForAgents]);
60
60
  const showAction = hovered || focusedWithin;
61
- return (jsx_runtime_1.jsxs("div", { style: row, onPointerEnter: () => setHovered(true), onPointerLeave: () => setHovered(false), onFocus: () => setFocusedWithin(true), onBlur: () => setFocusedWithin(false), children: [
62
- jsx_runtime_1.jsx("div", { style: content, children: children }), textToCopy || openInEditorLocation ? (jsx_runtime_1.jsxs("div", { style: {
61
+ return (jsx_runtime_1.jsxs("div", { "aria-label": "Inspector source location", role: "group", style: row, onPointerEnter: () => setHovered(true), onPointerLeave: () => setHovered(false), onFocus: () => setFocusedWithin(true), onBlur: () => setFocusedWithin(false), children: [
62
+ jsx_runtime_1.jsx("div", { style: content, children: children }), contextForAgents || openInEditorLocation ? (jsx_runtime_1.jsxs("div", { style: {
63
63
  ...action,
64
64
  opacity: showAction ? 1 : 0,
65
65
  pointerEvents: showAction ? 'auto' : 'none',
66
66
  }, children: [
67
- jsx_runtime_1.jsx(InspectorOpenInEditor_1.InspectorOpenInEditor, { location: openInEditorLocation }), textToCopy ? (jsx_runtime_1.jsx(InlineAction_1.InlineAction, { variant: null, onClick: onCopy, renderAction: renderCopyAction, title: "Copy location for agents" })) : null] })) : null] }));
67
+ jsx_runtime_1.jsx(InspectorOpenInEditor_1.InspectorOpenInEditor, { contextForAgents: contextForAgents, location: openInEditorLocation }), contextForAgents ? (jsx_runtime_1.jsx(InlineAction_1.InlineAction, { variant: null, onClick: onCopy, renderAction: renderCopyAction, title: "Copy context for agents" })) : null] })) : null] }));
68
68
  };
69
69
  exports.InspectorLocationCopy = InspectorLocationCopy;
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import type { OriginalPosition } from '../error-overlay/react-overlay/utils/get-source-map';
3
3
  export declare const InspectorOpenInEditor: React.FC<{
4
+ readonly contextForAgents?: string | null;
4
5
  readonly location: OriginalPosition | null;
5
6
  readonly label?: React.ReactNode;
6
7
  }>;
@@ -10,6 +10,7 @@ const caret_1 = require("../icons/caret");
10
10
  const editor_1 = require("../icons/editor");
11
11
  const modals_1 = require("../state/modals");
12
12
  const z_index_1 = require("../state/z-index");
13
+ const get_open_in_menu_items_1 = require("./get-open-in-menu-items");
13
14
  const InlineDropdown_1 = require("./InlineDropdown");
14
15
  const NotificationCenter_1 = require("./Notifications/NotificationCenter");
15
16
  const use_default_editor_info_1 = require("./use-default-editor-info");
@@ -38,15 +39,8 @@ const mainButtonBase = {
38
39
  padding: '0 6px',
39
40
  whiteSpace: 'nowrap',
40
41
  };
41
- const menuLabel = {
42
- color: 'inherit',
43
- fontFamily: 'sans-serif',
44
- fontSize: 13,
45
- lineHeight: '16px',
46
- };
47
42
  const editorButtonIconSize = 18;
48
- const editorMenuIconSize = 18;
49
- const InspectorOpenInEditor = ({ label, location }) => {
43
+ const InspectorOpenInEditor = ({ contextForAgents = null, label, location }) => {
50
44
  var _a;
51
45
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
52
46
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.SetSelectedModalContext);
@@ -55,6 +49,7 @@ const InspectorOpenInEditor = ({ label, location }) => {
55
49
  const [dropdownOpened, setDropdownOpened] = (0, react_1.useState)(false);
56
50
  const editorPickerAvailable = (0, use_default_editor_info_1.canUseEditorPicker)(previewServerState.type === 'connected');
57
51
  const editorInfo = (0, use_default_editor_info_1.useDefaultEditorInfo)(editorPickerAvailable);
52
+ const codingAgentInfo = (0, use_default_editor_info_1.useDefaultCodingAgentInfo)(editorPickerAvailable);
58
53
  const openWithEditor = (0, react_1.useCallback)(async (editorId) => {
59
54
  if (!location) {
60
55
  return;
@@ -67,6 +62,17 @@ const InspectorOpenInEditor = ({ label, location }) => {
67
62
  }
68
63
  }, [location]);
69
64
  const preferredEditorId = (0, use_default_editor_info_1.getPreferredEditorId)(editorInfo);
65
+ const openWithCodingAgent = (0, react_1.useCallback)(async (codingAgentId, codingAgentName) => {
66
+ try {
67
+ const response = await (0, open_in_editor_1.openInCodingAgent)(codingAgentId, codingAgentId === 'copilot' ? null : contextForAgents);
68
+ if (!response.success) {
69
+ (0, NotificationCenter_1.showNotification)(`Could not open ${codingAgentName}`, 2000);
70
+ }
71
+ }
72
+ catch (err) {
73
+ (0, NotificationCenter_1.showNotification)(err.message, 2000);
74
+ }
75
+ }, [contextForAgents]);
70
76
  const editorName = (_a = window.remotion_editorName) !== null && _a !== void 0 ? _a : 'default editor';
71
77
  const canOpenDefault = location !== null && window.remotion_editorName !== null;
72
78
  const onOpenDefault = (0, react_1.useCallback)((event) => {
@@ -101,49 +107,33 @@ const InspectorOpenInEditor = ({ label, location }) => {
101
107
  return jsx_runtime_1.jsx(caret_1.CaretDown, { color: color, small: true });
102
108
  }, []);
103
109
  const menuItems = (0, react_1.useMemo)(() => {
104
- var _a;
105
- const alternateEditors = ((_a = editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors) !== null && _a !== void 0 ? _a : [])
106
- .filter((editor) => editor.id !== preferredEditorId)
107
- .map((editor) => ({
108
- id: `open-in-${editor.id}`,
109
- keyHint: null,
110
- label: jsx_runtime_1.jsx("span", { style: menuLabel, children: editor.name }),
111
- leftItem: jsx_runtime_1.jsx(editor_1.EditorIcon, { editorId: editor.id, size: editorMenuIconSize }),
112
- onClick: () => {
113
- openWithEditor(editor.id).catch(() => undefined);
110
+ return (0, get_open_in_menu_items_1.getOpenInMenuItems)({
111
+ codingAgentInfo,
112
+ editorDisabled: location === null,
113
+ editorInfo,
114
+ excludeCodingAgentId: null,
115
+ excludeEditorId: preferredEditorId,
116
+ onConfigureApps: () => {
117
+ var _a;
118
+ var _b;
119
+ setSelectedModal({
120
+ type: 'settings',
121
+ initialTab: 'apps',
122
+ initialPublicLicenseKey: (_b = (_a = window.remotion_renderDefaults) === null || _a === void 0 ? void 0 : _a.publicLicenseKey) !== null && _b !== void 0 ? _b : null,
123
+ });
124
+ },
125
+ onOpenInCodingAgent: (codingAgentId, codingAgentName) => {
126
+ openWithCodingAgent(codingAgentId, codingAgentName).catch(() => undefined);
114
127
  },
115
- quickSwitcherLabel: null,
116
- subMenu: null,
117
- type: 'item',
118
- value: editor.id,
119
- }));
120
- const settingsItems = [
121
- ...(alternateEditors.length > 0
122
- ? [{ type: 'divider', id: 'editor-settings-divider' }]
123
- : []),
124
- {
125
- id: 'set-default-editor',
126
- keyHint: null,
127
- label: jsx_runtime_1.jsx("span", { style: menuLabel, children: "Set default editor..." }),
128
- leftItem: null,
129
- onClick: () => {
130
- var _a;
131
- var _b;
132
- setSelectedModal({
133
- type: 'settings',
134
- initialTab: 'apps',
135
- initialPublicLicenseKey: (_b = (_a = window.remotion_renderDefaults) === null || _a === void 0 ? void 0 : _a.publicLicenseKey) !== null && _b !== void 0 ? _b : null,
136
- });
137
- },
138
- quickSwitcherLabel: null,
139
- subMenu: null,
140
- type: 'item',
141
- value: 'set-default-editor',
128
+ onOpenInEditor: (editorId) => {
129
+ openWithEditor(editorId).catch(() => undefined);
142
130
  },
143
- ];
144
- return [...alternateEditors, ...settingsItems];
131
+ });
145
132
  }, [
146
- editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors,
133
+ codingAgentInfo,
134
+ editorInfo,
135
+ location,
136
+ openWithCodingAgent,
147
137
  openWithEditor,
148
138
  preferredEditorId,
149
139
  setSelectedModal,
@@ -153,7 +143,7 @@ const InspectorOpenInEditor = ({ label, location }) => {
153
143
  }
154
144
  return (jsx_runtime_1.jsxs("div", { style: splitButton, onPointerEnter: () => setHovered(true), onPointerLeave: () => setHovered(false), children: [
155
145
  jsx_runtime_1.jsxs("button", { "aria-label": `Open in ${editorName}`, disabled: !canOpenDefault, onClick: onOpenDefault, style: mainButtonStyle, tabIndex: tabIndex, title: `Open in ${editorName}`, type: "button", children: [label, jsx_runtime_1.jsx(editor_1.EditorIcon, { editorId: preferredEditorId, size: editorButtonIconSize })
156
- ] }), jsx_runtime_1.jsx(InlineDropdown_1.InlineDropdown, { onOpenChange: setDropdownOpened, renderAction: renderDropdownAction, style: dropdownStyle, title: "Open in another editor", unhoveredColor: dropdownForegroundColor, values: menuItems, variant: "compact" })
146
+ ] }), jsx_runtime_1.jsx(InlineDropdown_1.InlineDropdown, { onOpenChange: setDropdownOpened, renderAction: renderDropdownAction, style: dropdownStyle, title: "Open in another app", unhoveredColor: dropdownForegroundColor, values: menuItems, variant: "compact" })
157
147
  ] }));
158
148
  };
159
149
  exports.InspectorOpenInEditor = InspectorOpenInEditor;
@@ -11,6 +11,9 @@ export declare const SequenceInspectorHeader: React.FC<{
11
11
  readonly sourceLocation: SequenceInspectorSourceLocation;
12
12
  readonly track: TimelineTrackData;
13
13
  }>;
14
+ export declare const SequenceInspectorDuplicationSection: React.FC<{
15
+ readonly track: TimelineTrackData;
16
+ }>;
14
17
  export declare const SequenceInspectorSections: React.FC<{
15
18
  readonly track: TimelineTrackData;
16
19
  }>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SequenceInspectorSections = exports.SequenceInspectorHeader = exports.useSequenceInspectorSourceLocation = void 0;
3
+ exports.SequenceInspectorSections = exports.SequenceInspectorDuplicationSection = exports.SequenceInspectorHeader = exports.useSequenceInspectorSourceLocation = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const client_id_1 = require("../../helpers/client-id");
@@ -10,7 +10,7 @@ const InspectorInfoHeader_1 = require("../InspectorInfoHeader");
10
10
  const InspectorLocationCopy_1 = require("../InspectorLocationCopy");
11
11
  const InspectorSourceLocation_1 = require("../InspectorSourceLocation");
12
12
  const layout_1 = require("../layout");
13
- const use_open_sequence_in_editor_1 = require("../Timeline/use-open-sequence-in-editor");
13
+ const use_open_sequence_in_apps_1 = require("../Timeline/use-open-sequence-in-apps");
14
14
  const use_rename_sequence_1 = require("../Timeline/use-rename-sequence");
15
15
  const common_1 = require("./common");
16
16
  const ConnectedCompositionsSection_1 = require("./ConnectedCompositionsSection");
@@ -38,7 +38,7 @@ const defaultCursor = {
38
38
  cursor: 'default',
39
39
  };
40
40
  const useSequenceInspectorSourceLocation = (sequence) => {
41
- const { canOpenInEditor, openInEditor, originalLocation } = (0, use_open_sequence_in_editor_1.useOpenSequenceInEditor)(sequence);
41
+ const { canOpenInEditor, openInEditor, originalLocation } = (0, use_open_sequence_in_apps_1.useOpenSequenceInApps)(sequence);
42
42
  const validatedLocation = (0, react_1.useMemo)(() => {
43
43
  var _a;
44
44
  if (!originalLocation ||
@@ -99,11 +99,29 @@ const SequenceInspectorHeader = ({ sourceLocation, track }) => {
99
99
  ] }) }));
100
100
  };
101
101
  exports.SequenceInspectorHeader = SequenceInspectorHeader;
102
+ const SequenceInspectorDuplicationSection = ({ track }) => {
103
+ var _a;
104
+ var _b;
105
+ const numberOfInstances = (_b = (_a = track.nodePathInfo) === null || _a === void 0 ? void 0 : _a.numberOfSequencesWithThisNodePath) !== null && _b !== void 0 ? _b : 0;
106
+ if (numberOfInstances <= 1) {
107
+ return null;
108
+ }
109
+ return (jsx_runtime_1.jsx(common_1.InspectorSection, { header: jsx_runtime_1.jsxs("span", { style: {
110
+ color: 'inherit',
111
+ display: 'block',
112
+ fontFamily: 'inherit',
113
+ fontSize: 'inherit',
114
+ fontWeight: 'normal',
115
+ lineHeight: 'inherit',
116
+ margin: '2px 0',
117
+ }, children: [numberOfInstances, " instances"] }), children: null }));
118
+ };
119
+ exports.SequenceInspectorDuplicationSection = SequenceInspectorDuplicationSection;
102
120
  const SequenceInspectorSections = ({ track }) => {
103
121
  const sourceLocation = (0, exports.useSequenceInspectorSourceLocation)(track.sequence);
104
122
  const connectedCompositions = (0, ConnectedCompositionsSection_1.useConnectedCompositions)({ track });
105
123
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
106
- jsx_runtime_1.jsx(exports.SequenceInspectorHeader, { sourceLocation: sourceLocation, track: track }), connectedCompositions.length > 0 ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
124
+ jsx_runtime_1.jsx(exports.SequenceInspectorHeader, { sourceLocation: sourceLocation, track: track }), jsx_runtime_1.jsx(exports.SequenceInspectorDuplicationSection, { track: track }), connectedCompositions.length > 0 ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
107
125
  jsx_runtime_1.jsx(common_1.InspectorSectionDivider, {}), jsx_runtime_1.jsx(ConnectedCompositionsSection_1.ConnectedCompositionsSection, { connectedCompositions: connectedCompositions })
108
126
  ] })) : null] }));
109
127
  };
@@ -141,7 +141,7 @@ const SequenceExpandedInspector = ({ track, readOnlyStudio }) => {
141
141
  return jsx_runtime_1.jsx(common_1.InspectorMessage, { children: "Sequence inspector unavailable" });
142
142
  }
143
143
  return (jsx_runtime_1.jsxs("div", { style: styles_1.selectedContainer, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, onPointerDown: selectSequenceOnInspectorPointerDown, children: [
144
- jsx_runtime_1.jsx(SequenceInspectorHeader_1.SequenceInspectorHeader, { sourceLocation: sourceLocation, track: track }), connectedCompositions.length > 0 ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
144
+ jsx_runtime_1.jsx(SequenceInspectorHeader_1.SequenceInspectorHeader, { sourceLocation: sourceLocation, track: track }), jsx_runtime_1.jsx(SequenceInspectorHeader_1.SequenceInspectorDuplicationSection, { track: track }), connectedCompositions.length > 0 ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
145
145
  jsx_runtime_1.jsx(common_1.InspectorSectionDivider, {}), jsx_runtime_1.jsx(ConnectedCompositionsSection_1.ConnectedCompositionsSection, { connectedCompositions: connectedCompositions })
146
146
  ] })) : null, validatedLocation ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [jsx_runtime_1.jsx(InspectorSequenceSection_1.InspectorSequenceSection, { sequence: track.sequence, readOnlyStudio: readOnlyStudio, validatedLocation: validatedLocation, nodePathInfo: track.nodePathInfo, keyframeDisplayOffset: track.keyframeDisplayOffset, renderTransformControls: () => jsx_runtime_1.jsx(AlignmentControls_1.AlignmentControls, { track: track }) }), jsx_runtime_1.jsxs(common_1.InspectorActionSection, { children: [
147
147
  jsx_runtime_1.jsx(SplitSequenceAction, { selection: sequenceSelection, track: track }), jsx_runtime_1.jsx(SequenceSourceActions, { selection: sequenceSelection, track: track, validatedSource: validatedLocation.source })
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const MenuSectionHeader: React.FC<{
3
+ readonly children: string;
4
+ }>;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MenuSectionHeader = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const colors_1 = require("../../helpers/colors");
6
+ const sectionHeader = {
7
+ color: colors_1.WHITE_ALPHA_50,
8
+ fontSize: 10,
9
+ lineHeight: '12px',
10
+ paddingBottom: 2,
11
+ paddingLeft: 8,
12
+ paddingRight: 8,
13
+ paddingTop: 6,
14
+ userSelect: 'none',
15
+ WebkitUserSelect: 'none',
16
+ };
17
+ const MenuSectionHeader = ({ children }) => {
18
+ return jsx_runtime_1.jsx("div", { style: sectionHeader, children: children });
19
+ };
20
+ exports.MenuSectionHeader = MenuSectionHeader;
@@ -7,22 +7,33 @@ const mobile_layout_1 = require("../../helpers/mobile-layout");
7
7
  const noop_1 = require("../../helpers/noop");
8
8
  const z_index_1 = require("../../state/z-index");
9
9
  const MenuContent_1 = require("../NewComposition/MenuContent");
10
+ const menu_tree_context_1 = require("./menu-tree-context");
10
11
  const portals_1 = require("./portals");
11
12
  const SubMenuComponent = ({ portalStyle, subMenuActivated, subMenu, onQuitFullMenu, onQuitSubMenu, }) => {
12
13
  const mobileLayout = (0, mobile_layout_1.useMobileLayout)();
14
+ const menuTreeId = (0, react_1.useContext)(menu_tree_context_1.MenuTreeContext);
13
15
  const onOutsideClick = (0, react_1.useCallback)((e) => {
16
+ if (menuTreeId !== null) {
17
+ if ((0, menu_tree_context_1.isNodeInMenuTree)(e, menuTreeId)) {
18
+ onQuitSubMenu();
19
+ }
20
+ else {
21
+ onQuitFullMenu();
22
+ }
23
+ return;
24
+ }
14
25
  if (portals_1.portals.find((p) => p.contains(e)) || mobileLayout) {
15
26
  onQuitSubMenu();
16
27
  }
17
28
  else {
18
29
  onQuitFullMenu();
19
30
  }
20
- }, [mobileLayout, onQuitFullMenu, onQuitSubMenu]);
31
+ }, [menuTreeId, mobileLayout, onQuitFullMenu, onQuitSubMenu]);
21
32
  const onPointerDown = (0, react_1.useCallback)((e) => {
22
33
  // Prevent deselection of currently selected items
23
34
  e.stopPropagation();
24
35
  }, []);
25
- return (jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onEscape: onQuitFullMenu, onOutsideClick: onOutsideClick, children: jsx_runtime_1.jsx("div", { style: portalStyle, className: "css-reset", onPointerDown: onPointerDown, children: jsx_runtime_1.jsx(MenuContent_1.MenuContent, { onNextMenu: noop_1.noop, onPreviousMenu: onQuitSubMenu, values: subMenu.items, onHide: onQuitFullMenu, leaveLeftSpace: subMenu.leaveLeftSpace, preselectIndex: subMenuActivated === 'without-mouse' &&
36
+ return (jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onEscape: onQuitFullMenu, onOutsideClick: onOutsideClick, children: jsx_runtime_1.jsx("div", { "data-remotion-menu-tree-id": menuTreeId !== null && menuTreeId !== void 0 ? menuTreeId : undefined, style: portalStyle, className: "css-reset", onPointerDown: onPointerDown, children: jsx_runtime_1.jsx(MenuContent_1.MenuContent, { onNextMenu: noop_1.noop, onPreviousMenu: onQuitSubMenu, values: subMenu.items, onHide: onQuitFullMenu, leaveLeftSpace: subMenu.leaveLeftSpace, preselectIndex: subMenuActivated === 'without-mouse' &&
26
37
  typeof subMenu.preselectIndex === 'number'
27
38
  ? subMenu.preselectIndex
28
39
  : false, topItemCanBeUnselected: false, fixedHeight: null }) }) }));
@@ -0,0 +1,3 @@
1
+ export declare const getNextMenuTreeId: () => number;
2
+ export declare const MenuTreeContext: import("react").Context<number | null>;
3
+ export declare const isNodeInMenuTree: (node: Node, menuTreeId: number) => boolean;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isNodeInMenuTree = exports.MenuTreeContext = exports.getNextMenuTreeId = void 0;
4
+ const react_1 = require("react");
5
+ let nextMenuTreeId = 0;
6
+ const getNextMenuTreeId = () => nextMenuTreeId++;
7
+ exports.getNextMenuTreeId = getNextMenuTreeId;
8
+ exports.MenuTreeContext = (0, react_1.createContext)(null);
9
+ const isNodeInMenuTree = (node, menuTreeId) => {
10
+ const element = node instanceof Element ? node : node.parentElement;
11
+ return ((element === null || element === void 0 ? void 0 : element.closest(`[data-remotion-menu-tree-id="${menuTreeId}"]`)) !== null);
12
+ };
13
+ exports.isNodeInMenuTree = isNodeInMenuTree;
@@ -4,6 +4,11 @@ type DividerItem = {
4
4
  type: 'divider';
5
5
  id: string;
6
6
  };
7
+ type SectionHeaderItem = {
8
+ type: 'section-header';
9
+ id: string;
10
+ label: string;
11
+ };
7
12
  export type SubMenu = {
8
13
  preselectIndex: number | false;
9
14
  leaveLeftSpace: boolean;
@@ -21,7 +26,7 @@ export type SelectionItem = {
21
26
  quickSwitcherLabel: string | null;
22
27
  disabled?: boolean;
23
28
  };
24
- export type ComboboxValue = DividerItem | SelectionItem;
29
+ export type ComboboxValue = DividerItem | SectionHeaderItem | SelectionItem;
25
30
  export declare const Combobox: React.FC<{
26
31
  readonly values: ComboboxValue[];
27
32
  readonly selectedId: string | number;