@remotion/studio 4.0.504 → 4.0.505

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 (86) hide show
  1. package/dist/components/AssetSelectorItem.js +2 -2
  2. package/dist/components/AudioWaveform.d.ts +1 -1
  3. package/dist/components/AudioWaveform.js +36 -3
  4. package/dist/components/CompositionContextButton.d.ts +1 -1
  5. package/dist/components/CompositionContextButton.js +2 -2
  6. package/dist/components/CompositionSelector.js +2 -2
  7. package/dist/components/CompositionSelectorItem.js +4 -4
  8. package/dist/components/ContextMenu.d.ts +5 -7
  9. package/dist/components/ContextMenu.js +54 -21
  10. package/dist/components/EditorGuides/Guide.js +2 -2
  11. package/dist/components/EffectPickerModal.js +2 -2
  12. package/dist/components/InlineAction.d.ts +1 -1
  13. package/dist/components/InlineAction.js +14 -13
  14. package/dist/components/InlineDropdown.d.ts +3 -2
  15. package/dist/components/InlineDropdown.js +16 -5
  16. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +2 -2
  17. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +1 -1
  18. package/dist/components/InspectorPanel/common.js +24 -34
  19. package/dist/components/InspectorSequenceSection.js +1 -1
  20. package/dist/components/Menu/MenuItem.js +16 -12
  21. package/dist/components/MenuBuildIndicator.js +11 -58
  22. package/dist/components/MenuCompositionName.js +3 -63
  23. package/dist/components/MenuToolbar.js +22 -2
  24. package/dist/components/NewComposition/InputDragger.d.ts +1 -0
  25. package/dist/components/NewComposition/InputDragger.js +5 -4
  26. package/dist/components/NewComposition/MenuContent.d.ts +1 -1
  27. package/dist/components/NewComposition/menu-typeahead.d.ts +1 -1
  28. package/dist/components/PlayPause.js +2 -2
  29. package/dist/components/PlaybackRateSelector.js +3 -9
  30. package/dist/components/PreviewToolbar.js +7 -4
  31. package/dist/components/RenderButton.d.ts +1 -0
  32. package/dist/components/RenderButton.js +54 -37
  33. package/dist/components/SelectedOutlineElement.js +9 -10
  34. package/dist/components/SelectedOutlineOverlay.js +5 -1
  35. package/dist/components/SizeSelector.js +3 -9
  36. package/dist/components/Timeline/Timeline.js +4 -4
  37. package/dist/components/Timeline/TimelineDragHandler.js +3 -0
  38. package/dist/components/Timeline/TimelineEffectItem.js +6 -2
  39. package/dist/components/Timeline/TimelineEffectPropItem.js +6 -3
  40. package/dist/components/Timeline/TimelineExpandedKeyframeRow.d.ts +6 -6
  41. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +32 -1
  42. package/dist/components/Timeline/TimelineHeightContainer.d.ts +1 -0
  43. package/dist/components/Timeline/TimelineHeightContainer.js +2 -2
  44. package/dist/components/Timeline/TimelineInOutDragHandler.js +3 -3
  45. package/dist/components/Timeline/TimelineKeyframeEasingLine.d.ts +4 -2
  46. package/dist/components/Timeline/TimelineKeyframeEasingLine.js +30 -28
  47. package/dist/components/Timeline/TimelineList.d.ts +1 -0
  48. package/dist/components/Timeline/TimelineList.js +2 -3
  49. package/dist/components/Timeline/TimelineScaleField.js +1 -1
  50. package/dist/components/Timeline/TimelineSequence.js +34 -28
  51. package/dist/components/Timeline/TimelineSequenceItem.d.ts +3 -3
  52. package/dist/components/Timeline/TimelineSequenceItem.js +34 -23
  53. package/dist/components/Timeline/TimelineSequencePropItem.d.ts +10 -2
  54. package/dist/components/Timeline/TimelineSequencePropItem.js +64 -12
  55. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +2 -2
  56. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +38 -5
  57. package/dist/components/Timeline/TimelineTimeIndicators.js +36 -3
  58. package/dist/components/Timeline/TimelineVideoInfo.d.ts +1 -1
  59. package/dist/components/Timeline/TimelineVideoInfo.js +36 -3
  60. package/dist/components/Timeline/TimelineZoomControls.d.ts +2 -2
  61. package/dist/components/Timeline/TimelineZoomControls.js +39 -12
  62. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.d.ts +1 -1
  63. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +7 -18
  64. package/dist/components/Timeline/use-timeline-height.d.ts +2 -1
  65. package/dist/components/Timeline/use-timeline-height.js +3 -2
  66. package/dist/components/TimelineCombobox.d.ts +11 -0
  67. package/dist/components/TimelineCombobox.js +181 -0
  68. package/dist/components/TopPanel.js +6 -7
  69. package/dist/components/selected-outline-types.d.ts +1 -1
  70. package/dist/esm/{chunk-43m68z1k.js → chunk-7pgk8h5m.js} +7731 -7410
  71. package/dist/esm/internals.mjs +7731 -7410
  72. package/dist/esm/previewEntry.mjs +7547 -7226
  73. package/dist/esm/renderEntry.mjs +1 -1
  74. package/dist/helpers/hoverable.d.ts +11 -0
  75. package/dist/helpers/hoverable.js +70 -0
  76. package/dist/helpers/inject-css.js +3 -0
  77. package/dist/helpers/use-is-fullscreen.d.ts +1 -0
  78. package/dist/helpers/use-is-fullscreen.js +25 -0
  79. package/dist/helpers/use-menu-structure.js +3 -10
  80. package/dist/icons/canvas-zoom.d.ts +10 -0
  81. package/dist/icons/canvas-zoom.js +21 -0
  82. package/dist/icons/playback-rate.d.ts +5 -0
  83. package/dist/icons/playback-rate.js +31 -0
  84. package/dist/icons/search.d.ts +5 -0
  85. package/dist/icons/search.js +10 -0
  86. package/package.json +12 -12
@@ -7,6 +7,7 @@ exports.InspectorDefaultPropsWarnings = exports.InspectorInlineAction = exports.
7
7
  const jsx_runtime_1 = require("react/jsx-runtime");
8
8
  const react_1 = __importDefault(require("react"));
9
9
  const colors_1 = require("../../helpers/colors");
10
+ const hoverable_1 = require("../../helpers/hoverable");
10
11
  const InspectorPanelLayout_1 = require("../InspectorPanelLayout");
