@remotion/studio 4.0.499 → 4.0.500

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 (132) hide show
  1. package/dist/components/AssetSelector.js +8 -6
  2. package/dist/components/AssetSelectorItem.d.ts +24 -0
  3. package/dist/components/AssetSelectorItem.js +113 -80
  4. package/dist/components/CompositionSelector.js +2 -32
  5. package/dist/components/ControlButton.js +1 -0
  6. package/dist/components/ExplorerPanel.js +2 -1
  7. package/dist/components/ExplorerPanelRef.d.ts +2 -0
  8. package/dist/components/GlobalKeybindings.js +7 -1
  9. package/dist/components/InlineAction.d.ts +2 -1
  10. package/dist/components/InlineAction.js +2 -2
  11. package/dist/components/InlineDropdown.d.ts +1 -1
  12. package/dist/components/InlineDropdown.js +3 -2
  13. package/dist/components/InspectorPanel/AlignmentControls.d.ts +2 -2
  14. package/dist/components/InspectorPanel/AlignmentControls.js +5 -2
  15. package/dist/components/InspectorPanel/CompositionInspector.js +8 -7
  16. package/dist/components/InspectorPanel/CompositionMetadata.js +170 -57
  17. package/dist/components/InspectorPanel/ConnectedCompositionsSection.d.ts +2 -2
  18. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +3 -3
  19. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +7 -7
  20. package/dist/components/InspectorPanel/common.d.ts +17 -4
  21. package/dist/components/InspectorPanel/common.js +60 -6
  22. package/dist/components/InspectorPanel/use-composition-actions.js +1 -0
  23. package/dist/components/InspectorPanel/use-track-for-selection.d.ts +1 -1
  24. package/dist/components/InspectorSequenceSection.js +43 -19
  25. package/dist/components/KeyboardShortcutsExplainer.js +4 -2
  26. package/dist/components/Menu/MenuItem.js +2 -1
  27. package/dist/components/MenuCompositionName.js +30 -7
  28. package/dist/components/MenuToolbar.d.ts +0 -1
  29. package/dist/components/MenuToolbar.js +8 -7
  30. package/dist/components/MobilePanel.d.ts +2 -1
  31. package/dist/components/MobilePanel.js +29 -25
  32. package/dist/components/ModalContainer.d.ts +1 -0
  33. package/dist/components/ModalContainer.js +2 -2
  34. package/dist/components/Modals.js +1 -1
  35. package/dist/components/NewComposition/DismissableModal.d.ts +1 -0
  36. package/dist/components/NewComposition/DismissableModal.js +2 -2
  37. package/dist/components/NewComposition/InputDragger.d.ts +7 -0
  38. package/dist/components/NewComposition/InputDragger.js +119 -8
  39. package/dist/components/OutlineToggle.d.ts +1 -3
  40. package/dist/components/OutlineToggle.js +2 -2
  41. package/dist/components/PreviewToolbar.js +10 -4
  42. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.d.ts +7 -0
  43. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.js +44 -0
  44. package/dist/components/QuickSwitcher/NoResults.d.ts +1 -1
  45. package/dist/components/QuickSwitcher/NoResults.js +1 -0
  46. package/dist/components/QuickSwitcher/QuickSwitcher.d.ts +5 -0
  47. package/dist/components/QuickSwitcher/QuickSwitcher.js +6 -2
  48. package/dist/components/QuickSwitcher/QuickSwitcherContent.d.ts +5 -0
  49. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +76 -12
  50. package/dist/components/QuickSwitcher/QuickSwitcherResult.d.ts +4 -0
  51. package/dist/components/QuickSwitcher/QuickSwitcherResult.js +11 -8
  52. package/dist/components/QuickSwitcher/asset-search.d.ts +9 -0
  53. package/dist/components/QuickSwitcher/asset-search.js +42 -0
  54. package/dist/components/SelectedOutlineCropControls.d.ts +8 -0
  55. package/dist/components/SelectedOutlineCropControls.js +299 -0
  56. package/dist/components/SelectedOutlineElement.js +83 -43
  57. package/dist/components/SelectedOutlineOverlay.d.ts +2 -2
  58. package/dist/components/SelectedOutlineOverlay.js +130 -8
  59. package/dist/components/SequencePropsSubscriptionProvider.d.ts +2 -0
  60. package/dist/components/SequencePropsSubscriptionProvider.js +31 -3
  61. package/dist/components/SidebarCollapserControls.d.ts +3 -1
  62. package/dist/components/SidebarCollapserControls.js +34 -29
  63. package/dist/components/SnappingToggle.d.ts +1 -3
  64. package/dist/components/SnappingToggle.js +2 -2
  65. package/dist/components/Timeline/TimelineAssetField.d.ts +9 -1
  66. package/dist/components/Timeline/TimelineAssetField.js +52 -100
  67. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +7 -3
  68. package/dist/components/Timeline/TimelineClipboardKeybindings.js +65 -38
  69. package/dist/components/Timeline/TimelineColorField.js +20 -1
  70. package/dist/components/Timeline/TimelineEffectPropItem.js +8 -77
  71. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +1 -0
  72. package/dist/components/Timeline/TimelineHeightContainer.d.ts +2 -2
  73. package/dist/components/Timeline/TimelineKeyframeTracksContext.d.ts +3 -3
  74. package/dist/components/Timeline/TimelineList.d.ts +2 -2
  75. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +7 -1
  76. package/dist/components/Timeline/TimelineSelection.d.ts +5 -5
  77. package/dist/components/Timeline/TimelineSelection.js +8 -6
  78. package/dist/components/Timeline/TimelineSequence.js +1 -5
  79. package/dist/components/Timeline/TimelineSequenceItem.js +57 -10
  80. package/dist/components/Timeline/TimelineSequencePropItem.js +27 -75
  81. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +0 -1
  82. package/dist/components/Timeline/TimelineTrack.d.ts +2 -2
  83. package/dist/components/Timeline/TimelineTracks.d.ts +2 -2
  84. package/dist/components/Timeline/find-track-for-node-path-info.d.ts +1 -1
  85. package/dist/components/Timeline/get-sequence-context-menu-items.js +14 -12
  86. package/dist/components/Timeline/reset-selected-timeline-props.js +18 -10
  87. package/dist/components/Timeline/save-effect-prop.d.ts +10 -0
  88. package/dist/components/Timeline/save-effect-prop.js +52 -1
  89. package/dist/components/Timeline/should-show-track-in-timeline.d.ts +2 -2
  90. package/dist/components/Timeline/timeline-asset-link.js +17 -1
  91. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.d.ts +4 -0
  92. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +9 -3
  93. package/dist/components/Timeline/use-timeline-height.d.ts +2 -2
  94. package/dist/components/TopPanel.js +2 -2
  95. package/dist/components/UndoRedoButtons.js +27 -5
  96. package/dist/components/composition-drop-preview.js +1 -0
  97. package/dist/components/menu-toolbar-height.d.ts +1 -0
  98. package/dist/components/menu-toolbar-height.js +4 -0
  99. package/dist/components/selected-outline-drag.d.ts +41 -4
  100. package/dist/components/selected-outline-drag.js +179 -2
  101. package/dist/components/selected-outline-geometry.d.ts +1 -0
  102. package/dist/components/selected-outline-measurement.d.ts +11 -0
  103. package/dist/components/selected-outline-measurement.js +64 -3
  104. package/dist/components/selected-outline-types.d.ts +44 -1
  105. package/dist/components/selected-outline-types.js +21 -1
  106. package/dist/error-overlay/remotion-overlay/Overlay.js +3 -3
  107. package/dist/error-overlay/remotion-overlay/ShortcutHint.js +2 -3
  108. package/dist/esm/{chunk-pk1zwsn1.js → chunk-dr1y1vm3.js} +8417 -7127
  109. package/dist/esm/internals.mjs +8417 -7127
  110. package/dist/esm/previewEntry.mjs +51241 -49953
  111. package/dist/esm/renderEntry.mjs +1 -1
  112. package/dist/helpers/calculate-timeline.d.ts +2 -2
  113. package/dist/helpers/calculate-timeline.js +8 -28
  114. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +3 -10
  115. package/dist/helpers/get-timeline-sequence-sort-key.js +5 -13
  116. package/dist/helpers/interactivity-enabled.d.ts +1 -0
  117. package/dist/helpers/interactivity-enabled.js +7 -2
  118. package/dist/helpers/is-mac.d.ts +1 -0
  119. package/dist/helpers/is-mac.js +4 -0
  120. package/dist/helpers/open-in-editor.d.ts +5 -1
  121. package/dist/helpers/open-in-editor.js +15 -1
  122. package/dist/helpers/sort-by-nonce-history.js +97 -19
  123. package/dist/helpers/use-keybinding.js +2 -3
  124. package/dist/helpers/use-menu-structure.js +10 -1
  125. package/dist/icons/caret.d.ts +1 -0
  126. package/dist/icons/caret.js +2 -2
  127. package/dist/icons/pen.d.ts +5 -0
  128. package/dist/icons/pen.js +8 -0
  129. package/dist/state/modals.d.ts +5 -0
  130. package/package.json +12 -12
  131. package/dist/helpers/get-timeline-sequence-hash.d.ts +0 -6
  132. package/dist/helpers/get-timeline-sequence-hash.js +0 -33
