@remotion/studio 4.0.475 → 4.0.477

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 (88) hide show
  1. package/dist/components/Canvas.js +40 -1
  2. package/dist/components/ColorPicker/ColorPickerPopup.d.ts +6 -0
  3. package/dist/components/ColorPicker/ColorPickerPopup.js +11 -6
  4. package/dist/components/ControlButton.d.ts +1 -0
  5. package/dist/components/ControlButton.js +7 -2
  6. package/dist/components/EditorGuides/Guide.js +122 -20
  7. package/dist/components/EditorRuler/Ruler.js +21 -15
  8. package/dist/components/EditorRuler/index.js +18 -10
  9. package/dist/components/GlobalKeybindings.js +12 -0
  10. package/dist/components/KeyboardShortcutsExplainer.js +24 -0
  11. package/dist/components/NewComposition/InputDragger.d.ts +6 -0
  12. package/dist/components/NewComposition/InputDragger.js +40 -14
  13. package/dist/components/NewComposition/RenameComposition.js +8 -1
  14. package/dist/components/NewComposition/RenameFolder.js +8 -1
  15. package/dist/components/NewComposition/RenameStaticFile.js +11 -1
  16. package/dist/components/Notifications/Notification.js +5 -4
  17. package/dist/components/Notifications/NotificationCenter.js +1 -1
  18. package/dist/components/ObserveDefaultPropsContext.js +6 -2
  19. package/dist/components/OutlineToggle.js +1 -1
  20. package/dist/components/PlayPause.js +22 -66
  21. package/dist/components/PreviewToolbar.js +15 -1
  22. package/dist/components/RenderModal/RenderModalJSONPropsEditor.js +2 -1
  23. package/dist/components/SelectedOutlineElement.d.ts +17 -0
  24. package/dist/components/SelectedOutlineElement.js +938 -0
  25. package/dist/components/SelectedOutlineOverlay.d.ts +4 -174
  26. package/dist/components/SelectedOutlineOverlay.js +310 -1392
  27. package/dist/components/SelectedOutlineUvControls.js +1 -1
  28. package/dist/components/ShowGuidesProvider.js +4 -4
  29. package/dist/components/Timeline/SubscribeToNodePaths.d.ts +2 -1
  30. package/dist/components/Timeline/SubscribeToNodePaths.js +2 -1
  31. package/dist/components/Timeline/Timeline.js +3 -1
  32. package/dist/components/Timeline/TimelineClipboardKeybindings.js +9 -10
  33. package/dist/components/Timeline/TimelineDeleteKeybindings.js +15 -4
  34. package/dist/components/Timeline/TimelineKeyframeEasingLine.js +7 -11
  35. package/dist/components/Timeline/TimelineList.js +1 -1
  36. package/dist/components/Timeline/TimelineRotationField.js +17 -17
  37. package/dist/components/Timeline/TimelineScaleField.js +1 -1
  38. package/dist/components/Timeline/TimelineSelection.d.ts +27 -13
  39. package/dist/components/Timeline/TimelineSelection.js +47 -28
  40. package/dist/components/Timeline/TimelineSequence.js +169 -8
  41. package/dist/components/Timeline/TimelineSequenceFrame.d.ts +1 -0
  42. package/dist/components/Timeline/TimelineSequenceFrame.js +17 -6
  43. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -0
  44. package/dist/components/Timeline/TimelineSequenceItem.js +294 -142
  45. package/dist/components/Timeline/TimelineSequenceName.d.ts +4 -2
  46. package/dist/components/Timeline/TimelineSequenceName.js +67 -2
  47. package/dist/components/Timeline/TimelineTransformOriginField.js +1 -1
  48. package/dist/components/Timeline/TimelineTranslateField.js +1 -1
  49. package/dist/components/Timeline/TimelineUvCoordinateField.js +1 -1
  50. package/dist/components/Timeline/delete-selected-timeline-item.js +4 -0
  51. package/dist/components/Timeline/disable-sequence-interactivity.d.ts +8 -0
  52. package/dist/components/Timeline/disable-sequence-interactivity.js +24 -0
  53. package/dist/components/Timeline/duplicate-selected-timeline-item.d.ts +1 -2
  54. package/dist/components/Timeline/get-sequence-context-menu-items.d.ts +20 -0
  55. package/dist/components/Timeline/get-sequence-context-menu-items.js +160 -0
  56. package/dist/components/Timeline/reset-selected-timeline-props.js +2 -2
  57. package/dist/components/Timeline/sequence-props-subscription-store.d.ts +2 -1
  58. package/dist/components/Timeline/sequence-props-subscription-store.js +11 -3
  59. package/dist/components/Timeline/should-clear-selection-on-pointer-down.d.ts +2 -0
  60. package/dist/components/Timeline/should-clear-selection-on-pointer-down.js +16 -2
  61. package/dist/components/Timeline/timeline-rotation-utils.d.ts +1 -1
  62. package/dist/components/Timeline/timeline-rotation-utils.js +4 -2
  63. package/dist/components/Timeline/update-selected-easing.d.ts +4 -6
  64. package/dist/components/Timeline/use-sequence-props-subscription.d.ts +2 -1
  65. package/dist/components/Timeline/use-sequence-props-subscription.js +3 -1
  66. package/dist/components/Timeline/use-timeline-keyframe-drag.d.ts +37 -1
  67. package/dist/components/Timeline/use-timeline-keyframe-drag.js +290 -14
  68. package/dist/components/import-assets.d.ts +36 -8
  69. package/dist/components/import-assets.js +170 -10
  70. package/dist/components/selected-outline-drag.d.ts +117 -0
  71. package/dist/components/selected-outline-drag.js +427 -0
  72. package/dist/components/selected-outline-measurement.d.ts +67 -0
  73. package/dist/components/selected-outline-measurement.js +355 -0
  74. package/dist/components/selected-outline-types.d.ts +121 -0
  75. package/dist/components/selected-outline-types.js +15 -0
  76. package/dist/components/selected-outline-uv.d.ts +1 -0
  77. package/dist/components/selected-outline-uv.js +12 -0
  78. package/dist/esm/{chunk-qaqqvw4q.js → chunk-t8fjnw2d.js} +14059 -12029
  79. package/dist/esm/internals.mjs +14059 -12029
  80. package/dist/esm/previewEntry.mjs +14066 -12036
  81. package/dist/esm/renderEntry.mjs +1 -1
  82. package/dist/helpers/editor-guide-selection.d.ts +31 -0
  83. package/dist/helpers/editor-guide-selection.js +58 -0
  84. package/dist/helpers/editor-ruler.d.ts +3 -3
  85. package/dist/helpers/editor-ruler.js +16 -18
  86. package/dist/state/editor-guides.d.ts +2 -2
  87. package/dist/state/editor-guides.js +2 -2
  88. package/package.json +11 -11
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.InputDragger = void 0;
36
+ exports.InputDragger = exports.deriveInputDraggerStep = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  const remotion_1 = require("remotion");
@@ -46,7 +46,25 @@ const RemInput_1 = require("./RemInput");
46
46
  const isInt = (num) => {
47
47
  return num % 1 === 0;
48
48
  };
