@remotion/studio 4.0.499 → 4.0.501

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 (204) hide show
  1. package/dist/Studio.js +1 -1
  2. package/dist/api/delete-static-file.js +8 -3
  3. package/dist/api/rename-static-file.js +8 -0
  4. package/dist/api/watch-public-folder.js +2 -1
  5. package/dist/api/watch-static-file.js +2 -1
  6. package/dist/api/write-static-file.js +8 -3
  7. package/dist/components/AssetSelector.js +11 -7
  8. package/dist/components/AssetSelectorItem.d.ts +25 -0
  9. package/dist/components/AssetSelectorItem.js +116 -80
  10. package/dist/components/Canvas.js +6 -1
  11. package/dist/components/CaptionInspector.d.ts +10 -0
  12. package/dist/components/CaptionInspector.js +24 -0
  13. package/dist/components/CaptionTextEditor.d.ts +9 -0
  14. package/dist/components/CaptionTextEditor.js +132 -0
  15. package/dist/components/CompositionSelector.js +2 -32
  16. package/dist/components/ControlButton.js +1 -0
  17. package/dist/components/CurrentAsset.js +3 -2
  18. package/dist/components/EditorContexts.d.ts +0 -1
  19. package/dist/components/EditorContexts.js +2 -2
  20. package/dist/components/ExplorerPanel.js +2 -1
  21. package/dist/components/ExplorerPanelRef.d.ts +2 -0
  22. package/dist/components/FpsCounter.js +3 -3
  23. package/dist/components/FullscreenToggle.js +2 -1
  24. package/dist/components/GlobalKeybindings.js +9 -1
  25. package/dist/components/InitialCompositionLoader.d.ts +1 -1
  26. package/dist/components/InlineAction.d.ts +2 -1
  27. package/dist/components/InlineAction.js +3 -2
  28. package/dist/components/InlineCaptionInspector.d.ts +11 -0
  29. package/dist/components/InlineCaptionInspector.js +108 -0
  30. package/dist/components/InlineDropdown.d.ts +1 -1
  31. package/dist/components/InlineDropdown.js +3 -2
  32. package/dist/components/InspectorPanel/AlignmentControls.d.ts +2 -2
  33. package/dist/components/InspectorPanel/AlignmentControls.js +5 -2
  34. package/dist/components/InspectorPanel/CompositionInspector.js +12 -9
  35. package/dist/components/InspectorPanel/CompositionMetadata.js +170 -57
  36. package/dist/components/InspectorPanel/ConnectedCompositionsSection.d.ts +2 -2
  37. package/dist/components/InspectorPanel/SelectedInspector.d.ts +1 -0
  38. package/dist/components/InspectorPanel/SelectedInspector.js +2 -2
  39. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +3 -3
  40. package/dist/components/InspectorPanel/SequenceSelectionInspector.d.ts +1 -0
  41. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +10 -10
  42. package/dist/components/InspectorPanel/common.d.ts +17 -4
  43. package/dist/components/InspectorPanel/common.js +60 -6
  44. package/dist/components/InspectorPanel/inspector-section-collapse.d.ts +22 -0
  45. package/dist/components/InspectorPanel/inspector-section-collapse.js +165 -0
  46. package/dist/components/InspectorPanel/styles.js +7 -1
  47. package/dist/components/InspectorPanel/use-composition-actions.d.ts +3 -0
  48. package/dist/components/InspectorPanel/use-composition-actions.js +91 -5
  49. package/dist/components/InspectorPanel/use-track-for-selection.d.ts +1 -1
  50. package/dist/components/InspectorPanel.js +2 -2
  51. package/dist/components/InspectorSequenceSection.d.ts +2 -1
  52. package/dist/components/InspectorSequenceSection.js +279 -25
  53. package/dist/components/KeyboardShortcutsExplainer.js +4 -2
  54. package/dist/components/Menu/MenuItem.js +2 -1
  55. package/dist/components/MenuCompositionName.js +30 -7
  56. package/dist/components/MenuToolbar.d.ts +0 -1
  57. package/dist/components/MenuToolbar.js +15 -7
  58. package/dist/components/MobilePanel.d.ts +2 -1
  59. package/dist/components/MobilePanel.js +29 -25
  60. package/dist/components/ModalContainer.d.ts +1 -0
  61. package/dist/components/ModalContainer.js +2 -2
  62. package/dist/components/Modals.js +1 -1
  63. package/dist/components/NewComposition/DismissableModal.d.ts +1 -0
  64. package/dist/components/NewComposition/DismissableModal.js +2 -2
  65. package/dist/components/NewComposition/InputDragger.d.ts +7 -0
  66. package/dist/components/NewComposition/InputDragger.js +119 -8
  67. package/dist/components/OutlineToggle.d.ts +1 -3
  68. package/dist/components/OutlineToggle.js +2 -2
  69. package/dist/components/PreviewToolbar.js +10 -4
  70. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.d.ts +7 -0
  71. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.js +45 -0
  72. package/dist/components/QuickSwitcher/NoResults.d.ts +1 -1
  73. package/dist/components/QuickSwitcher/NoResults.js +1 -0
  74. package/dist/components/QuickSwitcher/QuickSwitcher.d.ts +10 -0
  75. package/dist/components/QuickSwitcher/QuickSwitcher.js +6 -2
  76. package/dist/components/QuickSwitcher/QuickSwitcherContent.d.ts +10 -0
  77. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +95 -13
  78. package/dist/components/QuickSwitcher/QuickSwitcherResult.d.ts +4 -0
  79. package/dist/components/QuickSwitcher/QuickSwitcherResult.js +11 -8
  80. package/dist/components/QuickSwitcher/asset-search.d.ts +9 -0
  81. package/dist/components/QuickSwitcher/asset-search.js +42 -0
  82. package/dist/components/RenderQueue/ClientRenderQueueProcessor.d.ts +0 -1
  83. package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +3 -14
  84. package/dist/components/RenderQueue/RenderQueueDownloadItem.js +2 -2
  85. package/dist/components/SelectedOutlineCropControls.d.ts +8 -0
  86. package/dist/components/SelectedOutlineCropControls.js +299 -0
  87. package/dist/components/SelectedOutlineElement.js +84 -47
  88. package/dist/components/SelectedOutlineOverlay.d.ts +2 -2
  89. package/dist/components/SelectedOutlineOverlay.js +147 -16
  90. package/dist/components/SequencePropsSubscriptionProvider.d.ts +2 -0
  91. package/dist/components/SequencePropsSubscriptionProvider.js +31 -3
  92. package/dist/components/ShowOutlinesProvider.js +4 -1
  93. package/dist/components/SidebarCollapserControls.d.ts +3 -1
  94. package/dist/components/SidebarCollapserControls.js +34 -29
  95. package/dist/components/SnappingToggle.d.ts +1 -3
  96. package/dist/components/SnappingToggle.js +2 -2
  97. package/dist/components/Timeline/Timeline.js +19 -5
  98. package/dist/components/Timeline/TimelineAssetField.d.ts +9 -1
  99. package/dist/components/Timeline/TimelineAssetField.js +53 -100
  100. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +7 -3
  101. package/dist/components/Timeline/TimelineClipboardKeybindings.js +65 -38
  102. package/dist/components/Timeline/TimelineColorField.js +20 -1
  103. package/dist/components/Timeline/TimelineEffectPropItem.js +8 -77
  104. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +8 -1
  105. package/dist/components/Timeline/TimelineHeightContainer.d.ts +2 -2
  106. package/dist/components/Timeline/TimelineKeyframeTracksContext.d.ts +3 -3
  107. package/dist/components/Timeline/TimelineList.d.ts +2 -2
  108. package/dist/components/Timeline/TimelinePrimitiveFieldValue.d.ts +7 -2
  109. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +10 -2
  110. package/dist/components/Timeline/TimelineRowChrome.d.ts +3 -0
  111. package/dist/components/Timeline/TimelineRowChrome.js +4 -3
  112. package/dist/components/Timeline/TimelineSelection.d.ts +9 -7
  113. package/dist/components/Timeline/TimelineSelection.js +17 -12
  114. package/dist/components/Timeline/TimelineSequence.js +2 -9
  115. package/dist/components/Timeline/TimelineSequenceItem.js +61 -15
  116. package/dist/components/Timeline/TimelineSequencePropItem.js +36 -85
  117. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +0 -1
  118. package/dist/components/Timeline/TimelineTrack.d.ts +2 -2
  119. package/dist/components/Timeline/TimelineTrack.js +4 -2
  120. package/dist/components/Timeline/TimelineTracks.d.ts +2 -2
  121. package/dist/components/Timeline/border-radius-representation.d.ts +16 -0
  122. package/dist/components/Timeline/border-radius-representation.js +60 -0
  123. package/dist/components/Timeline/delete-selected-timeline-item.js +1 -6
  124. package/dist/components/Timeline/find-track-for-node-path-info.d.ts +1 -1
  125. package/dist/components/Timeline/get-sequence-context-menu-items.js +14 -12
  126. package/dist/components/Timeline/get-sequence-prop-reset-changes.d.ts +10 -0
  127. package/dist/components/Timeline/get-sequence-prop-reset-changes.js +33 -0
  128. package/dist/components/Timeline/reset-selected-timeline-props.js +20 -18
  129. package/dist/components/Timeline/save-effect-prop.d.ts +10 -0
  130. package/dist/components/Timeline/save-effect-prop.js +52 -1
  131. package/dist/components/Timeline/save-sequence-prop.d.ts +12 -1
  132. package/dist/components/Timeline/save-sequence-prop.js +25 -1
  133. package/dist/components/Timeline/should-show-track-in-timeline.d.ts +2 -2
  134. package/dist/components/Timeline/timeline-asset-link.js +17 -1
  135. package/dist/components/Timeline/timeline-field-display-utils.js +1 -0
  136. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.d.ts +4 -0
  137. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +9 -3
  138. package/dist/components/Timeline/use-timeline-asset-drop.js +4 -0
  139. package/dist/components/Timeline/use-timeline-height.d.ts +2 -2
  140. package/dist/components/TopPanel.js +2 -2
  141. package/dist/components/UndoRedoButtons.js +42 -11
  142. package/dist/components/composition-drop-preview.js +1 -0
  143. package/dist/components/handle-drop.d.ts +3 -2
  144. package/dist/components/handle-drop.js +2 -1
  145. package/dist/components/import-assets.d.ts +4 -2
  146. package/dist/components/import-assets.js +20 -7
  147. package/dist/components/menu-toolbar-height.d.ts +1 -0
  148. package/dist/components/menu-toolbar-height.js +4 -0
  149. package/dist/components/selected-outline-drag.d.ts +41 -4
  150. package/dist/components/selected-outline-drag.js +179 -2
  151. package/dist/components/selected-outline-geometry.d.ts +1 -0
  152. package/dist/components/selected-outline-measurement.d.ts +11 -0
  153. package/dist/components/selected-outline-measurement.js +64 -3
  154. package/dist/components/selected-outline-types.d.ts +44 -1
  155. package/dist/components/selected-outline-types.js +21 -1
  156. package/dist/components/use-element-overwrite-confirmation.d.ts +2 -0
  157. package/dist/components/use-element-overwrite-confirmation.js +73 -0
  158. package/dist/components/use-static-files.js +7 -2
  159. package/dist/error-overlay/react-overlay/effects/resolve-file-source.js +13 -2
  160. package/dist/error-overlay/remotion-overlay/Overlay.js +3 -3
  161. package/dist/error-overlay/remotion-overlay/ShortcutHint.js +2 -3
  162. package/dist/esm/{chunk-pk1zwsn1.js → chunk-n1kj09yv.js} +10618 -8002
  163. package/dist/esm/index.mjs +24 -8
  164. package/dist/esm/internals.mjs +10618 -8002
  165. package/dist/esm/previewEntry.mjs +40002 -37388
  166. package/dist/esm/renderEntry.mjs +1 -1
  167. package/dist/helpers/browser-studio-operations.d.ts +3 -0
  168. package/dist/helpers/browser-studio-operations.js +14 -0
  169. package/dist/helpers/calculate-timeline.d.ts +2 -2
  170. package/dist/helpers/calculate-timeline.js +8 -28
  171. package/dist/helpers/client-id.d.ts +0 -1
  172. package/dist/helpers/client-id.js +15 -10
  173. package/dist/helpers/download-blob.d.ts +1 -0
  174. package/dist/helpers/download-blob.js +15 -0
  175. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +3 -10
  176. package/dist/helpers/get-timeline-sequence-sort-key.js +5 -13
  177. package/dist/helpers/inject-css.js +5 -3
  178. package/dist/helpers/interactivity-enabled.d.ts +1 -0
  179. package/dist/helpers/interactivity-enabled.js +7 -2
  180. package/dist/helpers/is-mac.d.ts +1 -0
  181. package/dist/helpers/is-mac.js +4 -0
  182. package/dist/helpers/open-in-editor.d.ts +5 -1
  183. package/dist/helpers/open-in-editor.js +39 -4
  184. package/dist/helpers/preview-server-events.js +46 -9
  185. package/dist/helpers/sort-by-nonce-history.js +97 -19
  186. package/dist/helpers/use-create-composition.js +8 -6
  187. package/dist/helpers/use-keybinding.js +2 -3
  188. package/dist/helpers/use-menu-structure.js +39 -1
  189. package/dist/hot-middleware-client/client.js +3 -3
  190. package/dist/icons/border-radius.d.ts +4 -0
  191. package/dist/icons/border-radius.js +8 -0
  192. package/dist/icons/caret.d.ts +1 -0
  193. package/dist/icons/caret.js +2 -2
  194. package/dist/icons/fullscreen.d.ts +4 -0
  195. package/dist/icons/fullscreen.js +6 -0
  196. package/dist/icons/pen.d.ts +5 -0
  197. package/dist/icons/pen.js +8 -0
  198. package/dist/previewEntry.js +1 -1
  199. package/dist/state/modals.d.ts +9 -0
  200. package/dist/state/timeline-sequence-hover.d.ts +17 -0
  201. package/dist/state/timeline-sequence-hover.js +33 -0
  202. package/package.json +13 -12
  203. package/dist/helpers/get-timeline-sequence-hash.d.ts +0 -6
  204. package/dist/helpers/get-timeline-sequence-hash.js +0 -33