11
12
  const layout_1 = require("../layout");
12
13
  const ValidationMessage_1 = require("../NewComposition/ValidationMessage");
@@ -49,11 +50,9 @@ const INLINE_LABEL_BUTTON_MARGIN = 4;
49
50
  const inlineLabelButton = {
50
51
  alignItems: 'center',
51
52
  appearance: 'none',
52
- backgroundColor: colors_1.TRANSPARENT,
53
53
  border: 'none',
54
54
  borderRadius: 4,
55
55
  boxSizing: 'border-box',
56
- color: colors_1.LIGHT_TEXT,
57
56
  cursor: 'default',
58
57
  display: 'flex',
59
58
  fontFamily: 'sans-serif',
@@ -74,7 +73,6 @@ const compactInlineLabelButton = {
74
73
  height: layout_1.COMPACT_INLINE_ROW_HEIGHT,
75
74
  };
76
75
  const inlineLabelText = {
77
- color: colors_1.LIGHT_TEXT,
78
76
  flex: 1,
79
77
  fontFamily: 'sans-serif',
80
78
  fontSize: 13,
@@ -117,54 +115,46 @@ const segmentedTrailingAction = {
117
115
  padding: 0,
118
116
  width: 28,
119
117
  };
120
- const hiddenSegmentedTrailingIcon = {
121
- ...inlineLabelIcon,
122
- opacity: 0,
123
- };
124
118
  const InspectorInlineAction = ({ children, disabled, onClick, renderIcon, size = 'default', style, title, variant = { type: 'single' }, }) => {
125
- const [hovered, setHovered] = react_1.default.useState(false);
126
- const color = hovered && !disabled ? colors_1.WHITE : colors_1.LIGHT_TEXT;
127
119
  const isSegmented = variant.type === 'segmented';
120
+ // A non-clickable single action (onClick === null) never shows a hover
121
+ // effect. In the segmented variant, the main segment highlights whenever
122
+ // the group is hovered, even if it is not clickable itself.
123
+ const showsHover = !disabled && (onClick !== null || isSegmented);
128
124
  const buttonStyle = react_1.default.useMemo(() => ({
129
125
  ...(disabled ? inlineLabelButtonDisabled : inlineLabelButton),
130
- backgroundColor: (0, colors_1.getBackgroundFromHoverState)({
131
- hovered: hovered && !disabled,
132
- selected: false,
126
+ ...(0, hoverable_1.hoverableStyle)({
127
+ idleBackground: colors_1.TRANSPARENT,
128
+ hoverBackground: showsHover
129
+ ? (0, colors_1.getBackgroundFromHoverState)({ hovered: true, selected: false })
130
+ : colors_1.TRANSPARENT,
131
+ idleColor: colors_1.LIGHT_TEXT,
132
+ hoverColor: showsHover ? colors_1.WHITE : colors_1.LIGHT_TEXT,
133
133
  }),
134
- color,
135
134
  ...(size === 'compact' ? compactInlineLabelButton : null),
136
135
  ...(isSegmented ? segmentedMainAction : null),
137
136
  ...style,
138
- }), [color, disabled, hovered, isSegmented, size, style]);
139
- const textStyle = react_1.default.useMemo(() => ({
140
- ...inlineLabelText,
141
- color,
142
- }), [color]);
143
- const onPointerEnter = react_1.default.useCallback(() => {
144
- setHovered(true);
145
- }, []);
146
- const onPointerLeave = react_1.default.useCallback(() => {
147
- setHovered(false);
148
- }, []);
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 })
137
+ }), [disabled, showsHover, isSegmented, size, style]);
138
+ const mainContent = (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [renderIcon ? (jsx_runtime_1.jsx("span", { style: inlineLabelIcon, children: renderIcon(colors_1.CURRENT_COLOR) })) : null, jsx_runtime_1.jsx("span", { style: inlineLabelText, children: children })
150
139
  ] }));
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 }));
140
+ const mainAction = onClick ? (jsx_runtime_1.jsx("button", { className: `__remotion-inspector-inline-action ${hoverable_1.HOVERABLE_CLASS_NAME}`, type: "button", disabled: disabled, style: buttonStyle, title: title, onClick: onClick, children: mainContent })) : (jsx_runtime_1.jsx("div", { className: hoverable_1.HOVERABLE_CLASS_NAME, style: buttonStyle, title: title, children: mainContent }));
152
141
  if (variant.type === 'segmented') {
153
- const trailingColor = hovered && !variant.trailing.disabled ? colors_1.WHITE : colors_1.LIGHT_TEXT;
154
142
  const trailingStyle = {
155
143
  ...segmentedTrailingAction,
156
- backgroundColor: variant.trailing.disabled
157
- ? colors_1.TRANSPARENT
158
- : (0, colors_1.getBackgroundFromHoverState)({
159
- hovered,
160
- selected: false,
161
- }),
144
+ ...(0, hoverable_1.hoverableStyle)({
145
+ idleBackground: colors_1.TRANSPARENT,
146
+ hoverBackground: variant.trailing.disabled
147
+ ? colors_1.TRANSPARENT
148
+ : (0, colors_1.getBackgroundFromHoverState)({ hovered: true, selected: false }),
149
+ idleColor: colors_1.LIGHT_TEXT,
150
+ hoverColor: variant.trailing.disabled ? colors_1.LIGHT_TEXT : colors_1.WHITE,
151
+ }),
162
152
  height: size === 'compact'
163
153
  ? layout_1.COMPACT_INLINE_ROW_HEIGHT
164
154
  : layout_1.COMPACT_CONTROL_ROW_HEIGHT,
165
155
  opacity: variant.trailing.disabled ? 0.35 : 1,
166
156
  };
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) }) })
157
+ return (jsx_runtime_1.jsxs("div", { className: hoverable_1.HOVER_GROUP_CLASS_NAME, style: segmentedInlineAction, children: [mainAction, jsx_runtime_1.jsx("button", { type: "button", className: hoverable_1.HOVERABLE_CLASS_NAME, disabled: variant.trailing.disabled, style: trailingStyle, title: variant.trailing.title, onClick: variant.trailing.onClick, children: jsx_runtime_1.jsx("span", { className: hoverable_1.HOVER_GROUP_REVEAL_CLASS_NAME, style: inlineLabelIcon, children: variant.trailing.renderIcon(colors_1.CURRENT_COLOR) }) })
168
158
  ] }));
169
159
  }
170
160
  return mainAction;