49
- const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min, max: _max, step: _step, value, onTextChange, formatter = (q) => String(q), status, rightAlign, small, snapToStep = true, ...props }, ref) => {
49
+ const roundToDecimalPlaces = (val, decimalPlaces) => {
50
+ const factor = 10 ** decimalPlaces;
51
+ const rounded = Math.round(val * factor) / factor;
52
+ return Object.is(rounded, -0) ? 0 : rounded;
53
+ };
54
+ const deriveInputDraggerStep = ({ min, snapToStep, step, }) => {
55
+ if (!snapToStep) {
56
+ return 'any';
57
+ }
58
+ if (step !== undefined) {
59
+ return step;
60
+ }
61
+ if (typeof min === 'number' && isInt(min)) {
62
+ return 1;
63
+ }
64
+ return 0.0001;
65
+ };
66
+ exports.deriveInputDraggerStep = deriveInputDraggerStep;
67
+ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min, max: _max, step: _step, value, onTextChange, formatter = (q) => String(q), status, rightAlign, small, snapToStep = true, dragDecimalPlaces, ...props }, ref) => {
50
68
  const [inputFallback, setInputFallback] = (0, react_1.useState)(false);
51
69
  const [dragging, setDragging] = (0, react_1.useState)(false);
52
70
  const fallbackRef = (0, react_1.useRef)(null);
@@ -142,7 +160,11 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
142
160
  }