@@ -7,6 +7,8 @@ const remotion_1 = require("remotion");
7
7
  const colors_1 = require("../../helpers/colors");
8
8
  const is_composition_still_1 = require("../../helpers/is-composition-still");
9
9
  const resolved_stack_to_symbolicated_1 = require("../../helpers/resolved-stack-to-symbolicated");
10
+ const caret_1 = require("../../icons/caret");
11
+ const InlineDropdown_1 = require("../InlineDropdown");
10
12
  const InputDragger_1 = require("../NewComposition/InputDragger");
11
13
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
12
14
  const actions_1 = require("../RenderQueue/actions");
@@ -47,7 +49,57 @@ const dimensionsControls = {
47
49
  lineHeight: '16px',
48
50
  minWidth: 0,
49
51
  };
50
- const CompositionMetadataValue = ({ compositionId, computed, disabled, field, onPendingValue, onPendingValueAccepted, onPendingValueFailed, pendingValue, resolvedConfig, symbolicatedStack, value, }) => {
52
+ const presetButtonIcon = {
53
+ alignItems: 'center',
54
+ color: 'inherit',
55
+ display: 'flex',
56
+ flexShrink: 0,
57
+ height: 12,
58
+ justifyContent: 'center',
59
+ width: 12,
60
+ };
61
+ const presetDropdownContainer = {
62
+ display: 'flex',
63
+ flexShrink: 0,
64
+ };
65
+ const metadataLabelControls = {
66
+ alignItems: 'center',
67
+ color: 'inherit',
68
+ display: 'flex',
69
+ fontFamily: 'sans-serif',
70
+ fontSize: 13,
71
+ gap: 2,
72
+ lineHeight: '18px',
73
+ minWidth: 0,
74
+ };
75
+ const metadataLabelText = {
76
+ color: 'inherit',
77
+ fontFamily: 'sans-serif',
78
+ fontSize: 13,
79
+ lineHeight: '18px',
80
+ minWidth: 0,
81
+ overflow: 'hidden',
82
+ textOverflow: 'ellipsis',
83
+ whiteSpace: 'nowrap',
84
+ };
85
+ const dimensionPresets = [
86
+ { height: 1080, label: 'Full HD', width: 1920 },
87
+ { height: 1920, label: 'Full HD', width: 1080 },
88
+ { height: 720, label: 'HD', width: 1280 },
89
+ { height: 1280, label: 'HD', width: 720 },
90
+ { height: 1080, label: 'Square', width: 1080 },
91
+ ];
92
+ const frameRatePresets = [23.976, 24, 25, 29.97, 30, 50, 60];
93
+ const PresetDropdown = ({ disabled, title, values, visible }) => {
94
+ const renderAction = (0, react_1.useCallback)((color) => {
95
+ return (jsx_runtime_1.jsx("span", { style: presetButtonIcon, children: jsx_runtime_1.jsx(caret_1.CaretDown, { color: color, small: true }) }));
96
+ }, []);
97
+ return (jsx_runtime_1.jsx("div", { style: {
98
+ ...presetDropdownContainer,
99
+ visibility: visible ? 'visible' : 'hidden',
100
+ }, children: jsx_runtime_1.jsx(InlineDropdown_1.InlineDropdown, { disabled: disabled, renderAction: renderAction, title: title, values: values }) }));
101
+ };
102
+ const CompositionMetadataValue = ({ computed, disabled, field, onSave, pendingValue, value }) => {
51
103
  var _a;
52
104
  const [dragValue, setDragValue] = (0, react_1.useState)(null);
53
105
  const save = (0, react_1.useCallback)((newValue) => {
@@ -56,55 +108,9 @@ const CompositionMetadataValue = ({ compositionId, computed, disabled, field, on
56
108
  setDragValue(null);
57
109
  return;
58
110
  }
59
- if (symbolicatedStack === null) {
60
- setDragValue(null);
61
- (0, NotificationCenter_1.showNotification)('Could not determine where this composition is defined', 2000);
62
- return;
63
- }
64
- const codemod = {
65
- type: 'update-composition-metadata',
66
- idToUpdate: compositionId,
67
- newDurationInFrames: field === 'durationInFrames' ? newValue : null,
68
- newFps: field === 'fps' ? newValue : null,
69
- newHeight: field === 'height' ? newValue : null,
70
- newWidth: field === 'width' ? newValue : null,
71
- };
72
- const optimisticValue = {
73
- baseline: resolvedConfig,
74
- status: 'saving',
75
- value: newValue,
76
- };
77
- onPendingValue(field, optimisticValue);
78
111
  setDragValue(null);
79
- (0, actions_1.applyCodemod)({
80
- codemod,
81
- dryRun: false,
82
- signal: new AbortController().signal,
83
- symbolicatedStack,
84
- })
85
- .then((result) => {
86
- if (!result.success) {
87
- onPendingValueFailed(field, optimisticValue);
88
- (0, NotificationCenter_1.showNotification)(`Could not update composition ${field}: ${result.reason}`, 2000);
89
- return;
90
- }
91
- onPendingValueAccepted(field, optimisticValue);
92
- })
93
- .catch((error) => {
94
- onPendingValueFailed(field, optimisticValue);
95
- (0, NotificationCenter_1.showNotification)(`Could not update composition ${field}: ${error.message}`, 2000);
96
- });
97
- }, [
98
- compositionId,
99
- field,
100
- onPendingValue,
101
- onPendingValueAccepted,
102
- onPendingValueFailed,
103
- pendingValue === null || pendingValue === void 0 ? void 0 : pendingValue.value,
104
- resolvedConfig,
105
- symbolicatedStack,
106
- value,
107
- ]);
112
+ onSave({ [field]: newValue });
113
+ }, [field, onSave, pendingValue === null || pendingValue === void 0 ? void 0 : pendingValue.value, value]);
108
114
  const isFps = field === 'fps';
109
115
  const formatValue = (0, react_1.useCallback)((newValue) => {
110
116
  const numberValue = Number(newValue);
@@ -141,9 +147,6 @@ const CompositionMetadata = ({ compositionId, disabled, stack }) => {
141
147
  pending,
142
148
  }));
143
149
  }, [resolvedConfig]);