@@ -266,7 +266,7 @@ const InspectorSequenceSection = ({ sequence, readOnlyStudio, validatedLocation,
266
266
  jsx_runtime_1.jsx("span", { style: remoteSourceLeading, children: parts.leading }), jsx_runtime_1.jsx("span", { style: remoteSourceTrailing, children: parts.trailing })
267
267
  ] })),
268
268
  disabled: false,
269
- onClick: null,
269
+ onClick: () => (0, timeline_asset_link_1.openTimelineAssetLink)(linkInfo, selectAsset),
270
270
  title: linkInfo.href,
271
271
  };
272
272
  }
@@ -9,6 +9,7 @@ const player_1 = require("@remotion/player");
9
9
  const react_1 = require("react");
10
10
  const react_dom_1 = __importDefault(require("react-dom"));
11
11
  const colors_1 = require("../../helpers/colors");
12
+ const hoverable_1 = require("../../helpers/hoverable");
12
13
  const pointer_session_1 = require("../../helpers/pointer-session");
13
14
  const z_index_1 = require("../../state/z-index");
14
15
  const MenuContent_1 = require("../NewComposition/MenuContent");
@@ -17,7 +18,6 @@ const portals_1 = require("./portals");
17
18
  const styles_1 = require("./styles");
18
19
  const container = {
19
20
  fontSize: 13,
20
- color: colors_1.WHITE_ALPHA_80,
21
21
  paddingLeft: 10,
22
22
  paddingRight: 10,
23
23
  cursor: 'default',
@@ -28,7 +28,6 @@ const container = {
28
28
  border: 'none',
29
29
  };
30
30
  const MenuItem = ({ label: itemName, selected, id, onItemSelected, onItemHovered, onItemQuit, onPreviousMenu, onNextMenu, menu, }) => {
31
- const [hovered, setHovered] = (0, react_1.useState)(false);
32
31
  const ref = (0, react_1.useRef)(null);
33
32
  const size = player_1.PlayerInternals.useElementSize(ref, {
34
33
  triggerOnWindowResize: true,
@@ -38,13 +37,20 @@ const MenuItem = ({ label: itemName, selected, id, onItemSelected, onItemHovered
38
37
  const containerStyle = (0, react_1.useMemo)(() => {
39
38
  return {
40
39
  ...container,
41
- color: hovered || selected ? colors_1.WHITE : colors_1.WHITE_ALPHA_80,
42
- backgroundColor: (0, colors_1.getBackgroundFromHoverState)({
43
- hovered,
44
- selected,
40
+ ...(0, hoverable_1.hoverableStyle)({
41
+ idleBackground: (0, colors_1.getBackgroundFromHoverState)({
42
+ hovered: false,
43
+ selected,
44
+ }),
45
+ hoverBackground: (0, colors_1.getBackgroundFromHoverState)({
46
+ hovered: true,
47
+ selected,
48
+ }),
49
+ idleColor: selected ? colors_1.WHITE : colors_1.WHITE_ALPHA_80,
50
+ hoverColor: colors_1.WHITE,
45
51
  }),
46
52
  };
47
- }, [hovered, selected]);
53
+ }, [selected]);
48
54
  const portalStyle = (0, react_1.useMemo)(() => {
49
55
  if (!selected || !size) {
50
56
  return null;
@@ -55,13 +61,11 @@ const MenuItem = ({ label: itemName, selected, id, onItemSelected, onItemHovered
55
61
  top: size.top + size.height,
56
62
  };
57
63
  }, [selected, size]);
64
+ // Not for styling (which is done via CSS :hover), but for switching
65
+ // between menus when a menu is already open.
58
66
  const onPointerEnter = (0, react_1.useCallback)(() => {
59
67
  onItemHovered(id);
60
- setHovered(true);
61
68
  }, [id, onItemHovered]);
62
- const onPointerLeave = (0, react_1.useCallback)(() => {
63
- setHovered(false);
64
- }, []);
65
69
  const onPointerDown = (0, react_1.useCallback)((e) => {
66
70
  // Prevent deselection of currently selected items
67
71
  e.stopPropagation();
@@ -105,7 +109,7 @@ const MenuItem = ({ label: itemName, selected, id, onItemSelected, onItemHovered
105
109
  };
106
110
  }, [size]);
107
111
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
108
- jsx_runtime_1.jsx("button", { ref: ref, role: "button", tabIndex: tabIndex, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, onPointerDown: onPointerDown, onClick: onClick, style: containerStyle, type: "button", className: is_menu_item_1.MENU_INITIATOR_CLASSNAME, children: itemName }), portalStyle
112
+ jsx_runtime_1.jsx("button", { ref: ref, role: "button", tabIndex: tabIndex, onPointerEnter: onPointerEnter, onPointerDown: onPointerDown, onClick: onClick, style: containerStyle, type: "button", className: `${is_menu_item_1.MENU_INITIATOR_CLASSNAME} ${hoverable_1.HOVERABLE_CLASS_NAME}`, children: itemName }), portalStyle
109
113
  ? react_dom_1.default.createPortal(jsx_runtime_1.jsx("div", { className: "css-reset", style: outerStyle, children: jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onEscape: onItemQuit, onOutsideClick: onItemQuit, children: jsx_runtime_1.jsx("div", { style: portalStyle, onPointerDown: onMenuPointerDown, children: jsx_runtime_1.jsx(MenuContent_1.MenuContent, { onNextMenu: onPreviousMenu, onPreviousMenu: onNextMenu, values: menu.items, onHide: onItemQuit, leaveLeftSpace: menu.leaveLeftPadding, preselectIndex: false, topItemCanBeUnselected: true, fixedHeight: null }) }) }) }), (0, portals_1.getPortal)(currentZIndex))
110
114
  : null] }));
111
115
  };
@@ -3,13 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MenuBuildIndicator = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
- const client_id_1 = require("../helpers/client-id");
7
6
  const colors_1 = require("../helpers/colors");
8
- const get_git_menu_item_1 = require("../helpers/get-git-menu-item");
9
- const open_in_editor_1 = require("../helpers/open-in-editor");
7
+ const InspectorOpenInEditor_1 = require("./InspectorOpenInEditor");
10
8
  const layout_1 = require("./layout");
11
9
  const MenuCompositionName_1 = require("./MenuCompositionName");
12
- const NotificationCenter_1 = require("./Notifications/NotificationCenter");
13
10
  const Spinner_1 = require("./Spinner");
14
11
  const cwd = {
15
12
  fontSize: 13,
@@ -28,60 +25,15 @@ const noSpinner = {
28
25
  position: 'relative',
29
26
  width: spinnerSize,
30
27
  };
31
- const projectNameLinkBase = {
32
- color: 'inherit',
33
- textDecoration: 'none',
34
- cursor: 'pointer',
35
- fontSize: 'inherit',
36
- textUnderlineOffset: 2,
37
- };
38
- const projectNameLink = {
39
- ...projectNameLinkBase,
40
- };
41
- const projectNameLinkHovered = {
42
- ...projectNameLinkBase,
43
- textDecoration: 'underline',
44
- };
45
28
  const MenuBuildIndicator = ({ mobileLayout }) => {
46
29
  const [isBuilding, setIsBuilding] = (0, react_1.useState)(false);
47
- const [projectNameHovered, setProjectNameHovered] = (0, react_1.useState)(false);
48
- const ctx = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx).previewServerState;
49
- const showEditorLink = window.remotion_editorName && ctx.type === 'connected';
50
- const showGitLink = !showEditorLink && Boolean(window.remotion_gitSource);
51
- const handleProjectNameClick = (0, react_1.useCallback)(async () => {
52
- if (showEditorLink) {
53
- await (0, open_in_editor_1.openInEditor)({
54
- originalFileName: `${window.remotion_cwd}`,
55
- originalLineNumber: 1,
56
- originalColumnNumber: 1,
57
- originalFunctionName: null,
58
- originalScriptCode: null,
59
- }, null)
60
- .then(({ success }) => {
61
- if (!success) {
62
- (0, NotificationCenter_1.showNotification)(`Could not open ${window.remotion_editorName}`, 2000);
63
- }
64
- })
65
- .catch((err) => {
66
- // eslint-disable-next-line no-console
67
- console.error(err);
68
- (0, NotificationCenter_1.showNotification)(`Could not open ${window.remotion_editorName}`, 2000);
69
- });
70
- }
71
- else if (showGitLink) {
72
- window.open((0, get_git_menu_item_1.getGitSourceBranchUrl)(window.remotion_gitSource), '_blank');
73
- }
74
- }, [showEditorLink, showGitLink]);
75
- const projectNameTitle = (0, react_1.useMemo)(() => {
76
- if (showEditorLink) {
77
- return `Open in ${window.remotion_editorName}`;
78
- }
79
- if (showGitLink) {
80
- return `Open ${(0, get_git_menu_item_1.getGitSourceName)(window.remotion_gitSource)} Repo`;
81
- }
82
- return undefined;
83
- }, [showEditorLink, showGitLink]);
84
- const isClickable = showEditorLink || showGitLink;
30
+ const folderLocation = (0, react_1.useMemo)(() => {
31
+ return {
32
+ source: window.remotion_cwd,
33
+ line: 1,
34
+ column: 1,
35
+ };
36
+ }, []);
85
37
  (0, react_1.useEffect)(() => {
86
38
  window.remotion_isBuilding = () => {
87
39
  setIsBuilding(true);
@@ -94,8 +46,9 @@ const MenuBuildIndicator = ({ mobileLayout }) => {
94
46
  window.remotion_finishedBuilding = undefined;
95
47
  };
96
48
  }, []);
97
- return (jsx_runtime_1.jsxs("div", { style: cwd, title: window.remotion_cwd, children: [isClickable ? jsx_runtime_1.jsx(layout_1.Spacing, { x: mobileLayout ? 0.5 : 2 }) : null, mobileLayout ? null : isBuilding ? (jsx_runtime_1.jsx("div", { style: spinner, children: jsx_runtime_1.jsx(Spinner_1.Spinner, { duration: 0.5, size: spinnerSize, color: colors_1.WHITE_ALPHA_80 }) })) : (jsx_runtime_1.jsx("div", { style: noSpinner })), mobileLayout ? null : jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), isClickable ? (jsx_runtime_1.jsx("a", { style: projectNameHovered ? projectNameLinkHovered : projectNameLink, title: projectNameTitle, onClick: handleProjectNameClick, onPointerEnter: () => setProjectNameHovered(true), onPointerLeave: () => setProjectNameHovered(false), children: window.remotion_projectName })) : (window.remotion_projectName), jsx_runtime_1.jsx(MenuCompositionName_1.MenuCompositionName, {}), mobileLayout && isBuilding ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
49
+ return (jsx_runtime_1.jsxs("div", { style: cwd, title: window.remotion_cwd, children: [
50
+ jsx_runtime_1.jsx(layout_1.Spacing, { x: mobileLayout ? 0.5 : 2 }), window.remotion_projectName, jsx_runtime_1.jsx(MenuCompositionName_1.MenuCompositionName, {}), jsx_runtime_1.jsx(InspectorOpenInEditor_1.InspectorOpenInEditor, { location: folderLocation }), mobileLayout ? null : jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), mobileLayout ? (isBuilding ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
98
51
  jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx("div", { style: spinner, children: jsx_runtime_1.jsx(Spinner_1.Spinner, { duration: 0.5, size: spinnerSize, color: colors_1.WHITE_ALPHA_80 }) })
99
- ] })) : null] }));
52
+ ] })) : null) : isBuilding ? (jsx_runtime_1.jsx("div", { style: spinner, children: jsx_runtime_1.jsx(Spinner_1.Spinner, { duration: 0.5, size: spinnerSize, color: colors_1.WHITE_ALPHA_80 }) })) : (jsx_runtime_1.jsx("div", { style: noSpinner }))] }));
100
53
  };
101
54
  exports.MenuBuildIndicator = MenuBuildIndicator;
@@ -4,13 +4,7 @@ exports.MenuCompositionName = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
- const client_id_1 = require("../helpers/client-id");
8
7
  const colors_1 = require("../helpers/colors");
9
- const get_file_manager_name_1 = require("../helpers/get-file-manager-name");
10
- const open_in_editor_1 = require("../helpers/open-in-editor");
11
- const NotificationCenter_1 = require("./Notifications/NotificationCenter");
12
- const actions_1 = require("./RenderQueue/actions");
13
- const use_resolved_stack_1 = require("./Timeline/use-resolved-stack");
14
8
  const baseStyle = {
15
9
  color: 'inherit',
16
10
  textDecoration: 'none',
@@ -22,14 +16,6 @@ const compositionNameStyle = {
22
16
  ...baseStyle,
23
17
  cursor: 'default',
24
18
  };
25
- const clickableStyle = {
26
- ...baseStyle,
27
- cursor: 'pointer',
28
- };
29
- const clickableHoveredStyle = {
30
- ...clickableStyle,
31
- textDecoration: 'underline',
32
- };
33
19
  const slashStyle = {
34
20
  color: colors_1.LIGHT_TEXT,
35
21
  marginInline: 4,
@@ -37,12 +23,8 @@ const slashStyle = {
37
23
  top: 1,
38
24
  };
39
25
  const MenuCompositionName = () => {
40
- var _a, _b;
26
+ var _a;
41
27
  const { canvasContent, compositions } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
42
- const connectionStatus = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx)
43
- .previewServerState.type;
44
- const [opening, setOpening] = (0, react_1.useState)(false);
45
- const [hovered, setHovered] = (0, react_1.useState)(false);
46
28
  const composition = (0, react_1.useMemo)(() => {
47
29
  var _a;
48
30
  if (canvasContent === null || canvasContent.type !== 'composition') {
@@ -51,54 +33,12 @@ const MenuCompositionName = () => {
51
33
  return ((_a = compositions.find((c) => c.id === canvasContent.compositionId)) !== null && _a !== void 0 ? _a : null);
52
34
  }, [canvasContent, compositions]);
53
35
  const asset = (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'asset' ? canvasContent.asset : null;
54
- const resolvedLocation = (0, use_resolved_stack_1.useResolvedStack)((_a = composition === null || composition === void 0 ? void 0 : composition.stack) !== null && _a !== void 0 ? _a : null);
55
- const fileManagerName = (0, get_file_manager_name_1.getFileManagerName)(window.remotion_fileSystemPlatform);
56
- const canOpenComposition = resolvedLocation &&
57
- window.remotion_editorName &&
58
- connectionStatus === 'connected';
59
- const canOpenAsset = asset !== null &&
60
- window.remotion_publicFolderExists !== null &&
61
- connectionStatus === 'connected';
62
- const canOpen = canOpenComposition || canOpenAsset;
63
- const handleClick = (0, react_1.useCallback)(async () => {
64
- if (!canOpen || opening) {
65
- return;
66
- }
67
- setOpening(true);
68
- try {
69
- if (asset !== null && window.remotion_publicFolderExists !== null) {
70
- await (0, actions_1.openInFileExplorer)({
71
- directory: `${window.remotion_publicFolderExists}/${asset}`,
72
- });
73
- }
74
- else if (resolvedLocation) {
75
- await (0, open_in_editor_1.openOriginalPositionInEditor)(resolvedLocation, null);
76
- }
77
- }
78
- catch (err) {
79
- (0, NotificationCenter_1.showNotification)(err.message, 2000);
80
- }
81
- finally {
82
- setOpening(false);
83
- }
84
- }, [asset, canOpen, opening, resolvedLocation]);
85
36
  if (!composition && asset === null) {
86
37
  return null;
87
38
  }
88
- const name = (_b = composition === null || composition === void 0 ? void 0 : composition.id) !== null && _b !== void 0 ? _b : asset;
89
- const title = composition
90
- ? canOpenComposition
91
- ? `Open in ${window.remotion_editorName}`
92
- : composition.id
93
- : canOpenAsset
94
- ? `Show in ${fileManagerName}`
95
- : (asset !== null && asset !== void 0 ? asset : undefined);
39
+ const name = (_a = composition === null || composition === void 0 ? void 0 : composition.id) !== null && _a !== void 0 ? _a : asset;
96
40
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
97
- jsx_runtime_1.jsx("span", { style: slashStyle, children: "/" }), jsx_runtime_1.jsx("a", { style: canOpen && !opening
98
- ? hovered
99
- ? clickableHoveredStyle
100
- : clickableStyle
101
- : compositionNameStyle, title: title, onClick: handleClick, onPointerEnter: () => setHovered(true), onPointerLeave: () => setHovered(false), children: name })
41
+ jsx_runtime_1.jsx("span", { style: slashStyle, children: "/" }), jsx_runtime_1.jsx("span", { style: compositionNameStyle, children: name })
102
42
  ] }));
103
43
  };
104
44
  exports.MenuCompositionName = MenuCompositionName;
@@ -3,11 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MenuToolbar = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
+ const ShortcutHint_1 = require("../error-overlay/remotion-overlay/ShortcutHint");
6
7
  const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
7
8
  const client_id_1 = require("../helpers/client-id");
8
9
  const colors_1 = require("../helpers/colors");
9
10
  const mobile_layout_1 = require("../helpers/mobile-layout");
11
+ const use_keybinding_1 = require("../helpers/use-keybinding");
10
12
  const use_menu_structure_1 = require("../helpers/use-menu-structure");
13
+ const search_1 = require("../icons/search");
14
+ const modals_1 = require("../state/modals");
15
+ const InlineAction_1 = require("./InlineAction");
11
16
  const layout_1 = require("./layout");
12
17
  const menu_toolbar_height_1 = require("./menu-toolbar-height");
13
18
  const MenuItem_1 = require("./Menu/MenuItem");
@@ -34,6 +39,7 @@ const flex = {
34
39
  const MenuToolbar = ({ readOnlyStudio }) => {
35
40
  const [selected, setSelected] = (0, react_1.useState)(null);
36
41
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
42
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
37
43
  const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
38
44
  const canUndoAndRedo = !readOnlyStudio ||
39
45
  (previewServerState.type === 'connected' &&
@@ -104,9 +110,23 @@ const MenuToolbar = ({ readOnlyStudio }) => {
104
110
  // Prevent deselection of currently selected items
105
111
  e.stopPropagation();
106
112
  }, []);
113
+ const openQuickSwitcher = (0, react_1.useCallback)(() => {
114
+ setSelectedModal({
115
+ type: 'quick-switcher',
116
+ mode: 'compositions',
117
+ invocationTimestamp: Date.now(),
118
+ assetSelection: null,
119
+ compositionSelection: null,
120
+ });
121
+ }, [setSelectedModal]);
122
+ const renderSearchIcon = (0, react_1.useCallback)((color) => {
123
+ return jsx_runtime_1.jsx(search_1.SearchIcon, { color: color, width: 18, height: 18 });
124
+ }, []);
125
+ const searchTooltip = (0, use_keybinding_1.areKeyboardShortcutsDisabled)()
126
+ ? 'Quick Switcher'
127
+ : `Quick Switcher (${ShortcutHint_1.cmdOrCtrlCharacter}+K)`;
107
128
  return (jsx_runtime_1.jsxs(layout_1.Row, { align: "center", className: "css-reset", style: row, onPointerDown: onPointerDown, children: [
108
- jsx_runtime_1.jsxs("div", { style: fixedWidthLeft, children: [
109
- jsx_runtime_1.jsx(SidebarCollapserControls_1.SidebarCollapserControl, { side: "left" }), structure.map((s) => {
129
+ jsx_runtime_1.jsxs("div", { style: fixedWidthLeft, children: [mobileLayout ? (jsx_runtime_1.jsx(InlineAction_1.InlineAction, { variant: null, onClick: openQuickSwitcher, renderAction: renderSearchIcon, title: searchTooltip })) : (jsx_runtime_1.jsx(SidebarCollapserControls_1.SidebarCollapserControl, { side: "left" })), structure.map((s) => {
110
130
  return (jsx_runtime_1.jsx(MenuItem_1.MenuItem, { selected: selected === s.id, onItemSelected: itemClicked, onItemHovered: itemHovered, id: s.id, label: s.label, onItemQuit: onItemQuit, menu: s, onPreviousMenu: onPreviousMenu, onNextMenu: onNextMenu, leaveLeftPadding: s.leaveLeftPadding }, s.id));
111
131
  }), readOnlyStudio || browserStudioOperations ? null : jsx_runtime_1.jsx(UpdateCheck_1.UpdateCheck, {})] }), mobileLayout ? null : jsx_runtime_1.jsx("div", { style: flex }), jsx_runtime_1.jsx(MenuBuildIndicator_1.MenuBuildIndicator, { mobileLayout: mobileLayout }), jsx_runtime_1.jsx("div", { style: flex }), jsx_runtime_1.jsxs("div", { style: fixedWidthRight, children: [canUndoAndRedo ? jsx_runtime_1.jsx(UndoRedoButtons_1.UndoRedoButtons, {}) : null, jsx_runtime_1.jsx(SidebarCollapserControls_1.SidebarCollapserControl, { side: "right" })
112
132
  ] })
@@ -66,6 +66,7 @@ export declare const InputDragger: React.ForwardRefExoticComponent<InputHTMLAttr
66
66
  readonly buttonStyle?: React.CSSProperties | undefined;
67
67
  readonly rightAlign: boolean;
68
68
  readonly small?: boolean | undefined;
69
+ readonly allowStepMismatch?: boolean | undefined;
69
70
  readonly snapToStep?: boolean | undefined;
70
71
  readonly dragDecimalPlaces?: number | undefined;
71
72
  readonly dragSensitivity?: number | undefined;
@@ -295,7 +295,7 @@ const deriveInputDraggerValueDiff = ({ dragSensitivity, step, xDistance, }) => {
295
295
  return (0, remotion_1.interpolate)(xDistance, [-5, -4, 0, 4, 5], [-step * dragSensitivity, 0, 0, 0, step * dragSensitivity]);
296
296
  };
297
297
  exports.deriveInputDraggerValueDiff = deriveInputDraggerValueDiff;
298
- const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min, max: _max, step: _step, value, onTextChange, formatter = (q) => String(q), formatterStyle, formatterSubtitle, formatterSubtitleStyle, buttonStyle, status, rightAlign, small, snapToStep = true, dragDecimalPlaces, dragSensitivity = 1, type: _type, ...props }, ref) => {
298
+ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min, max: _max, step: _step, value, onTextChange, formatter = (q) => String(q), formatterStyle, formatterSubtitle, formatterSubtitleStyle, buttonStyle, status, rightAlign, small, allowStepMismatch = false, snapToStep = true, dragDecimalPlaces, dragSensitivity = 1, type: _type, ...props }, ref) => {
299
299
  const [inputFallback, setInputFallback] = (0, react_1.useState)(false);
300
300
  const [dragging, setDragging] = (0, react_1.useState)(false);
301
301
  const fallbackRef = (0, react_1.useRef)(null);
@@ -307,6 +307,7 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
307
307
  step: _step,
308
308
  });
309
309
  }, [_min, _step, snapToStep]);
310
+ const validationStep = allowStepMismatch ? 'any' : deriveStep;
310
311
  const span = (0, react_1.useMemo)(() => ({
311
312
  color: dragging ? 'var(--remotion-cli-internals-blue-hovered)' : colors_1.BLUE,
312
313
  cursor: 'ew-resize',
@@ -366,7 +367,7 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
366
367
  const validation = (0, exports.validateInputDraggerValue)({
367
368
  max: _max,
368
369
  min: _min,
369
- step: deriveStep,
370
+ step: validationStep,
370
371
  value: newValue,
371
372
  });
372
373
  if (validation.valid) {
@@ -378,7 +379,7 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
378
379
  fallbackRef.current.setCustomValidity(validation.message);
379
380
  fallbackRef.current.reportValidity();
380
381
  }
381
- }, [_max, _min, deriveStep, onEscape, onValueChangeEnd]);
382
+ }, [_max, _min, onEscape, onValueChangeEnd, validationStep]);
382
383
  const onInputKeyDown = (0, react_1.useCallback)((e) => {
383
384
  var _a;
384
385
  if (e.key === 'Enter') {
@@ -483,7 +484,7 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
483
484
  }
484
485
  }, [inputFallback]);
485
486
  if (inputFallback) {
486
- return (jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onEscape: onEscape, onOutsideClick: noop_1.noop, children: jsx_runtime_1.jsx(RemInput_1.RemotionInput, { ref: fallbackRef, autoFocus: true, onKeyDown: onInputKeyDown, onBlur: onBlur, onChange: onInputChange, min: _min, max: _max, step: deriveStep, defaultValue: value, status: status, rightAlign: rightAlign, small: small, ...props, type: "text" }) }));
487
+ return (jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onEscape: onEscape, onOutsideClick: noop_1.noop, children: jsx_runtime_1.jsx(RemInput_1.RemotionInput, { ref: fallbackRef, autoFocus: true, onKeyDown: onInputKeyDown, onBlur: onBlur, onChange: onInputChange, min: _min, max: _max, step: validationStep, defaultValue: value, status: status, rightAlign: rightAlign, small: small, ...props, type: "text" }) }));
487
488
  }