143
161
  const diff = (0, remotion_1.interpolate)(xDistance, [-5, -4, 0, 4, 5], [-step, 0, 0, 0, step]);
144
162
  const newValue = Math.min(max, Math.max(min, Number(value) + diff));
145
- const nextValue = snapToStep ? roundToStep(newValue, step) : newValue;
163
+ const nextValue = snapToStep
164
+ ? roundToStep(newValue, step)
165
+ : dragDecimalPlaces === undefined
166
+ ? newValue
167
+ : roundToDecimalPlaces(newValue, dragDecimalPlaces);
146
168
  lastDragValue = nextValue;
147
169
  onValueChange(nextValue);
148
170
  };
@@ -161,7 +183,16 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
161
183
  }, {
162
184
  once: true,
163
185
  });
164
- }, [_step, _min, _max, value, onValueChange, onValueChangeEnd, snapToStep]);
186
+ }, [
187
+ _step,
188
+ _min,
189
+ _max,
190
+ value,
191
+ onValueChange,
192
+ onValueChangeEnd,
193
+ snapToStep,
194
+ dragDecimalPlaces,
195
+ ]);
165
196
  (0, react_1.useEffect)(() => {
166
197
  var _a;
167
198
  if (inputFallback) {
@@ -169,16 +200,11 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
169
200
  }
170
201
  }, [inputFallback]);
171
202
  const deriveStep = (0, react_1.useMemo)(() => {
172
- if (!snapToStep) {
173
- return 'any';
174
- }
175
- if (_step !== undefined) {
176
- return _step;
177
- }
178
- if (typeof _min === 'number' && isInt(_min)) {
179
- return 1;
180
- }
181
- return 0.0001;
203
+ return (0, exports.deriveInputDraggerStep)({
204
+ min: _min,
205
+ snapToStep,
206
+ step: _step,
207
+ });
182
208
  }, [_min, _step, snapToStep]);
183
209
  if (inputFallback) {
184
210
  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, onKeyPress: onKeyPress, onBlur: onBlur, onChange: onInputChange, min: _min, max: _max, step: deriveStep, defaultValue: value, status: status, pattern: '[0-9]*[.]?[0-9]*', rightAlign: rightAlign, ...props, ...(small ? { style: { padding: '4px 6px', fontSize: 12 } } : {}) }) }));
@@ -33,6 +33,13 @@ const RenameCompositionLoaded = () => {
33
33
  const [newId, setName] = (0, react_1.useState)(() => {
34
34
  return resolved.result.id;
35
35
  });
36
+ const inputRef = (0, react_1.useRef)(null);
37
+ (0, react_1.useEffect)(() => {
38
+ const input = inputRef.current;
39
+ if (!input)
40
+ return;
41
+ input.select();
42
+ }, []);
36
43
  const onNameChange = (0, react_1.useCallback)((e) => {
37
44
  setName(e.target.value);
38
45
  }, []);
@@ -54,7 +61,7 @@ const RenameCompositionLoaded = () => {
54
61
  jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: `Rename ${resolved.result.id}` }), jsx_runtime_1.jsxs("form", { onSubmit: onSubmit, children: [
55
62
  jsx_runtime_1.jsx("div", { style: content, children: jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
56
63
  jsx_runtime_1.jsx("div", { style: layout_2.label, children: "ID" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsxs("div", { children: [
57
- jsx_runtime_1.jsx(RemInput_1.RemotionInput, { value: newId, onChange: onNameChange, type: "text", autoFocus: true, placeholder: "Composition ID", status: "ok", rightAlign: true }), compNameErrMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
64
+ jsx_runtime_1.jsx(RemInput_1.RemotionInput, { ref: inputRef, value: newId, onChange: onNameChange, type: "text", autoFocus: true, placeholder: "Composition ID", status: "ok", rightAlign: true }), compNameErrMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
58
65
  jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: compNameErrMessage, type: "error" })
59
66
  ] })) : null] }) })
60
67
  ] }) }), jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { children: jsx_runtime_1.jsx(CodemodFooter_1.CodemodFooter, { loadingNotification: 'Renaming...', errorNotification: 'Could not rename composition', successNotification: `Renamed to ${newId}`, genericSubmitLabel: 'Rename', submitLabel: ({ relativeRootPath }) => `Modify ${relativeRootPath}`, codemod: codemod, stack: compositionStack, valid: valid, onSuccess: null }) })
@@ -24,6 +24,13 @@ const content = {
24
24
  const RenameFolder = ({ folderName, parentName, stack }) => {
25
25
  const { folders } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
26
26
  const [newName, setName] = (0, react_1.useState)(folderName);
27
+ const inputRef = (0, react_1.useRef)(null);
28
+ (0, react_1.useEffect)(() => {
29
+ const input = inputRef.current;
30
+ if (!input)
31
+ return;
32
+ input.select();
33
+ }, []);
27
34
  const onNameChange = (0, react_1.useCallback)((e) => {
28
35
  setName(e.target.value);
29
36
  }, []);
@@ -50,7 +57,7 @@ const RenameFolder = ({ folderName, parentName, stack }) => {
50
57
  jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: `Rename ${folderId}` }), jsx_runtime_1.jsxs("form", { onSubmit: onSubmit, children: [
51
58
  jsx_runtime_1.jsx("div", { style: content, children: jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
52
59
  jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Name" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsxs("div", { children: [
53
- jsx_runtime_1.jsx(RemInput_1.RemotionInput, { value: newName, onChange: onNameChange, type: "text", autoFocus: true, placeholder: "Folder name", status: "ok", rightAlign: true }), folderNameErrMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
60
+ jsx_runtime_1.jsx(RemInput_1.RemotionInput, { ref: inputRef, value: newName, onChange: onNameChange, type: "text", autoFocus: true, placeholder: "Folder name", status: "ok", rightAlign: true }), folderNameErrMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
54
61
  jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: folderNameErrMessage, type: "error" })
55
62
  ] })) : null] }) })
56
63
  ] }) }), jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { children: jsx_runtime_1.jsx(CodemodFooter_1.CodemodFooter, { loadingNotification: 'Renaming folder...', errorNotification: 'Could not rename folder', successNotification: `Renamed folder to ${newName}`, genericSubmitLabel: 'Rename', submitLabel: ({ relativeRootPath }) => `Modify ${relativeRootPath}`, codemod: codemod, stack: stack, valid: valid, onSuccess: null }) })
@@ -39,6 +39,16 @@ const RenameStaticFileModal = ({ relativePath }) => {
39
39
  const staticFiles = (0, use_static_files_1.useStaticFiles)();
40
40
  const [newName, setNewName] = (0, react_1.useState)(() => getBaseName(relativePath));
41
41
  const [submitting, setSubmitting] = (0, react_1.useState)(false);
42
+ const inputRef = (0, react_1.useRef)(null);
43
+ (0, react_1.useEffect)(() => {
44
+ const input = inputRef.current;
45
+ if (!input)
46
+ return;
47
+ const dotIndex = newName.lastIndexOf('.');
48
+ const stemEnd = dotIndex === -1 ? newName.length : dotIndex;
49
+ input.setSelectionRange(0, stemEnd);
50
+ // eslint-disable-next-line react-hooks/exhaustive-deps
51
+ }, []);
42
52
  const parent = (0, react_1.useMemo)(() => getParent(relativePath), [relativePath]);
43
53
  const newRelativePath = (0, react_1.useMemo)(() => {
44
54
  return [parent, newName].filter(Boolean).join('/');
@@ -106,7 +116,7 @@ const RenameStaticFileModal = ({ relativePath }) => {
106
116
  jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: `Rename ${relativePath}` }), jsx_runtime_1.jsxs("form", { onSubmit: onSubmit, children: [
107
117
  jsx_runtime_1.jsx("div", { style: content, children: jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
108
118
  jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Name" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsxs("div", { children: [
109
- jsx_runtime_1.jsx(RemInput_1.RemotionInput, { value: newName, onChange: onNameChange, type: "text", autoFocus: true, autoComplete: "off", "data-1p-ignore": true, placeholder: "Asset name", status: validationMessage ? 'error' : 'ok', rightAlign: true }), validationMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
119
+ jsx_runtime_1.jsx(RemInput_1.RemotionInput, { ref: inputRef, value: newName, onChange: onNameChange, type: "text", autoFocus: true, autoComplete: "off", "data-1p-ignore": true, placeholder: "Asset name", status: validationMessage ? 'error' : 'ok', rightAlign: true }), validationMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
110
120
  jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: validationMessage, type: "error" })
111
121
  ] })) : null] }) })
112
122
  ] }) }), jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { children: jsx_runtime_1.jsxs(layout_1.Row, { align: "center", justify: "flex-end", children: [
@@ -3,14 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Notification = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
+ const colors_1 = require("../../helpers/colors");
6
7
  const notification = {
7
8
  backgroundColor: '#111111',
8
- color: 'white',
9
+ color: colors_1.TEXT_COLOR,
9
10
  fontFamily: 'Arial, Helvetica, sans-serif',
10
11
  display: 'inline-flex',
11
- padding: '8px 14px',
12
- borderRadius: 4,
13
- fontSize: 15,
12
+ padding: '6px 14px',
13
+ borderRadius: 6,
14
+ fontSize: 13,
14
15
  border: '0.25px solid rgba(255, 255, 255, 0.1)',
15
16
  boxShadow: '0 2px 3px rgba(0, 0, 0, 1)',
16
17
  marginTop: 3,
@@ -11,7 +11,7 @@ const container = {
11
11
  display: 'flex',
12
12
  width: '100%',
13
13
  flexDirection: 'column',
14
- paddingTop: 20,
14
+ paddingTop: 40,
15
15
  pointerEvents: 'none',
16
16
  backgroundColor: 'transparent',
17
17
  };
@@ -37,6 +37,7 @@ exports.ObserveDefaultProps = exports.ObserveDefaultPropsContext = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  const remotion_1 = require("remotion");
40
+ const no_react_1 = require("remotion/no-react");
40
41
  const client_id_1 = require("../helpers/client-id");
41
42
  const call_api_1 = require("./call-api");
42
43
  exports.ObserveDefaultPropsContext = react_1.default.createContext(null);
@@ -60,10 +61,13 @@ const ObserveDefaultProps = ({ compositionId, readOnlyStudio, children }) => {
60
61
  ...prevState,
61
62
  [compId]: { canUpdate: true },
62
63
  }));
64
+ // Resolve `remotion-file:` and `remotion-date:` tokens that the
65
+ // server emits for staticFile() and new Date() values
66
+ const deserialized = no_react_1.NoReactInternals.deserializeJSONWithSpecialTypes(JSON.stringify(result.currentDefaultProps));
63
67
  updateProps({
64
68
  id: compId,
65
- defaultProps: result.currentDefaultProps,
66
- newProps: result.currentDefaultProps,
69
+ defaultProps: deserialized,
70
+ newProps: deserialized,
67
71
  });
68
72
  }
69
73
  else {
@@ -15,6 +15,6 @@ const OutlineToggle = () => {
15
15
  const accessibilityLabel = editorShowOutlines
16
16
  ? 'Hide outlines'
17
17
  : 'Show outlines';
18
- return (jsx_runtime_1.jsx(ControlButton_1.ControlButton, { title: accessibilityLabel, "aria-label": accessibilityLabel, onClick: onClick, children: jsx_runtime_1.jsx("svg", { style: { width: 16, height: 16 }, viewBox: "0 0 512 512", fill: color, "aria-hidden": "true", focusable: "false", children: jsx_runtime_1.jsx("path", { d: "M32 119.4C12.9 108.4 0 87.7 0 64 0 28.7 28.7 0 64 0 87.7 0 108.4 12.9 119.4 32l273.1 0c11.1-19.1 31.7-32 55.4-32 35.3 0 64 28.7 64 64 0 23.7-12.9 44.4-32 55.4l0 273.1c19.1 11.1 32 31.7 32 55.4 0 35.3-28.7 64-64 64-23.7 0-44.4-12.9-55.4-32l-273.1 0c-11.1 19.1-31.7 32-55.4 32-35.3 0-64-28.7-64-64 0-23.7 12.9-44.4 32-55.4l0-273.1zm64 0l0 273.1c9.7 5.6 17.8 13.7 23.4 23.4l273.1 0c5.6-9.7 13.7-17.8 23.4-23.4l0-273.1c-9.7-5.6-17.8-13.7-23.4-23.4L119.4 96c-5.6 9.7-13.7 17.8-23.4 23.4z" }) }) }));
18
+ return (jsx_runtime_1.jsx(ControlButton_1.ControlButton, { title: accessibilityLabel, "aria-label": accessibilityLabel, onClick: onClick, children: jsx_runtime_1.jsx("svg", { style: { width: 18, height: 18 }, viewBox: "0 0 512 512", fill: color, "aria-hidden": "true", focusable: "false", children: jsx_runtime_1.jsx("path", { d: "M32 119.4C12.9 108.4 0 87.7 0 64 0 28.7 28.7 0 64 0 87.7 0 108.4 12.9 119.4 32l273.1 0c11.1-19.1 31.7-32 55.4-32 35.3 0 64 28.7 64 64 0 23.7-12.9 44.4-32 55.4l0 273.1c19.1 11.1 32 31.7 32 55.4 0 35.3-28.7 64-64 64-23.7 0-44.4-12.9-55.4-32l-273.1 0c-11.1 19.1-31.7 32-55.4 32-35.3 0-64-28.7-64-64 0-23.7 12.9-44.4 32-55.4l0-273.1zm64 0l0 273.1c9.7 5.6 17.8 13.7 23.4 23.4l273.1 0c5.6-9.7 13.7-17.8 23.4-23.4l0-273.1c-9.7-5.6-17.8-13.7-23.4-23.4L119.4 96c-5.6 9.7-13.7 17.8-23.4 23.4z" }) }) }));
19
19
  };
20
20
  exports.OutlineToggle = OutlineToggle;
@@ -68,66 +68,22 @@ const PlayPause = ({ playbackRate, loop, bufferStateDelayInMilliseconds, muted }
68
68
  pauseAndReturnToPlayStart();
69
69
  }
70
70
  }, [pauseAndReturnToPlayStart, playing]);
71
- const onArrowLeft = (0, react_1.useCallback)((e) => {
72
- e.preventDefault();
73
- if (e.altKey) {
74
- seek(0);
75
- (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
76
- direction: 'fit-left',
77
- durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
78
- frame: 0,
79
- });
80
- }
81
- else if (e.shiftKey) {
82
- frameBack((0, imperative_state_1.getCurrentFps)());
83
- (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
84
- direction: 'fit-left',
85
- durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
86
- frame: Math.max(0, getCurrentFrame() - (0, imperative_state_1.getCurrentFps)()),
87
- });
88
- }
89
- else {
90
- frameBack(1);
91
- (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
92
- direction: 'fit-left',
93
- durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
94
- frame: Math.max(0, getCurrentFrame() - 1),
95
- });
96
- }
97
- }, [frameBack, seek, getCurrentFrame]);
98
- const onArrowRight = (0, react_1.useCallback)((e) => {
99
- if (e.altKey) {
100
- seek((0, imperative_state_1.getCurrentDuration)() - 1);
101
- (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
102
- direction: 'fit-right',
103
- durationInFrames: (0, imperative_state_1.getCurrentDuration)() - 1,
104
- frame: (0, imperative_state_1.getCurrentDuration)() - 1,
105
- });
106
- }
107
- else if (e.shiftKey) {
108
- frameForward((0, imperative_state_1.getCurrentFps)());
109
- (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
110
- direction: 'fit-right',
111
- durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
112
- frame: Math.min((0, imperative_state_1.getCurrentDuration)() - 1, getCurrentFrame() + (0, imperative_state_1.getCurrentFps)()),
113
- });
114
- }
115
- else {
116
- frameForward(1);
117
- (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
118
- direction: 'fit-right',
119
- durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
120
- frame: Math.min((0, imperative_state_1.getCurrentDuration)() - 1, getCurrentFrame() + 1),
121
- });
122
- }
123
- e.preventDefault();
124
- }, [frameForward, seek, getCurrentFrame]);
125
71
  const oneFrameBack = (0, react_1.useCallback)(() => {
126
72
  frameBack(1);
127
- }, [frameBack]);
73
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
74
+ direction: 'fit-left',
75
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
76
+ frame: Math.max(0, getCurrentFrame() - 1),
77
+ });
78
+ }, [frameBack, getCurrentFrame]);
128
79
  const oneFrameForward = (0, react_1.useCallback)(() => {
129
80
  frameForward(1);
130
- }, [frameForward]);
81
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
82
+ direction: 'fit-right',
83
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
84
+ frame: Math.min((0, imperative_state_1.getCurrentDuration)() - 1, getCurrentFrame() + 1),
85
+ });
86
+ }, [frameForward, getCurrentFrame]);
131
87
  const jumpToStart = (0, react_1.useCallback)(() => {
132
88
  seek(inFrame !== null && inFrame !== void 0 ? inFrame : 0);
133
89
  }, [seek, inFrame]);