@@ -6,6 +6,7 @@ const react_1 = require("react");
6
6
  const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
7
7
  const frame_1 = require("../../icons/frame");
8
8
  const solid_1 = require("../../icons/solid");
9
+ const video_1 = require("../../icons/video");
9
10
  const VisualControls_1 = require("../../visual-controls/VisualControls");
10
11
  const DefaultPropsEditor_1 = require("../DefaultPropsEditor");
11
12
  const get_zod_if_possible_1 = require("../get-zod-if-possible");
@@ -25,14 +26,15 @@ const actionIconStyle = {
25
26
  height: 18,
26
27
  width: 18,
27
28
  };
28
- const CompositionActions = () => {
29
- const { canInsertAsset, canInsertSolid, canShowInsertAsset, canShowInsertSolid, insertAsset, insertSolid, } = (0, use_composition_actions_1.useCompositionActions)();
30
- if (!canShowInsertAsset && !canShowInsertSolid) {
29
+ const CompositionActions = ({ readOnlyStudio }) => {
30
+ const { canInsertAsset, canInsertComposition, canInsertSolid, canShowInsertAsset, canShowInsertComposition, canShowInsertSolid, insertAsset, insertComposition, insertSolid, } = (0, use_composition_actions_1.useCompositionActions)();
31
+ if ((readOnlyStudio && !canShowInsertSolid) ||
32
+ (!canShowInsertAsset && !canShowInsertComposition && !canShowInsertSolid)) {
31
33
  return null;
32
34
  }
33
- return (jsx_runtime_1.jsxs(common_1.InspectorActionSection, { children: [canShowInsertSolid ? (jsx_runtime_1.jsx(common_1.InspectorInlineAction, { disabled: !canInsertSolid, onClick: insertSolid, renderIcon: (color) => (jsx_runtime_1.jsx(solid_1.SolidIcon, { color: color, style: actionIconStyle })), children: "Add Solid" })) : null, canShowInsertAsset ? (jsx_runtime_1.jsx(common_1.InspectorInlineAction, { disabled: !canInsertAsset, onClick: insertAsset, renderIcon: (color) => (jsx_runtime_1.jsx(frame_1.PicIcon, { color: color, style: actionIconStyle })), children: "Add asset..." })) : null] }));
35
+ return (jsx_runtime_1.jsxs(common_1.InspectorActionSection, { children: [canShowInsertSolid ? (jsx_runtime_1.jsx(common_1.InspectorInlineAction, { disabled: !canInsertSolid, onClick: insertSolid, renderIcon: (color) => (jsx_runtime_1.jsx(solid_1.SolidIcon, { color: color, style: actionIconStyle })), children: "Add Solid" })) : null, canShowInsertAsset ? (jsx_runtime_1.jsx(common_1.InspectorInlineAction, { disabled: !canInsertAsset, onClick: insertAsset, renderIcon: (color) => (jsx_runtime_1.jsx(frame_1.PicIcon, { color: color, style: actionIconStyle })), children: "Add asset..." })) : null, canShowInsertComposition ? (jsx_runtime_1.jsx(common_1.InspectorInlineAction, { disabled: !canInsertComposition, onClick: insertComposition, renderIcon: (color) => (jsx_runtime_1.jsx(video_1.FilmIcon, { color: color, style: actionIconStyle })), children: "Add composition..." })) : null] }));
34
36
  };
35
- const CompositionDefaultPropsSection = ({ composition, currentDefaultProps, setDefaultProps }) => {
37
+ const CompositionDefaultPropsSection = ({ composition, currentDefaultProps, readOnlyStudio, setDefaultProps }) => {
36
38
  var _a;
37
39
  const z = (0, get_zod_if_possible_1.useZodIfPossible)();
38
40
  const canSaveDefaultProps = (0, react_1.useContext)(ObserveDefaultPropsContext_1.ObserveDefaultPropsContext);
@@ -79,7 +81,7 @@ const CompositionDefaultPropsSection = ({ composition, currentDefaultProps, setD
79
81
  propsEditType: 'default-props',
80
82
  showCannotSaveDefaultPropsWarning: canShowDefaultPropsSection,
81
83
  });
82
- if (!canShowDefaultPropsSection) {
84
+ if (readOnlyStudio || !canShowDefaultPropsSection) {
83
85
  return null;
84
86
  }
85
87
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
@@ -92,9 +94,10 @@ const CompositionDefaultPropsSection = ({ composition, currentDefaultProps, setD
92
94
  ] })
93
95
  ] }));