488
489
  return (jsx_runtime_1.jsxs("button", { ref: ref, type: "button", "aria-label": props['aria-label'], className: '__remotion_input_dragger', style: buttonStyle
489
490
  ? { ...exports.inputDraggerContainerStyle, ...buttonStyle }
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import type { ComboboxValue } from './ComboBox';
3
3
  export declare const MenuContent: React.FC<{
4
- readonly values: ComboboxValue[];
4
+ readonly values: readonly ComboboxValue[];
5
5
  readonly onHide: () => void;
6
6
  readonly onNextMenu: () => void;
7
7
  readonly onPreviousMenu: () => void;
@@ -1,5 +1,5 @@
1
1
  import type { ComboboxValue } from './ComboBox';
2
2
  export declare const findTypeaheadMenuItem: ({ query, values, }: {
3
3
  query: string;
4
- values: ComboboxValue[];
4
+ values: readonly ComboboxValue[];
5
5
  }) => string | null;
@@ -30,7 +30,7 @@ const PlayPause = ({ playbackRate, loop, bufferStateDelayInMilliseconds, muted,
30
30
  const { inFrame, outFrame } = (0, in_out_1.useTimelineInOutFramePosition)();
31
31
  const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
32
32
  const [showBufferIndicator, setShowBufferState] = (0, react_1.useState)(false);
33
- const { playing, play, pause, pauseAndReturnToPlayStart, frameBack, seek, frameForward, isLastFrame, isFirstFrame, emitter, getCurrentFrame, } = player_1.PlayerInternals.usePlayer();
33
+ const { playing, play, pause, pauseAndReturnToPlayStart, frameBack, seek, frameForward, emitter, getCurrentFrame, } = player_1.PlayerInternals.usePlayer();
34
34
  player_1.PlayerInternals.usePlayback({
35
35
  loop,
36
36
  playbackRate,
@@ -194,6 +194,6 @@ const PlayPause = ({ playbackRate, loop, bufferStateDelayInMilliseconds, muted,
194
194
  stopped = true;
195
195
  };
196
196
  }, [bufferStateDelayInMilliseconds, emitter]);
197
- return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [hideNavigationControls ? null : (jsx_runtime_1.jsx(ControlButton_1.ControlButton, { "aria-label": "Jump to beginning", title: "Jump to beginning", disabled: !videoConfig || isFirstFrame, onClick: jumpToStart, children: (color) => jsx_runtime_1.jsx(jump_to_start_1.JumpToStart, { style: backStyle, color: color }) })), hideNavigationControls ? null : (jsx_runtime_1.jsx(ControlButton_1.ControlButton, { "aria-label": "Step back one frame", title: "Step back one frame", disabled: !videoConfig || isFirstFrame, onClick: oneFrameBack, children: (color) => jsx_runtime_1.jsx(step_back_1.StepBack, { style: forwardBackStyle, color: color }) })), jsx_runtime_1.jsx(ControlButton_1.ControlButton, { "aria-label": playing ? 'Pause' : 'Play', title: playing ? 'Pause' : 'Play', onClick: playing ? pause : play, disabled: !videoConfig, children: (color) => playing ? (showBufferIndicator ? (jsx_runtime_1.jsx(player_1.PlayerInternals.BufferingIndicator, { type: "studio", color: color })) : (jsx_runtime_1.jsx(pause_1.Pause, { style: iconButton, color: color }))) : (jsx_runtime_1.jsx(play_1.Play, { style: iconButton, color: color })) }), hideNavigationControls ? null : (jsx_runtime_1.jsx(ControlButton_1.ControlButton, { "aria-label": "Step forward one frame", title: "Step forward one frame", disabled: !videoConfig || isLastFrame, onClick: oneFrameForward, children: (color) => jsx_runtime_1.jsx(step_forward_1.StepForward, { style: forwardBackStyle, color: color }) }))] }));
197
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [hideNavigationControls ? null : (jsx_runtime_1.jsx(ControlButton_1.ControlButton, { "aria-label": "Jump to beginning", title: "Jump to beginning", disabled: !videoConfig, onClick: jumpToStart, children: (color) => jsx_runtime_1.jsx(jump_to_start_1.JumpToStart, { style: backStyle, color: color }) })), hideNavigationControls ? null : (jsx_runtime_1.jsx(ControlButton_1.ControlButton, { "aria-label": "Step back one frame", title: "Step back one frame", disabled: !videoConfig, onClick: oneFrameBack, children: (color) => jsx_runtime_1.jsx(step_back_1.StepBack, { style: forwardBackStyle, color: color }) })), jsx_runtime_1.jsx(ControlButton_1.ControlButton, { "aria-label": playing ? 'Pause' : 'Play', title: playing ? 'Pause' : 'Play', onClick: playing ? pause : play, disabled: !videoConfig, children: (color) => playing ? (showBufferIndicator ? (jsx_runtime_1.jsx(player_1.PlayerInternals.BufferingIndicator, { type: "studio", color: color })) : (jsx_runtime_1.jsx(pause_1.Pause, { style: iconButton, color: color }))) : (jsx_runtime_1.jsx(play_1.Play, { style: iconButton, color: color })) }), hideNavigationControls ? null : (jsx_runtime_1.jsx(ControlButton_1.ControlButton, { "aria-label": "Step forward one frame", title: "Step forward one frame", disabled: !videoConfig, onClick: oneFrameForward, children: (color) => jsx_runtime_1.jsx(step_forward_1.StepForward, { style: forwardBackStyle, color: color }) }))] }));
198
198
  };
199
199
  exports.PlayPause = PlayPause;
@@ -7,9 +7,9 @@ const remotion_1 = require("remotion");
7
7
  const colors_1 = require("../helpers/colors");
8
8
  const is_current_selected_still_1 = require("../helpers/is-current-selected-still");
9
9
  const Checkmark_1 = require("../icons/Checkmark");
10
+ const playback_rate_1 = require("../icons/playback-rate");
10
11
  const playbackrate_1 = require("../state/playbackrate");
11
- const ControlButton_1 = require("./ControlButton");
12
- const ComboBox_1 = require("./NewComposition/ComboBox");
12
+ const TimelineCombobox_1 = require("./TimelineCombobox");
13
13
  const commonPlaybackRates = [
14
14
  -4, -2, -1, -0.5, -0.25, 0.25, 0.5, 1, 1.5, 2, 4,
15
15
  ];
@@ -17,7 +17,6 @@ const getPlaybackRateLabel = (playbackRate) => {
17
17
  return `${playbackRate}x`;
18
18
  };
19
19
  const accessibilityLabel = 'Change the playback rate';
20
- const comboStyle = { width: 64 };
21
20
  const usePlaybackRateMenuItems = ({ playbackRate, setPlaybackRate, }) => {
22
21
  const items = (0, react_1.useMemo)(() => {
23
22
  const divider = {
@@ -58,14 +57,9 @@ const PlaybackRateSelector = ({ playbackRate, setPlaybackRate, }) => {
58
57
  playbackRate,
59
58
  setPlaybackRate,
60
59
  });
61
- const style = (0, react_1.useMemo)(() => {
62
- return {
63
- padding: ControlButton_1.CONTROL_BUTTON_PADDING - 2,
64
- };
65
- }, []);
66
60
  if (isStill || canvasContent === null || canvasContent.type === 'asset') {
67
61
  return null;
68
62
  }
69
- return (jsx_runtime_1.jsx("div", { style: style, "aria-label": accessibilityLabel, children: jsx_runtime_1.jsx(ComboBox_1.Combobox, { size: "compact", title: accessibilityLabel, style: comboStyle, selectedId: selectedId, values: items, unhoveredIconColor: colors_1.WHITE_ALPHA_80 }) }));
63
+ return (jsx_runtime_1.jsx(TimelineCombobox_1.TimelineCombobox, { title: accessibilityLabel, labelWidth: 30, selectedId: selectedId, values: items, renderLeftItem: (color) => (jsx_runtime_1.jsx(playback_rate_1.PlaybackRateIcon, { color: color, playbackRate: playbackRate })), unhoveredIconColor: colors_1.WHITE_ALPHA_80 }));
70
64
  };
71
65
  exports.PlaybackRateSelector = PlaybackRateSelector;
@@ -57,7 +57,8 @@ const padding = {
57
57
  width: timeline_layout_1.TIMELINE_PADDING,
58
58
  };
59
59
  const toolbarControl = {
60
- display: 'contents',
60
+ display: 'flex',
61
+ flexShrink: 0,
61
62
  };
62
63
  const PreviewToolbarControl = ({ children }) => {
63
64
  const onPointerDown = (0, react_1.useCallback)((e) => {
@@ -79,14 +80,16 @@ const PreviewToolbar = ({ readOnlyStudio, bufferStateDelayInMilliseconds }) => {
79
80
  const playPause = (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(PlayPause_1.PlayPause, { bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds, loop: loop, playbackRate: playbackRate, muted: playerMuted, hideNavigationControls: isMobileLayout }) }));
80
81
  return (jsx_runtime_1.jsxs("div", { style: container, className: "css-reset", children: [
81
82
  jsx_runtime_1.jsxs("div", { style: sideContainer, children: [
82
- jsx_runtime_1.jsx("div", { style: padding }), isMobileLayout ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
83
+ jsx_runtime_1.jsx("div", { style: padding }), isMobileLayout ? null : (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(SizeSelector_1.SizeSelector, {}) })), !isMobileLayout && (isStill || isVideoComposition) ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
84
+ jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate }) })
85
+ ] })) : null, isMobileLayout ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
83
86
  jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(PreviewToolbarOverflowButton_1.PreviewToolbarOverflowButton, { showFullscreen: Boolean(canvasContent && isFullscreenSupported), showPlaybackRate: isVideoComposition, showLoop: isVideoComposition, showCompositionControls: (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition', playbackRate: playbackRate, setPlaybackRate: setPlaybackRate, loop: loop, setLoop: setLoop }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1.5 })
84
- ] })) : null, isVideoComposition && isMobileLayout ? (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(MuteToggle_1.MuteToggle, { muted: playerMuted, setMuted: setPlayerMuted }) })) : null] }), jsx_runtime_1.jsx(layout_1.Flex, {}), isMobileLayout ? null : (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(SizeSelector_1.SizeSelector, {}) })), !isMobileLayout && (isStill || isVideoComposition) ? (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate }) })) : null, isVideoComposition && isMobileLayout ? (jsx_runtime_1.jsx("div", { style: centeredPlayButton, children: playPause })) : null, isVideoComposition && !isMobileLayout ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
87
+ ] })) : null, isVideoComposition && isMobileLayout ? (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(MuteToggle_1.MuteToggle, { muted: playerMuted, setMuted: setPlayerMuted }) })) : null] }), jsx_runtime_1.jsx(layout_1.Flex, {}), isVideoComposition && isMobileLayout ? (jsx_runtime_1.jsx("div", { style: centeredPlayButton, children: playPause })) : null, isVideoComposition && !isMobileLayout ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
85
88
  jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), playPause, jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(LoopToggle_1.LoopToggle, { loop: loop, setLoop: setLoop }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.75 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(MuteToggle_1.MuteToggle, { muted: playerMuted, setMuted: setPlayerMuted }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(TimelineInOutToggle_1.TimelineInOutPointToggle, {}) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 })
86
89
  ] })) : null, (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition' ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [isMobileLayout ? null : (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(CheckboardToggle_1.CheckboardToggle, {}) })), isMobileLayout ? null : jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.25 }), isMobileLayout ? null : (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(OutlineToggle_1.OutlineToggle, {}) })), readOnlyStudio || isMobileLayout ? null : (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
87
90
  jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.25 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(SnappingToggle_1.SnappingToggle, {}) })
88
91
  ] }))] })) : null, jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), canvasContent && isFullscreenSupported ? (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(FullscreenToggle_1.FullScreenToggle, { hidden: isMobileLayout }) })) : null, jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsxs("div", { style: sideContainer, children: [
89
- jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsx(FpsCounter_1.FpsCounter, { playbackSpeed: playbackRate }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(RenderButton_1.RenderButton, { readOnlyStudio: readOnlyStudio, size: "compact" }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1.5 })
92
+ jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsx(FpsCounter_1.FpsCounter, { playbackSpeed: playbackRate }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(RenderButton_1.RenderButton, { readOnlyStudio: readOnlyStudio, size: "compact", narrow: isMobileLayout }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1.5 })
90
93
  ] }), jsx_runtime_1.jsx(PlaybackKeyboardShortcutsManager_1.PlaybackKeyboardShortcutsManager, { setPlaybackRate: setPlaybackRate }), jsx_runtime_1.jsx(PlaybackRatePersistor_1.PlaybackRatePersistor, {})
91
94
  ] }));
92
95
  };
@@ -3,4 +3,5 @@ export type RenderType = 'server-render' | 'client-render' | 'render-command';
3
3
  export declare const RenderButton: React.FC<{
4
4
  readonly readOnlyStudio: boolean;
5
5
  readonly size?: 'default' | 'compact';
6
+ readonly narrow?: boolean;
6
7
  }>;