@@ -136,20 +92,20 @@ const PlayPause = ({ playbackRate, loop, bufferStateDelayInMilliseconds, muted }
136
92
  }, [seek, outFrame]);
137
93
  const keybindings = (0, use_keybinding_1.useKeybinding)();
138
94
  (0, react_1.useEffect)(() => {
139
- const arrowLeft = keybindings.registerKeybinding({
95
+ const commandArrowLeft = keybindings.registerKeybinding({
140
96
  event: 'keydown',
141
97
  key: 'ArrowLeft',
142
- callback: onArrowLeft,
143
- commandCtrlKey: false,
98
+ callback: oneFrameBack,
99
+ commandCtrlKey: true,
144
100
  preventDefault: true,
145
101
  triggerIfInputFieldFocused: false,
146
102
  keepRegisteredWhenNotHighestContext: false,
147
103
  });
148
- const arrowRight = keybindings.registerKeybinding({
104
+ const commandArrowRight = keybindings.registerKeybinding({
149
105
  event: 'keydown',
150
106
  key: 'ArrowRight',
151
- callback: onArrowRight,
152
- commandCtrlKey: false,
107
+ callback: oneFrameForward,
108
+ commandCtrlKey: true,
153
109
  preventDefault: true,
154
110
  triggerIfInputFieldFocused: false,
155
111
  keepRegisteredWhenNotHighestContext: false,
@@ -191,8 +147,8 @@ const PlayPause = ({ playbackRate, loop, bufferStateDelayInMilliseconds, muted }
191
147
  keepRegisteredWhenNotHighestContext: false,
192
148
  });
193
149
  return () => {
194
- arrowLeft.unregister();
195
- arrowRight.unregister();
150
+ commandArrowLeft.unregister();
151
+ commandArrowRight.unregister();
196
152
  space.unregister();
197
153
  enter.unregister();
198
154
  a.unregister();
@@ -202,10 +158,10 @@ const PlayPause = ({ playbackRate, loop, bufferStateDelayInMilliseconds, muted }
202
158
  jumpToEnd,
203
159
  jumpToStart,
204
160
  keybindings,
205
- onArrowLeft,
206
- onArrowRight,
207
161
  onEnter,
208
162
  onSpace,
163
+ oneFrameBack,
164
+ oneFrameForward,
209
165
  ]);
210
166
  (0, react_1.useEffect)(() => {
211
167
  let timeout = null;
@@ -95,7 +95,21 @@ const PreviewToolbar = ({ readOnlyStudio, bufferStateDelayInMilliseconds }) => {
95
95
  const isFullscreenSupported = (0, check_fullscreen_support_1.checkFullscreenSupport)();
96
96
  const isMobileLayout = (0, mobile_layout_1.useMobileLayout)();
97
97
  (0, react_1.useEffect)(() => {
98
- if (isMobileLayout && previewToolbarRef.current) {
98
+ if (!isMobileLayout) {
99
+ // The indicators are `position: fixed` and are shown/placed
100
+ // imperatively by the scroll handler below. Without this reset,
101
+ // leaving the mobile layout (window resized past the breakpoint)
102
+ // leaves them visible at stale viewport coordinates — an orphaned
103
+ // grey gradient rectangle floating over the canvas.
104
+ if (leftScrollIndicatorRef.current) {
105
+ leftScrollIndicatorRef.current.style.display = 'none';
106
+ }
107
+ if (rightScrollIndicatorRef.current) {
108
+ rightScrollIndicatorRef.current.style.display = 'none';
109
+ }
110
+ return;
111
+ }
112
+ if (previewToolbarRef.current) {
99
113
  const updateScrollableIndicatorProps = (target) => {
100
114
  var _a;
101
115
  const boundingBox = target.getBoundingClientRect();
@@ -103,7 +103,8 @@ const RenderModalJSONPropsEditor = ({ setValue, value, defaultProps, onSave, ser
103
103
  }
104
104
  const { result } = e;
105
105
  if (result.canUpdate) {
106
- const nextState = parseJS(result.currentDefaultProps, schema);
106
+ const deserialized = no_react_1.NoReactInternals.deserializeJSONWithSpecialTypes(JSON.stringify(result.currentDefaultProps));
107
+ const nextState = parseJS(deserialized, schema);
107
108
  setLocalValue(nextState);
108
109
  }
109
110
  });
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import type { SelectedOutline } from './selected-outline-geometry';
3
+ import { type SelectedOutlineDragTarget, type SelectedOutlineRotationDragTarget, type SelectedOutlineScaleDragTarget, type SelectedOutlineTarget } from './selected-outline-types';
4
+ import type { TimelineSelection, TimelineSelectionInteraction } from './Timeline/TimelineSelection';
5
+ export declare const SelectedOutlineElement: React.FC<{
6
+ readonly allDragTargets: readonly SelectedOutlineDragTarget[];
7
+ readonly allRotationDragTargets: readonly SelectedOutlineRotationDragTarget[];
8
+ readonly allScaleDragTargets: readonly SelectedOutlineScaleDragTarget[];
9
+ readonly dragging: boolean;
10
+ readonly hovered: boolean;
11
+ readonly outline: SelectedOutline;
12
+ readonly onDraggingChange: (dragging: boolean) => void;
13
+ readonly onHoverChange: (key: string | null) => void;
14
+ readonly onSelect: (item: TimelineSelection, interaction: TimelineSelectionInteraction) => void;
15
+ readonly scale: number;
16
+ readonly target: SelectedOutlineTarget | undefined;
17
+ }>;