144
- const onPendingValue = (0, react_1.useCallback)((field, value) => {
145
- setPendingValues((pending) => ({ ...pending, [field]: value }));
146
- }, []);
147
150
  const onPendingValueAccepted = (0, react_1.useCallback)((field, value) => {
148
151
  setPendingValues((pending) => {
149
152
  if (resolvedConfigRef.current === null) {
@@ -160,6 +163,84 @@ const CompositionMetadata = ({ compositionId, disabled, stack }) => {
160
163
  const onPendingValueFailed = (0, react_1.useCallback)((field, value) => {
161
164
  setPendingValues((pending) => (0, optimistic_composition_metadata_1.failPendingCompositionMetadataValue)({ field, pending, value }));
162
165
  }, []);
166
+ const currentValues = (0, react_1.useMemo)(() => {
167
+ var _a, _b, _c, _d;
168
+ return ({
169
+ durationInFrames: (_a = video === null || video === void 0 ? void 0 : video.durationInFrames) !== null && _a !== void 0 ? _a : 0,
170
+ fps: (_b = video === null || video === void 0 ? void 0 : video.fps) !== null && _b !== void 0 ? _b : 0,
171
+ height: (_c = video === null || video === void 0 ? void 0 : video.height) !== null && _c !== void 0 ? _c : 0,
172
+ width: (_d = video === null || video === void 0 ? void 0 : video.width) !== null && _d !== void 0 ? _d : 0,
173
+ });
174
+ }, [video]);
175
+ const saveMetadata = (0, react_1.useCallback)((newValues) => {
176
+ var _a, _b, _c, _d;
177
+ if (disabled || resolvedConfig === null) {
178
+ return;
179
+ }
180
+ const changedFields = Object.keys(newValues).filter((field) => {
181
+ var _a;
182
+ var _b;
183
+ return newValues[field] !==
184
+ ((_b = (_a = pendingValues[field]) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : currentValues[field]);
185
+ });
186
+ if (changedFields.length === 0) {
187
+ return;
188
+ }
189
+ if (symbolicatedStack === null) {
190
+ (0, NotificationCenter_1.showNotification)('Could not determine where this composition is defined', 2000);
191
+ return;
192
+ }
193
+ const optimisticValues = changedFields.reduce((values, field) => {
194
+ values[field] = {
195
+ baseline: resolvedConfig,
196
+ status: 'saving',
197
+ value: newValues[field],
198
+ };
199
+ return values;
200
+ }, {});
201
+ const codemod = {
202
+ type: 'update-composition-metadata',
203
+ idToUpdate: compositionId,
204
+ newDurationInFrames: (_a = newValues.durationInFrames) !== null && _a !== void 0 ? _a : null,
205
+ newFps: (_b = newValues.fps) !== null && _b !== void 0 ? _b : null,
206
+ newHeight: (_c = newValues.height) !== null && _c !== void 0 ? _c : null,
207
+ newWidth: (_d = newValues.width) !== null && _d !== void 0 ? _d : null,
208
+ };
209
+ setPendingValues((pending) => ({ ...pending, ...optimisticValues }));
210
+ (0, actions_1.applyCodemod)({
211
+ codemod,
212
+ dryRun: false,
213
+ signal: new AbortController().signal,
214
+ symbolicatedStack,
215
+ })
216
+ .then((result) => {
217
+ if (!result.success) {
218
+ for (const field of changedFields) {
219
+ onPendingValueFailed(field, optimisticValues[field]);
220
+ }
221
+ (0, NotificationCenter_1.showNotification)(`Could not update composition metadata: ${result.reason}`, 2000);
222
+ return;
223
+ }
224
+ for (const field of changedFields) {
225
+ onPendingValueAccepted(field, optimisticValues[field]);
226
+ }
227
+ })
228
+ .catch((error) => {
229
+ for (const field of changedFields) {
230
+ onPendingValueFailed(field, optimisticValues[field]);
231
+ }
232
+ (0, NotificationCenter_1.showNotification)(`Could not update composition metadata: ${error.message}`, 2000);
233
+ });
234
+ }, [
235
+ compositionId,
236
+ currentValues,
237
+ disabled,
238
+ onPendingValueAccepted,
239
+ onPendingValueFailed,
240
+ pendingValues,
241
+ resolvedConfig,
242
+ symbolicatedStack,
243
+ ]);
163
244
  if (video === null || resolvedConfig === null) {
164
245
  return null;
165
246
  }
@@ -172,11 +253,43 @@ const CompositionMetadata = ({ compositionId, disabled, stack }) => {
172
253
  const fpsIsComputed = (metadataSource === null || metadataSource === void 0 ? void 0 : metadataSource.fps) === 'calculate-metadata';
173
254
  const durationIsComputed = (metadataSource === null || metadataSource === void 0 ? void 0 : metadataSource.durationInFrames) === 'calculate-metadata';
174
255
  const isStill = (0, is_composition_still_1.isCompositionStill)(video);
175
- return (jsx_runtime_1.jsxs("div", { style: compositionMetadataContainer, children: [
176
- jsx_runtime_1.jsx(common_1.InspectorDetailRow, { label: "Dimensions", children: jsx_runtime_1.jsxs("div", { style: dimensionsControls, children: [
177
- jsx_runtime_1.jsx(CompositionMetadataValue, { compositionId: compositionId, computed: widthIsComputed, disabled: disabled, field: "width", onPendingValue: onPendingValue, onPendingValueAccepted: onPendingValueAccepted, onPendingValueFailed: onPendingValueFailed, pendingValue: (_a = pendingValues.width) !== null && _a !== void 0 ? _a : null, resolvedConfig: resolvedConfig, symbolicatedStack: symbolicatedStack, value: video.width }), jsx_runtime_1.jsx(CompositionMetadataValue, { compositionId: compositionId, computed: heightIsComputed, disabled: disabled, field: "height", onPendingValue: onPendingValue, onPendingValueAccepted: onPendingValueAccepted, onPendingValueFailed: onPendingValueFailed, pendingValue: (_b = pendingValues.height) !== null && _b !== void 0 ? _b : null, resolvedConfig: resolvedConfig, symbolicatedStack: symbolicatedStack, value: video.height })
178
- ] }) }), isStill ? null : (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
179
- jsx_runtime_1.jsx(common_1.InspectorDetailRow, { label: "Frame rate", children: jsx_runtime_1.jsx(CompositionMetadataValue, { compositionId: compositionId, computed: fpsIsComputed, disabled: disabled, field: "fps", onPendingValue: onPendingValue, onPendingValueAccepted: onPendingValueAccepted, onPendingValueFailed: onPendingValueFailed, pendingValue: (_c = pendingValues.fps) !== null && _c !== void 0 ? _c : null, resolvedConfig: resolvedConfig, symbolicatedStack: symbolicatedStack, value: video.fps }) }), jsx_runtime_1.jsx(common_1.InspectorDetailRow, { label: "Duration", children: jsx_runtime_1.jsx(CompositionMetadataValue, { compositionId: compositionId, computed: durationIsComputed, disabled: disabled, field: "durationInFrames", onPendingValue: onPendingValue, onPendingValueAccepted: onPendingValueAccepted, onPendingValueFailed: onPendingValueFailed, pendingValue: (_d = pendingValues.durationInFrames) !== null && _d !== void 0 ? _d : null, resolvedConfig: resolvedConfig, symbolicatedStack: symbolicatedStack, value: video.durationInFrames }) })
256
+ const dimensionPresetValues = dimensionPresets.flatMap((preset, index) => [
257
+ ...(index === 2 || index === 4
258
+ ? [{ type: 'divider', id: `dimension-divider-${index}` }]
259
+ : []),
260
+ {
261
+ type: 'item',
262
+ id: `${preset.width}x${preset.height}`,
263
+ label: `${preset.width}x${preset.height} (${preset.label})`,
264
+ value: `${preset.width}x${preset.height}`,
265
+ onClick: () => {
266
+ saveMetadata({ height: preset.height, width: preset.width });
267
+ },
268
+ keyHint: null,
269
+ leftItem: null,
270
+ subMenu: null,
271
+ quickSwitcherLabel: null,
272
+ },
273
+ ]);
274
+ const frameRatePresetValues = frameRatePresets.map((fps) => ({
275
+ type: 'item',
276
+ id: String(fps),
277
+ label: `${fps} fps`,
278
+ value: fps,
279
+ onClick: () => {
280
+ saveMetadata({ fps });
281
+ },
282
+ keyHint: null,
283
+ leftItem: null,
284
+ subMenu: null,
285
+ quickSwitcherLabel: null,
286
+ }));
287
+ return (jsx_runtime_1.jsxs("div", { style: compositionMetadataContainer, children: [jsx_runtime_1.jsx(common_1.InspectorDetailRow, { label: (hovered) => (jsx_runtime_1.jsxs("div", { style: metadataLabelControls, children: [
288
+ jsx_runtime_1.jsx("span", { style: metadataLabelText, children: "Dimensions" }), disabled || widthIsComputed || heightIsComputed ? null : (jsx_runtime_1.jsx(PresetDropdown, { disabled: pendingValues.width !== undefined ||
289
+ pendingValues.height !== undefined, title: "Choose dimension preset", values: dimensionPresetValues, visible: hovered }))] })), children: jsx_runtime_1.jsxs("div", { style: dimensionsControls, children: [
290
+ jsx_runtime_1.jsx(CompositionMetadataValue, { computed: widthIsComputed, disabled: disabled, field: "width", onSave: saveMetadata, pendingValue: (_a = pendingValues.width) !== null && _a !== void 0 ? _a : null, value: video.width }), jsx_runtime_1.jsx(CompositionMetadataValue, { computed: heightIsComputed, disabled: disabled, field: "height", onSave: saveMetadata, pendingValue: (_b = pendingValues.height) !== null && _b !== void 0 ? _b : null, value: video.height })
291
+ ] }) }), isStill ? null : (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [jsx_runtime_1.jsx(common_1.InspectorDetailRow, { label: (hovered) => (jsx_runtime_1.jsxs("div", { style: metadataLabelControls, children: [
292
+ jsx_runtime_1.jsx("span", { style: metadataLabelText, children: "Frame rate" }), disabled || fpsIsComputed ? null : (jsx_runtime_1.jsx(PresetDropdown, { disabled: pendingValues.fps !== undefined, title: "Choose frame rate preset", values: frameRatePresetValues, visible: hovered }))] })), children: jsx_runtime_1.jsx("div", { style: dimensionsControls, children: jsx_runtime_1.jsx(CompositionMetadataValue, { computed: fpsIsComputed, disabled: disabled, field: "fps", onSave: saveMetadata, pendingValue: (_c = pendingValues.fps) !== null && _c !== void 0 ? _c : null, value: video.fps }) }) }), jsx_runtime_1.jsx(common_1.InspectorDetailRow, { label: "Duration", children: jsx_runtime_1.jsx(CompositionMetadataValue, { computed: durationIsComputed, disabled: disabled, field: "durationInFrames", onSave: saveMetadata, pendingValue: (_d = pendingValues.durationInFrames) !== null && _d !== void 0 ? _d : null, value: video.durationInFrames }) })
180
293
  ] }))] }));
181
294
  };
182
295
  exports.CompositionMetadata = CompositionMetadata;
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
2
  import type { _InternalTypes } from 'remotion';
3
- import type { TrackWithHash } from '../../helpers/get-timeline-sequence-sort-key';
3
+ import type { TimelineTrackData } from '../../helpers/get-timeline-sequence-sort-key';
4
4
  export declare const useConnectedCompositions: ({ track, }: {
5
- readonly track: TrackWithHash;
5
+ readonly track: TimelineTrackData;
6
6
  }) => import("remotion").AnyComposition[];
7
7
  export declare const ConnectedCompositionsSection: React.FC<{
8
8
  readonly connectedCompositions: readonly _InternalTypes['AnyComposition'][];
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { CodePosition } from '../../error-overlay/react-overlay/utils/get-source-map';
3
- import type { TrackWithHash } from '../../helpers/get-timeline-sequence-sort-key';
3
+ import type { TimelineTrackData } from '../../helpers/get-timeline-sequence-sort-key';
4
4
  type SequenceInspectorSourceLocation = {
5
5
  readonly canOpenInEditor: boolean;
6
6
  readonly openFileLocation: () => void;
@@ -9,9 +9,9 @@ type SequenceInspectorSourceLocation = {
9
9
  export declare const useSequenceInspectorSourceLocation: (sequence: import("remotion").TSequence) => SequenceInspectorSourceLocation;
10
10
  export declare const SequenceInspectorHeader: React.FC<{
11
11
  readonly sourceLocation: SequenceInspectorSourceLocation;
12
- readonly track: TrackWithHash;
12
+ readonly track: TimelineTrackData;
13
13
  }>;
14
14
  export declare const SequenceInspectorSections: React.FC<{
15
- readonly track: TrackWithHash;
15
+ readonly track: TimelineTrackData;
16
16
  }>;
17
17
  export {};
@@ -131,22 +131,22 @@ const SequenceExpandedInspector = ({ track }) => {
131
131
  }
132
132
  selectItems([sequenceSelection], { reveal: true });
133
133
  }, [selectItems, sequenceSelected, sequenceSelection]);
134
- if (previewServerState.type !== 'connected') {
134
+ if (previewServerState.type !== 'connected' &&
135
+ !window.remotion_isReadOnlyStudio) {
135
136
  return jsx_runtime_1.jsx(common_1.InspectorMessage, { children: "Studio server disconnected" });
136
137
  }
137
138
  if (!track.nodePathInfo ||
138
139
  sequenceSelection === null ||
139
- !(0, InspectorSequenceSection_1.hasSequenceControls)(track.sequence) ||
140
- !validatedLocation) {
140
+ !(0, InspectorSequenceSection_1.hasSequenceControls)(track.sequence)) {
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
144
  jsx_runtime_1.jsx(SequenceInspectorHeader_1.SequenceInspectorHeader, { sourceLocation: sourceLocation, 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
- ] })) : null, jsx_runtime_1.jsx(InspectorSequenceSection_1.InspectorSequenceSection, { sequence: track.sequence, 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
- jsx_runtime_1.jsx(SplitSequenceAction, { selection: sequenceSelection, track: track }), jsx_runtime_1.jsx(SequenceSourceActions, { selection: sequenceSelection, track: track, validatedSource: validatedLocation.source })
148
- ] })
149
- ] }));
146
+ ] })) : null, validatedLocation ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [jsx_runtime_1.jsx(InspectorSequenceSection_1.InspectorSequenceSection, { sequence: track.sequence, 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
+ jsx_runtime_1.jsx(SplitSequenceAction, { selection: sequenceSelection, track: track }), jsx_runtime_1.jsx(SequenceSourceActions, { selection: sequenceSelection, track: track, validatedSource: validatedLocation.source })
148
+ ] })
149
+ ] })) : (jsx_runtime_1.jsx(common_1.InspectorMessage, { children: "Source controls unavailable" }))] }));
150
150
  };