94
96
  };
95
- const CompositionVisualControlsSection = () => {
97
+ const CompositionVisualControlsSection = ({ readOnlyStudio }) => {
96
98
  const { handles: visualControlHandles } = (0, react_1.useContext)(VisualControls_1.VisualControlsContext);
97
- const hasVisualControls = (0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
99
+ const hasVisualControls = !readOnlyStudio &&
100
+ (0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
98
101
  Object.keys(visualControlHandles).length > 0;
99
102
  if (!hasVisualControls) {
100
103
  return null;
@@ -109,7 +112,7 @@ const CompositionInspector = ({ composition, currentDefaultProps, readOnlyStudio
109
112
  return (jsx_runtime_1.jsxs("div", { style: styles_1.scrollableContainer, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: [
110
113
  jsx_runtime_1.jsxs("div", { style: styles_1.inspectorOverviewSection, children: [
111
114
  jsx_runtime_1.jsx(CompositionInspectorHeader_1.CompositionInspectorHeader, {}), jsx_runtime_1.jsx(common_1.InspectorSectionDivider, {}), jsx_runtime_1.jsx(CompositionMetadata_1.CompositionMetadata, { compositionId: composition.id, disabled: readOnlyStudio, stack: composition.stack })
112
- ] }), jsx_runtime_1.jsx(CompositionDefaultPropsSection, { composition: composition, currentDefaultProps: currentDefaultProps, setDefaultProps: setDefaultProps }), jsx_runtime_1.jsx(CompositionVisualControlsSection, {}), jsx_runtime_1.jsx(CompositionActions, {})
115
+ ] }), jsx_runtime_1.jsx(CompositionDefaultPropsSection, { composition: composition, currentDefaultProps: currentDefaultProps, readOnlyStudio: readOnlyStudio, setDefaultProps: setDefaultProps }), jsx_runtime_1.jsx(CompositionVisualControlsSection, { readOnlyStudio: readOnlyStudio }), jsx_runtime_1.jsx(CompositionActions, { readOnlyStudio: readOnlyStudio })
113
116
  ] }));
114
117
  };
115
118
  exports.CompositionInspector = CompositionInspector;
@@ -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'][];
@@ -2,4 +2,5 @@ import React from 'react';
2
2
  import type { TimelineSelection } from '../Timeline/TimelineSelection';
3
3
  export declare const SelectedInspector: React.FC<{
4
4
  readonly selection: TimelineSelection;
5
+ readonly readOnlyStudio: boolean;
5
6
  }>;
@@ -8,9 +8,9 @@ const GuideInspector_1 = require("./GuideInspector");
8
8
  const inspector_selection_1 = require("./inspector-selection");
9
9
  const KeyframeInspector_1 = require("./KeyframeInspector");
10
10
  const SequenceSelectionInspector_1 = require("./SequenceSelectionInspector");
11
- const SelectedInspector = ({ selection }) => {
11
+ const SelectedInspector = ({ selection, readOnlyStudio }) => {
12
12
  if ((0, inspector_selection_1.isSequenceSectionSelection)(selection)) {
13
- return jsx_runtime_1.jsx(SequenceSelectionInspector_1.SequenceSelectionInspector, { selection: selection });
13
+ return (jsx_runtime_1.jsx(SequenceSelectionInspector_1.SequenceSelectionInspector, { selection: selection, readOnlyStudio: readOnlyStudio }));
14
14
  }
15
15
  if (selection.type === 'keyframe') {
16
16
  return jsx_runtime_1.jsx(KeyframeInspector_1.KeyframeInspector, { selection: selection });
@@ -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 {};
@@ -2,4 +2,5 @@ import React from 'react';
2
2
  import type { SequenceSectionSelection } from './inspector-selection';
3
3
  export declare const SequenceSelectionInspector: React.FC<{
4
4
  readonly selection: SequenceSectionSelection;
5
+ readonly readOnlyStudio: boolean;
5
6
  }>;
@@ -99,7 +99,7 @@ const SequenceSourceActions = ({ selection, track, validatedSource }) => {
99
99
  }, [confirm, selection.nodePathInfo, sourceActionsDisabled]);
100
100
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [(freezeFrameMenuItem === null || freezeFrameMenuItem === void 0 ? void 0 : freezeFrameMenuItem.type) === 'item' ? (jsx_runtime_1.jsx(common_1.InspectorInlineAction, { disabled: Boolean(freezeFrameMenuItem.disabled), onClick: () => freezeFrameMenuItem.onClick(freezeFrameMenuItem.id, null), renderIcon: (color) => (jsx_runtime_1.jsx(snowflake_1.SnowflakeIcon, { style: largeActionIconStyle, color: color })), children: freezeFrameMenuItem.label })) : null, jsx_runtime_1.jsx(common_1.InspectorInlineAction, { disabled: sourceActionsDisabled, onClick: onDuplicate, renderIcon: (color) => (jsx_runtime_1.jsx(duplicate_1.DuplicateIcon, { style: largeActionIconStyle, color: color })), children: "Duplicate" }), jsx_runtime_1.jsx(common_1.InspectorInlineAction, { disabled: sourceActionsDisabled, onClick: onDelete, renderIcon: (color) => (jsx_runtime_1.jsx(trash_1.TrashIcon, { style: actionIconStyle, color: color })), children: "Delete" })] }));
101
101
  };
102
- const SequenceExpandedInspector = ({ track }) => {
102
+ const SequenceExpandedInspector = ({ track, readOnlyStudio }) => {
103
103
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
104
104
  const { selectedItems, selectItems } = (0, TimelineSelection_1.useTimelineSelection)();
105
105
  const sourceLocation = (0, SequenceInspectorHeader_1.useSequenceInspectorSourceLocation)(track.sequence);
@@ -131,29 +131,29 @@ 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, 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
+ 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
- const SequenceSelectionInspector = ({ selection }) => {
151
+ const SequenceSelectionInspector = ({ selection, readOnlyStudio }) => {
152
152
  const track = (0, use_track_for_selection_1.useTrackForSelection)(selection);
153
153
  if (!track) {
154
154
  return jsx_runtime_1.jsx(common_1.InspectorMessage, { children: "Sequence inspector unavailable" });
155
155
  }
156
156
  const stackKey = track.sequence.getStack();
157
- return (jsx_runtime_1.jsx(SequenceExpandedInspector, { track: track }, stackKey !== null && stackKey !== void 0 ? stackKey : track.sequence.id));
157
+ return (jsx_runtime_1.jsx(SequenceExpandedInspector, { track: track, readOnlyStudio: readOnlyStudio }, stackKey !== null && stackKey !== void 0 ? stackKey : track.sequence.id));
158
158
  };
159
159
  exports.SequenceSelectionInspector = SequenceSelectionInspector;
@@ -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 }) => {
@@ -0,0 +1,22 @@
1
+ import type { SchemaFieldGroup } from '@remotion/studio-shared';
2
+ import { type InteractivitySchema } from 'remotion';
3
+ export type SmartCollapsibleInspectorGroup = Extract<SchemaFieldGroup, 'background' | 'border' | 'border-radius' | 'crop' | 'layout'>;
4
+ export type InspectorSectionActivity = 'active' | 'inactive' | 'unknown';
5
+ type InspectorSectionPropStatus = {
6
+ readonly status: 'static';
7
+ readonly codeValue: unknown;
8
+ } | {
9
+ readonly status: 'computed' | 'keyframed';
10
+ };
11
+ export declare const isSmartCollapsibleInspectorGroup: (group: SchemaFieldGroup) => group is SmartCollapsibleInspectorGroup;
12
+ export declare const isInspectorSectionEffectivelyInactive: ({ group, propStatuses, schema, }: {
13
+ readonly group: SmartCollapsibleInspectorGroup;
14
+ readonly propStatuses: Readonly<Record<string, InspectorSectionPropStatus>> | undefined;
15
+ readonly schema?: InteractivitySchema | undefined;
16
+ }) => boolean;
17
+ export declare const getInspectorSectionActivity: ({ group, propStatuses, schema, }: {
18
+ readonly group: SmartCollapsibleInspectorGroup;
19
+ readonly propStatuses: Readonly<Record<string, InspectorSectionPropStatus>> | undefined;
20
+ readonly schema?: InteractivitySchema | undefined;
21
+ }) => InspectorSectionActivity;
22
+ export {};