151
151
  const SequenceSelectionInspector = ({ selection }) => {
152
152
  const track = (0, use_track_for_selection_1.useTrackForSelection)(selection);
@@ -21,18 +21,31 @@ export declare const InspectorMessage: React.FC<{
21
21
  readonly children: React.ReactNode;
22
22
  }>;
23
23
  export declare const InspectorDetailRow: React.FC<{
24
- readonly label: string;
24
+ readonly label: React.ReactNode | ((hovered: boolean) => React.ReactNode);
25
25
  readonly children: React.ReactNode;
26
26
  }>;
27
- export declare const InspectorInlineAction: React.FC<{
28
- readonly children: React.ReactNode;
27
+ export type InspectorInlineActionSegment = {
29
28
  readonly disabled: boolean;
30
29
  readonly onClick: React.MouseEventHandler<HTMLButtonElement>;
30
+ readonly renderIcon: (color: string) => React.ReactNode;
31
+ readonly title?: string;
32
+ };
33
+ export type InspectorInlineActionProps = {
34
+ readonly children: React.ReactNode;
35
+ readonly disabled: boolean;
36
+ readonly onClick: React.MouseEventHandler<HTMLButtonElement> | null;
31
37
  readonly renderIcon?: (color: string) => React.ReactNode;
32
38
  readonly size?: 'default' | 'compact';
33
39
  readonly style?: React.CSSProperties;
34
40
  readonly title?: string;
35
- }>;
41
+ readonly variant?: {
42
+ readonly type: 'single';
43
+ } | {
44
+ readonly type: 'segmented';
45
+ readonly trailing: InspectorInlineActionSegment;
46
+ };
47
+ };
48
+ export declare const InspectorInlineAction: React.FC<InspectorInlineActionProps>;
36
49
  export declare const InspectorDefaultPropsWarnings: React.FC<{
37
50
  readonly warnings: RenderModalWarning[];
38
51
  }>;
@@ -38,9 +38,12 @@ const InspectorBackAction = ({ children, disabled, onClick, title }) => {
38
38
  exports.InspectorBackAction = InspectorBackAction;
39
39
  const InspectorMessage = ({ children }) => jsx_runtime_1.jsx("div", { style: styles_1.centeredMessage, children: children });
40
40
  exports.InspectorMessage = InspectorMessage;
41
- const InspectorDetailRow = ({ label, children }) => (jsx_runtime_1.jsxs("div", { style: styles_1.detailRow, children: [
42
- jsx_runtime_1.jsx("div", { style: styles_1.detailLabel, children: label }), jsx_runtime_1.jsx("div", { style: styles_1.detailValue, children: children })
43
- ] }));
41
+ const InspectorDetailRow = ({ label, children }) => {
42
+ const [hovered, setHovered] = react_1.default.useState(false);
43
+ return (jsx_runtime_1.jsxs("div", { style: styles_1.detailRow, onPointerEnter: () => setHovered(true), onPointerLeave: () => setHovered(false), children: [
44
+ jsx_runtime_1.jsx("div", { style: styles_1.detailLabel, children: typeof label === 'function' ? label(hovered) : label }), jsx_runtime_1.jsx("div", { style: styles_1.detailValue, children: children })
45
+ ] }));
46
+ };
44
47
  exports.InspectorDetailRow = InspectorDetailRow;
45
48
  const INLINE_LABEL_BUTTON_MARGIN = 4;
46
49
  const inlineLabelButton = {
@@ -89,9 +92,39 @@ const inlineLabelIcon = {
89
92
  justifyContent: 'center',
90
93
  width: 18,
91
94
  };
92
- const InspectorInlineAction = ({ children, disabled, onClick, renderIcon, size = 'default', style, title, }) => {
95
+ const segmentedInlineAction = {
96
+ display: 'flex',
97
+ gap: 1,
98
+ margin: `0 ${INLINE_LABEL_BUTTON_MARGIN}px`,
99
+ width: `calc(100% - ${INLINE_LABEL_BUTTON_MARGIN * 2}px)`,
100
+ };
101
+ const segmentedMainAction = {
102
+ borderRadius: '4px 0 0 4px',
103
+ flex: 1,
104
+ margin: 0,
105
+ minWidth: 0,
106
+ width: 'auto',
107
+ };
108
+ const segmentedTrailingAction = {
109
+ alignItems: 'center',
110
+ appearance: 'none',
111
+ border: 'none',
112
+ borderRadius: '0 4px 4px 0',
113
+ display: 'flex',
114
+ flex: '0 0 28px',
115
+ justifyContent: 'center',
116
+ margin: 0,
117
+ padding: 0,
118
+ width: 28,
119
+ };
120
+ const hiddenSegmentedTrailingIcon = {
121
+ ...inlineLabelIcon,
122
+ opacity: 0,
123
+ };
124
+ const InspectorInlineAction = ({ children, disabled, onClick, renderIcon, size = 'default', style, title, variant = { type: 'single' }, }) => {
93
125
  const [hovered, setHovered] = react_1.default.useState(false);
94
126
  const color = hovered && !disabled ? colors_1.WHITE : colors_1.LIGHT_TEXT;
127
+ const isSegmented = variant.type === 'segmented';
95
128
  const buttonStyle = react_1.default.useMemo(() => ({
96
129
  ...(disabled ? inlineLabelButtonDisabled : inlineLabelButton),
97
130
  backgroundColor: (0, colors_1.getBackgroundFromHoverState)({
@@ -100,8 +133,9 @@ const InspectorInlineAction = ({ children, disabled, onClick, renderIcon, size =
100
133
  }),
101
134
  color,
102
135
  ...(size === 'compact' ? compactInlineLabelButton : null),
136
+ ...(isSegmented ? segmentedMainAction : null),
103
137
  ...style,
104
- }), [color, disabled, hovered, size, style]);
138
+ }), [color, disabled, hovered, isSegmented, size, style]);
105
139
  const textStyle = react_1.default.useMemo(() => ({
106
140
  ...inlineLabelText,
107
141
  color,
@@ -112,8 +146,28 @@ const InspectorInlineAction = ({ children, disabled, onClick, renderIcon, size =
112
146
  const onPointerLeave = react_1.default.useCallback(() => {
113
147
  setHovered(false);
114
148
  }, []);
115
- return (jsx_runtime_1.jsxs("button", { className: "__remotion-inspector-inline-action", type: "button", disabled: disabled, style: buttonStyle, title: title, onClick: onClick, onPointerEnter: disabled ? undefined : onPointerEnter, onPointerLeave: onPointerLeave, children: [renderIcon ? (jsx_runtime_1.jsx("span", { style: inlineLabelIcon, children: renderIcon(color) })) : null, jsx_runtime_1.jsx("span", { style: textStyle, children: children })
149
+ const mainContent = (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [renderIcon ? (jsx_runtime_1.jsx("span", { style: inlineLabelIcon, children: renderIcon(color) })) : null, jsx_runtime_1.jsx("span", { style: textStyle, children: children })
116
150
  ] }));
151
+ const mainAction = onClick ? (jsx_runtime_1.jsx("button", { className: "__remotion-inspector-inline-action", type: "button", disabled: disabled, style: buttonStyle, title: title, onClick: onClick, onPointerEnter: disabled || isSegmented ? undefined : onPointerEnter, onPointerLeave: isSegmented ? undefined : onPointerLeave, children: mainContent })) : (jsx_runtime_1.jsx("div", { style: buttonStyle, title: title, children: mainContent }));
152
+ if (variant.type === 'segmented') {
153
+ const trailingColor = hovered && !variant.trailing.disabled ? colors_1.WHITE : colors_1.LIGHT_TEXT;
154
+ const trailingStyle = {
155
+ ...segmentedTrailingAction,
156
+ backgroundColor: variant.trailing.disabled
157
+ ? colors_1.TRANSPARENT
158
+ : (0, colors_1.getBackgroundFromHoverState)({
159
+ hovered,
160
+ selected: false,
161
+ }),
162
+ height: size === 'compact'
163
+ ? layout_1.COMPACT_INLINE_ROW_HEIGHT
164
+ : layout_1.COMPACT_CONTROL_ROW_HEIGHT,
165
+ opacity: variant.trailing.disabled ? 0.35 : 1,
166
+ };
167
+ return (jsx_runtime_1.jsxs("div", { style: segmentedInlineAction, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, children: [mainAction, jsx_runtime_1.jsx("button", { type: "button", disabled: variant.trailing.disabled, style: trailingStyle, title: variant.trailing.title, onClick: variant.trailing.onClick, children: jsx_runtime_1.jsx("span", { style: hovered ? inlineLabelIcon : hiddenSegmentedTrailingIcon, children: variant.trailing.renderIcon(trailingColor) }) })
168
+ ] }));
169
+ }
170
+ return mainAction;
117
171
  };
118
172
  exports.InspectorInlineAction = InspectorInlineAction;
119
173
  const InspectorDefaultPropsWarnings = ({ warnings }) => {
@@ -34,6 +34,7 @@ const useCompositionActions = () => {
34
34
  compositionId: currentCompositionId,
35
35
  });
36
36
  const canShowInsertSolid = previewInteractive &&
37
+ !window.remotion_isReadOnlyStudio &&
37
38
  (compositionComponentInfo === null || compositionComponentInfo === void 0 ? void 0 : compositionComponentInfo.canAddSequence) === true &&
38
39
  currentCompositionId !== null &&
39
40
  compositionFile !== null &&
@@ -1,2 +1,2 @@
1
1
  import type { TimelineSelection } from '../Timeline/TimelineSelection';
2
- export declare const useTrackForSelection: (selection: TimelineSelection) => import("../../helpers/get-timeline-sequence-sort-key").TrackWithHash | null;
2
+ export declare const useTrackForSelection: (selection: TimelineSelection) => import("../../helpers/get-timeline-sequence-sort-key").TimelineTrackData | null;
@@ -6,6 +6,7 @@ const react_1 = require("react");
6
6
  const client_id_1 = require("../helpers/client-id");
7
7
  const colors_1 = require("../helpers/colors");
8
8
  const get_preview_file_type_1 = require("../helpers/get-preview-file-type");
9
+ const interactivity_enabled_1 = require("../helpers/interactivity-enabled");
9
10
  const timeline_layout_1 = require("../helpers/timeline-layout");
10
11
  const plus_1 = require("../icons/plus");
11
12
  const modals_1 = require("../state/modals");
@@ -13,8 +14,9 @@ const AssetFileIcon_1 = require("./AssetFileIcon");
13
14
  const InlineAction_1 = require("./InlineAction");
14
15
  const common_1 = require("./InspectorPanel/common");
15
16
  const styles_1 = require("./InspectorPanel/styles");
16
- const InspectorPanelLayout_1 = require("./InspectorPanelLayout");
17
+ const asset_search_1 = require("./QuickSwitcher/asset-search");
17
18
  const timeline_asset_link_1 = require("./Timeline/timeline-asset-link");
19
+ const TimelineAssetField_1 = require("./Timeline/TimelineAssetField");
18
20
  const TimelineExpandedRow_1 = require("./Timeline/TimelineExpandedRow");
19
21
  const TimelineRowLayoutContext_1 = require("./Timeline/TimelineRowLayoutContext");
20
22
  const TimelineSelection_1 = require("./Timeline/TimelineSelection");
@@ -47,15 +49,14 @@ const assetSelectorIcon = {
47
49
  height: 18,
48
50
  width: 18,
49
51
  };
50
- const remoteSourceLabel = {
51
- color: colors_1.LIGHT_TEXT,
52
+ const remoteSourcePartsContainer = {
53
+ color: 'inherit',
52
54
  display: 'flex',
53
55
  fontFamily: 'Arial, Helvetica, sans-serif',
54
56
  fontSize: 12,
55
57
  lineHeight: '18px',
56
58
  minWidth: 0,
57
59
  overflow: 'hidden',
58
- padding: `6px ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px`,
59
60
  whiteSpace: 'nowrap',
60
61
  };
61
62
  const remoteSourceLeading = {
@@ -141,7 +142,6 @@ const hasSequenceControls = (sequence) => {
141
142
  };
142
143
  exports.hasSequenceControls = hasSequenceControls;
143
144
  const InspectorSequenceSection = ({ sequence, validatedLocation, nodePathInfo, keyframeDisplayOffset, renderTransformControls, }) => {
144
- var _a;
145
145
  const { tree } = (0, use_timeline_expanded_tree_1.useTimelineExpandedTree)({
146
146
  sequence,
147
147
  nodePathInfo,
@@ -153,18 +153,41 @@ const InspectorSequenceSection = ({ sequence, validatedLocation, nodePathInfo, k
153
153
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
154
154
  const selectAsset = (0, use_select_asset_1.useSelectAsset)();
155
155
  const mediaSrc = (0, timeline_asset_link_1.getTimelineAssetSrcFromSchema)(sequence.controls);
156
- const assetLinkInfo = (0, react_1.useMemo)(() => (mediaSrc ? (0, timeline_asset_link_1.getTimelineAssetLinkInfo)(mediaSrc) : null), [mediaSrc]);
157
- const localAsset = (assetLinkInfo === null || assetLinkInfo === void 0 ? void 0 : assetLinkInfo.kind) === 'local' ? assetLinkInfo : null;
158
- const remoteAsset = (assetLinkInfo === null || assetLinkInfo === void 0 ? void 0 : assetLinkInfo.kind) === 'remote' ? assetLinkInfo : null;
159
- const remoteSourceParts = (0, react_1.useMemo)(() => remoteAsset ? (0, timeline_asset_link_1.splitRemoteSourceForMiddleEllipsis)(remoteAsset.href) : null, [remoteAsset]);
160
- const jumpToAsset = (0, react_1.useCallback)(() => {
161
- if (localAsset) {
162
- (0, timeline_asset_link_1.openTimelineAssetLink)(localAsset, selectAsset);
156
+ const assetSelectionInitialQuery = (0, asset_search_1.getAssetSearchQueryForComponent)(sequence.controls.componentIdentity);
157
+ const getSourceAction = (0, react_1.useCallback)((src) => {
158
+ var _a;
159
+ const linkInfo = (0, timeline_asset_link_1.getTimelineAssetLinkInfo)(src);
160
+ if ((linkInfo === null || linkInfo === void 0 ? void 0 : linkInfo.kind) === 'local') {
161
+ const fileName = (_a = linkInfo.assetPath.split('/').pop()) !== null && _a !== void 0 ? _a : linkInfo.assetPath;
162
+ return {
163
+ children: fileName,
164
+ disabled: false,
165
+ onClick: () => (0, timeline_asset_link_1.openTimelineAssetLink)(linkInfo, selectAsset),
166
+ renderIcon: (color) => (jsx_runtime_1.jsx(AssetFileIcon_1.AssetFileIcon, { color: color, fileType: (0, get_preview_file_type_1.getPreviewFileType)(linkInfo.assetPath), style: assetSelectorIcon })),
167
+ title: linkInfo.assetPath,
168
+ };
169
+ }
170
+ if ((linkInfo === null || linkInfo === void 0 ? void 0 : linkInfo.kind) === 'remote') {
171
+ const parts = (0, timeline_asset_link_1.splitRemoteSourceForMiddleEllipsis)(linkInfo.href);
172
+ return {
173
+ children: (jsx_runtime_1.jsxs("span", { style: remoteSourcePartsContainer, children: [
174
+ jsx_runtime_1.jsx("span", { style: remoteSourceLeading, children: parts.leading }), jsx_runtime_1.jsx("span", { style: remoteSourceTrailing, children: parts.trailing })
175
+ ] })),
176
+ disabled: false,
177
+ onClick: null,
178
+ title: linkInfo.href,
179
+ };
163
180
  }
164
- }, [localAsset, selectAsset]);
165
- const localAssetFileName = localAsset
166
- ? ((_a = localAsset.assetPath.split('/').pop()) !== null && _a !== void 0 ? _a : localAsset.assetPath)
167
- : null;
181
+ return null;
182
+ }, [selectAsset]);
183
+ const sourceAction = (0, react_1.useMemo)(() => {
184
+ return mediaSrc ? getSourceAction(mediaSrc) : null;
185
+ }, [getSourceAction, mediaSrc]);
186
+ const assetSelectionContextValue = (0, react_1.useMemo)(() => ({
187
+ getSourceAction,
188
+ initialQuery: assetSelectionInitialQuery,
189
+ sourceAction,
190
+ }), [assetSelectionInitialQuery, getSourceAction, sourceAction]);
168
191
  const getIsExpanded = (0, react_1.useCallback)((candidate) => {
169
192
  return !collapsedKeys.has(getInspectorExpansionKey(candidate));
170
193
  }, [collapsedKeys]);
@@ -212,10 +235,13 @@ const InspectorSequenceSection = ({ sequence, validatedLocation, nodePathInfo, k
212
235
  })), [controlRows]);
213
236
  const effectSelectableItems = (0, react_1.useMemo)(() => (0, exports.getInspectorSelectableItems)(effectRows), [effectRows]);
214
237
  const controlGroups = (0, react_1.useMemo)(() => getInspectorControlGroups(controlRows), [controlRows]);
238
+ const layoutGroup = controlGroups.find((group) => group.id === 'layout');
239
+ const controlGroupsWithoutLayout = controlGroups.filter((group) => group.id !== 'layout');
215
240
  const { schema } = sequence.controls;
216
241
  const showEffectsSection = nodePathInfo.supportsEffects || effectRows.length > 0;
217
242
  const canAddEffect = nodePathInfo.supportsEffects &&
218
243
  previewServerState.type === 'connected' &&
244
+ (0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
219
245
  Boolean(validatedLocation.source);
220
246
  const onAddEffect = (0, react_1.useCallback)(() => {
221
247
  if (!canAddEffect || previewServerState.type !== 'connected') {
@@ -242,8 +268,6 @@ const InspectorSequenceSection = ({ sequence, validatedLocation, nodePathInfo, k
242
268
  if (controlRows.length === 0 && !showEffectsSection) {
243
269
  return (jsx_runtime_1.jsx("div", { style: container, children: jsx_runtime_1.jsx(common_1.InspectorSection, { header: "Controls", children: jsx_runtime_1.jsx("div", { style: emptyState, children: "No schema" }) }) }));
244
270
  }
245
- return (jsx_runtime_1.jsxs("div", { style: container, children: [controlRows.length > 0 ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: controlSelectableItems, children: controlGroups.map((group) => (jsx_runtime_1.jsxs(common_1.InspectorSection, { header: group.label, children: [group.id === 'source' && localAsset ? (jsx_runtime_1.jsx(common_1.InspectorInlineAction, { disabled: false, onClick: jumpToAsset, renderIcon: (color) => (jsx_runtime_1.jsx(AssetFileIcon_1.AssetFileIcon, { color: color, fileType: (0, get_preview_file_type_1.getPreviewFileType)(localAsset.assetPath), style: assetSelectorIcon })), size: "compact", title: localAsset.assetPath, children: localAssetFileName })) : null, group.id === 'source' && remoteAsset && remoteSourceParts ? (jsx_runtime_1.jsxs("div", { style: remoteSourceLabel, title: remoteAsset.href, children: [
246
- jsx_runtime_1.jsx("span", { style: remoteSourceLeading, children: remoteSourceParts.leading }), jsx_runtime_1.jsx("span", { style: remoteSourceTrailing, children: remoteSourceParts.trailing })
247
- ] })) : null, group.id === 'transforms' ? renderTransformControls() : null, group.id === 'source' ? null : group.rows.map(renderRow)] }, group.id))) })) : null, showEffectsSection ? (jsx_runtime_1.jsx(common_1.InspectorSection, { header: effectsHeader, children: effectRows.length > 0 ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: effectSelectableItems, children: effectRows.map(renderRow) })) : null })) : null] }));
271
+ return (jsx_runtime_1.jsx(TimelineAssetField_1.AssetSelectionContext.Provider, { value: assetSelectionContextValue, children: jsx_runtime_1.jsxs("div", { style: container, children: [controlRows.length > 0 ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: controlSelectableItems, children: controlGroupsWithoutLayout.map((group) => (jsx_runtime_1.jsxs(common_1.InspectorSection, { header: group.label, children: [group.id === 'transforms' ? renderTransformControls() : null, group.rows.map(renderRow)] }, group.id))) })) : null, showEffectsSection ? (jsx_runtime_1.jsx(common_1.InspectorSection, { header: effectsHeader, children: effectRows.length > 0 ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: effectSelectableItems, children: effectRows.map(renderRow) })) : null })) : null, layoutGroup ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: controlSelectableItems, children: jsx_runtime_1.jsx(common_1.InspectorSection, { header: layoutGroup.label, children: layoutGroup.rows.map(renderRow) }) })) : null] }) }));
248
272
  };
249
273
  exports.InspectorSequenceSection = InspectorSequenceSection;
@@ -4,6 +4,7 @@ exports.KeyboardShortcutsExplainer = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ShortcutHint_1 = require("../error-overlay/remotion-overlay/ShortcutHint");
6
6
  const colors_1 = require("../helpers/colors");
7
+ const is_mac_1 = require("../helpers/is-mac");
7
8
  const studio_runtime_config_1 = require("../helpers/studio-runtime-config");
8
9
  const use_keybinding_1 = require("../helpers/use-keybinding");
9
10
  const keys_1 = require("../icons/keys");
@@ -141,8 +142,9 @@ const KeyboardShortcutsExplainer = () => {
141
142
  ] }), jsx_runtime_1.jsx("div", { style: right, children: "Undo" })
142
143
  ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
143
144
  jsx_runtime_1.jsxs("div", { style: left, children: [
144
- jsx_runtime_1.jsx("kbd", { style: key, children: ShortcutHint_1.cmdOrCtrlCharacter }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.3 }), jsx_runtime_1.jsx("kbd", { style: key, children: "Y" })
145
- ] }), jsx_runtime_1.jsx("div", { style: right, children: "Redo" })
145
+ jsx_runtime_1.jsx("kbd", { style: key, children: ShortcutHint_1.cmdOrCtrlCharacter }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.3 }), is_mac_1.isMac ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
146
+ jsx_runtime_1.jsx("kbd", { style: key, children: "Shift" }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.3 }), jsx_runtime_1.jsx("kbd", { style: key, children: "Z" })
147
+ ] })) : (jsx_runtime_1.jsx("kbd", { style: key, children: "Y" }))] }), jsx_runtime_1.jsx("div", { style: right, children: "Redo" })
146
148
  ] }), jsx_runtime_1.jsx("br", {}), jsx_runtime_1.jsx("div", { style: title, children: "Interactivity" }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
147
149
  jsx_runtime_1.jsx("div", { style: left, children: jsx_runtime_1.jsx("kbd", { style: key, children: "Shift" }) }), jsx_runtime_1.jsx("div", { style: right, children: "Select range / axis lock drag" })
148
150
  ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [