@remotion/studio 4.0.475 → 4.0.476

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 (36) hide show
  1. package/dist/components/ColorPicker/ColorPickerPopup.d.ts +6 -0
  2. package/dist/components/ColorPicker/ColorPickerPopup.js +11 -6
  3. package/dist/components/GlobalKeybindings.js +12 -0
  4. package/dist/components/KeyboardShortcutsExplainer.js +24 -0
  5. package/dist/components/NewComposition/InputDragger.d.ts +6 -0
  6. package/dist/components/NewComposition/InputDragger.js +40 -14
  7. package/dist/components/NewComposition/RenameComposition.js +8 -1
  8. package/dist/components/NewComposition/RenameFolder.js +8 -1
  9. package/dist/components/NewComposition/RenameStaticFile.js +11 -1
  10. package/dist/components/Notifications/Notification.js +5 -4
  11. package/dist/components/Notifications/NotificationCenter.js +1 -1
  12. package/dist/components/ObserveDefaultPropsContext.js +6 -2
  13. package/dist/components/PlayPause.js +22 -66
  14. package/dist/components/PreviewToolbar.js +15 -1
  15. package/dist/components/RenderModal/RenderModalJSONPropsEditor.js +2 -1
  16. package/dist/components/SelectedOutlineOverlay.d.ts +47 -11
  17. package/dist/components/SelectedOutlineOverlay.js +545 -54
  18. package/dist/components/Timeline/TimelineRotationField.js +17 -17
  19. package/dist/components/Timeline/TimelineScaleField.js +1 -1
  20. package/dist/components/Timeline/TimelineSequenceItem.js +301 -109
  21. package/dist/components/Timeline/TimelineSequenceName.d.ts +4 -2
  22. package/dist/components/Timeline/TimelineSequenceName.js +67 -2
  23. package/dist/components/Timeline/TimelineTransformOriginField.js +1 -1
  24. package/dist/components/Timeline/TimelineTranslateField.js +1 -1
  25. package/dist/components/Timeline/TimelineUvCoordinateField.js +1 -1
  26. package/dist/components/Timeline/disable-sequence-interactivity.d.ts +8 -0
  27. package/dist/components/Timeline/disable-sequence-interactivity.js +24 -0
  28. package/dist/components/Timeline/reset-selected-timeline-props.js +2 -2
  29. package/dist/components/Timeline/timeline-rotation-utils.d.ts +1 -1
  30. package/dist/components/Timeline/timeline-rotation-utils.js +4 -2
  31. package/dist/components/Timeline/use-timeline-keyframe-drag.js +8 -13
  32. package/dist/esm/{chunk-qaqqvw4q.js → chunk-0atarw3p.js} +2659 -1707
  33. package/dist/esm/internals.mjs +2659 -1707
  34. package/dist/esm/previewEntry.mjs +2661 -1709
  35. package/dist/esm/renderEntry.mjs +1 -1
  36. package/package.json +11 -11
@@ -1,5 +1,11 @@
1
1
  import React from 'react';
2
2
  export declare const POPUP_WIDTH = 240;
3
+ export declare const parseEyeDropperColor: (pickedColor: string) => {
4
+ r: number;
5
+ g: number;
6
+ b: number;
7
+ a: number;
8
+ };
3
9
  export type ChannelKey = 'r' | 'g' | 'b' | 'a-percent';
4
10
  export declare const ColorPickerPopup: React.FC<{
5
11
  readonly value: string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ColorPickerPopup = exports.POPUP_WIDTH = void 0;
3
+ exports.ColorPickerPopup = exports.parseEyeDropperColor = exports.POPUP_WIDTH = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const color_conversion_1 = require("../../helpers/color-conversion");
@@ -100,6 +100,14 @@ const eyedropperButtonStyle = {
100
100
  flex: '0 0 auto',
101
101
  };
102
102
  const hasEyeDropper = () => typeof window !== 'undefined' && 'EyeDropper' in window;
103
+ const parseEyeDropperColor = (pickedColor) => {
104
+ const parsed = (0, color_conversion_1.parseAnyColor)(pickedColor);
105
+ return {
106
+ ...parsed,
107
+ a: 255,
108
+ };
109
+ };
110
+ exports.parseEyeDropperColor = parseEyeDropperColor;
103
111
  const ChannelInput = ({ label, channel, value, min, max, onCommit, }) => {
104
112
  const [draft, setDraft] = (0, react_1.useState)(String(Math.round(value)));
105
113
  const { tabIndex } = (0, z_index_1.useZIndex)();
@@ -243,10 +251,7 @@ const ColorPickerPopup = ({ value, onChange, onChangeComplete }) => {
243
251
  dropper
244
252
  .open()
245
253
  .then((result) => {
246
- const parsed = (0, color_conversion_1.parseAnyColor)(result.sRGBHex);
247
- // `EyeDropper` always returns full opacity; preserve the user's
248
- // previously chosen alpha so opening it doesn't drop transparency.
249
- parsed.a = rgba.a;
254
+ const parsed = (0, exports.parseEyeDropperColor)(result.sRGBHex);
250
255
  const newHsva = (0, color_conversion_1.rgbaToHsva)(parsed);
251
256
  if (newHsva.s === 0) {
252
257
  newHsva.h = hsva.h;
@@ -256,7 +261,7 @@ const ColorPickerPopup = ({ value, onChange, onChangeComplete }) => {
256
261
  .catch(() => {
257
262
  // Aborted; ignore.
258
263
  });
259
- }, [emit, hsva.h, rgba.a]);
264
+ }, [emit, hsva.h]);
260
265
  const previewFill = (0, react_1.useMemo)(() => {
261
266
  return {
262
267
  ...previewSwatchFillBase,
@@ -40,6 +40,17 @@ const GlobalKeybindings = () => {
40
40
  commandCtrlKey: true,
41
41
  preventDefault: true,
42
42
  });
43
+ const cmdSKey = keybindings.registerKeybinding({
44
+ event: 'keydown',
45
+ key: 's',
46
+ callback: () => {
47
+ (0, NotificationCenter_1.showNotification)('Remotion saves automatically', 2000);
48
+ },
49
+ triggerIfInputFieldFocused: true,
50
+ keepRegisteredWhenNotHighestContext: false,
51
+ commandCtrlKey: true,
52
+ preventDefault: true,
53
+ });
43
54
  const cmdIKey = process.env.ASK_AI_ENABLED
44
55
  ? keybindings.registerKeybinding({
45
56
  event: 'keydown',
@@ -103,6 +114,7 @@ const GlobalKeybindings = () => {
103
114
  cKey.unregister();
104
115
  questionMark.unregister();
105
116
  cmdKKey.unregister();
117
+ cmdSKey.unregister();
106
118
  cmdIKey === null || cmdIKey === void 0 ? void 0 : cmdIKey.unregister();
107
119
  pageDown.unregister();
108
120
  pageUp.unregister();
@@ -138,6 +138,30 @@ const KeyboardShortcutsExplainer = () => {
138
138
  jsx_runtime_1.jsxs("div", { style: left, children: [
139
139
  jsx_runtime_1.jsx("kbd", { style: key, children: ShortcutHint_1.cmdOrCtrlCharacter }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.3 }), jsx_runtime_1.jsx("kbd", { style: key, children: "Y" })
140
140
  ] }), jsx_runtime_1.jsx("div", { style: right, children: "Redo" })
141
+ ] }), jsx_runtime_1.jsx("br", {}), jsx_runtime_1.jsx("div", { style: title, children: "Interactivity" }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
142
+ jsx_runtime_1.jsx("div", { style: left, children: jsx_runtime_1.jsx("kbd", { style: key, children: "Shift" }) }), jsx_runtime_1.jsx("div", { style: right, children: "Select range / axis lock drag" })
143
+ ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
144
+ jsx_runtime_1.jsx("div", { style: left, children: jsx_runtime_1.jsx("kbd", { style: key, children: ShortcutHint_1.cmdOrCtrlCharacter }) }), jsx_runtime_1.jsx("div", { style: right, children: "Toggle selection" })
145
+ ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
146
+ jsx_runtime_1.jsxs("div", { style: left, children: [
147
+ jsx_runtime_1.jsx("kbd", { style: key, children: ShortcutHint_1.cmdOrCtrlCharacter }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.3 }), jsx_runtime_1.jsx("kbd", { style: key, children: "A" })
148
+ ] }), jsx_runtime_1.jsx("div", { style: right, children: "Select sequence rows" })
149
+ ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
150
+ jsx_runtime_1.jsxs("div", { style: left, children: [
151
+ jsx_runtime_1.jsx("kbd", { style: key, children: ShortcutHint_1.cmdOrCtrlCharacter }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.3 }), jsx_runtime_1.jsx("kbd", { style: key, children: "D" })
152
+ ] }), jsx_runtime_1.jsx("div", { style: right, children: "Duplicate sequences" })
153
+ ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
154
+ jsx_runtime_1.jsxs("div", { style: left, children: [
155
+ jsx_runtime_1.jsx("kbd", { style: key, children: ShortcutHint_1.cmdOrCtrlCharacter }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.3 }), jsx_runtime_1.jsx("kbd", { style: key, children: "C" })
156
+ ] }), jsx_runtime_1.jsx("div", { style: right, children: "Copy effects / values" })
157
+ ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
158
+ jsx_runtime_1.jsxs("div", { style: left, children: [
159
+ jsx_runtime_1.jsx("kbd", { style: key, children: ShortcutHint_1.cmdOrCtrlCharacter }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.3 }), jsx_runtime_1.jsx("kbd", { style: key, children: "V" })
160
+ ] }), jsx_runtime_1.jsx("div", { style: right, children: "Paste effects / values" })
161
+ ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
162
+ jsx_runtime_1.jsxs("div", { style: left, children: [
163
+ jsx_runtime_1.jsx("kbd", { style: key, children: "Del" }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.3 }), jsx_runtime_1.jsx("kbd", { style: key, children: "\u232B" })
164
+ ] }), jsx_runtime_1.jsx("div", { style: right, children: "Delete / reset selection" })
141
165
  ] }), process.env.ASK_AI_ENABLED && (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
142
166
  jsx_runtime_1.jsx("br", {}), jsx_runtime_1.jsx("div", { style: title, children: "AI" }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
143
167
  jsx_runtime_1.jsxs("div", { style: left, children: [
@@ -1,6 +1,11 @@
1
1
  import type { InputHTMLAttributes } from 'react';
2
2
  import React from 'react';
3
3
  import type { RemInputStatus } from './RemInput';
4
+ export declare const deriveInputDraggerStep: ({ min, snapToStep, step, }: {
5
+ readonly min: string | number | undefined;
6
+ readonly snapToStep: boolean;
7
+ readonly step: string | number | undefined;
8
+ }) => string | number;
4
9
  export declare const InputDragger: React.ForwardRefExoticComponent<InputHTMLAttributes<HTMLInputElement> & {
5
10
  readonly onValueChange: (newVal: number) => void;
6
11
  readonly onValueChangeEnd?: ((newVal: number) => void) | undefined;
@@ -10,4 +15,5 @@ export declare const InputDragger: React.ForwardRefExoticComponent<InputHTMLAttr
10
15
  readonly rightAlign: boolean;
11
16
  readonly small?: boolean | undefined;
12
17
  readonly snapToStep?: boolean | undefined;
18
+ readonly dragDecimalPlaces?: number | undefined;
13
19
  } & React.RefAttributes<HTMLButtonElement>>;
@@ -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 {
@@ -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
  });
@@ -19,10 +19,11 @@ type RotationFieldSchema = Extract<SequenceFieldSchema, {
19
19
  type: 'rotation-css';
20
20
  }>;
21
21
  type SelectedOutlineScaleDragTarget = {
22
- readonly propStatus: CanUpdateSequencePropStatusStatic;
22
+ readonly propStatus: CanUpdateSequencePropStatusStatic | CanUpdateSequencePropStatusKeyframed;
23
23
  readonly clientId: string;
24
24
  readonly fieldDefault: number | string | undefined;
25
25
  readonly fieldSchema: ScaleFieldSchema;
26
+ readonly keyframeDisplayOffset: number;
26
27
  readonly linked: boolean;
27
28
  readonly nodePath: SequencePropsSubscriptionKey;
28
29
  readonly schema: SequenceSchema;
@@ -35,6 +36,7 @@ type SelectedOutlineRotationDragTarget = {
35
36
  readonly keyframeDisplayOffset: number;
36
37
  readonly nodePath: SequencePropsSubscriptionKey;
37
38
  readonly schema: SequenceSchema;
39
+ readonly transformOriginValue: string;
38
40
  };
39
41
  export type SelectedOutlineDragState = {
40
42
  readonly defaultValue: string | null;
@@ -47,6 +49,7 @@ export type SelectedOutlineDragState = {
47
49
  export type SelectedOutlineScaleDragState = {
48
50
  readonly defaultValue: string | null;
49
51
  readonly key: string;
52
+ readonly sourceFrame: number;
50
53
  readonly startX: number;
51
54
  readonly startY: number;
52
55
  readonly startZ: number;
@@ -66,6 +69,7 @@ type SequenceWithSelectedOutline = {
66
69
  readonly nodePathInfo: SequenceNodePathInfo;
67
70
  readonly sequence: TSequence;
68
71
  };
72
+ export declare const selectedOutlineDragThresholdPx = 4;
69
73
  export declare const getSelectedOutlineRotationDeltaDegrees: ({ from, to, }: {
70
74
  readonly from: number;
71
75
  readonly to: number;
@@ -77,6 +81,26 @@ export declare const getSelectedOutlineRotationCornerInfo: (points: readonly [Ou
77
81
  cursorDegrees: number;
78
82
  point: OutlinePoint;
79
83
  };
84
+ export declare const getSelectedOutlineRotationPivot: ({ dimensions, points, transformOriginValue, }: {
85
+ readonly dimensions: {
86
+ readonly width: number;
87
+ readonly height: number;
88
+ } | null;
89
+ readonly points: readonly [OutlinePoint, OutlinePoint, OutlinePoint, OutlinePoint];
90
+ readonly transformOriginValue: string;
91
+ }) => OutlinePoint;
92
+ type SvgViewport = {
93
+ readonly x: number;
94
+ readonly y: number;
95
+ readonly width: number;
96
+ readonly height: number;
97
+ };
98
+ type SvgScreenCtm = Pick<DOMMatrixReadOnly, 'a' | 'b' | 'c' | 'd' | 'e' | 'f'>;
99
+ export declare const getTransformedSvgViewportPoints: ({ viewport, ctm, containerRect, }: {
100
+ readonly viewport: SvgViewport;
101
+ readonly ctm: SvgScreenCtm;
102
+ readonly containerRect: Pick<DOMRect, "left" | "top">;
103
+ }) => readonly [OutlinePoint, OutlinePoint, OutlinePoint, OutlinePoint];
80
104
  export declare const getSelectedSequenceKeys: (selectedItems: readonly TimelineSelection[]) => Set<string>;
81
105
  export declare const getOutlineSelectionInteraction: ({ shiftKey, metaKey, ctrlKey, }: {
82
106
  readonly shiftKey: boolean;
@@ -105,6 +129,10 @@ export declare const applySelectedOutlineDragAxisLock: ({ deltaX, deltaY, axisLo
105
129
  deltaX: number;
106
130
  deltaY: number;
107
131
  };
132
+ export declare const isSelectedOutlineDragPastThreshold: ({ deltaX, deltaY, }: {
133
+ readonly deltaX: number;
134
+ readonly deltaY: number;
135
+ }) => boolean;
108
136
  export type SelectedOutlineStaticDragChange = SaveSequencePropChange & {
109
137
  readonly type: 'static';
110
138
  };
@@ -123,19 +151,34 @@ export declare const getSelectedOutlineDragChanges: ({ dragStates, lastValues, }
123
151
  readonly dragStates: readonly SelectedOutlineDragState[];
124
152
  readonly lastValues: ReadonlyMap<string, string>;
125
153
  }) => SelectedOutlineDragChange[];
154
+ export type SelectedOutlineKeyboardNudgeDirection = 'left' | 'right' | 'up' | 'down';
155
+ export declare const getSelectedOutlineKeyboardNudgeDelta: ({ direction, shiftKey, }: {
156
+ readonly direction: SelectedOutlineKeyboardNudgeDirection;
157
+ readonly shiftKey: boolean;
158
+ }) => number;
159
+ export declare const getSelectedOutlineKeyboardNudgeDeltas: ({ deltaX, deltaY, direction, shiftKey, }: {
160
+ readonly deltaX: number;
161
+ readonly deltaY: number;
162
+ readonly direction: SelectedOutlineKeyboardNudgeDirection;
163
+ readonly shiftKey: boolean;
164
+ }) => {
165
+ deltaX: number;
166
+ deltaY: number;
167
+ };
126
168
  export type SelectedOutlineScaleEdge = 'top' | 'right' | 'bottom' | 'left';
127
169
  type SelectedOutlineScaleEdgeInfo = {
128
170
  readonly axis: 'x' | 'y';
129
- readonly cursor: React.CSSProperties['cursor'];
171
+ readonly cursor: string;
130
172
  readonly end: OutlinePoint;
131
173
  readonly extent: number;
132
174
  readonly normal: OutlinePoint;
133
175
  readonly start: OutlinePoint;
134
176
  };
135
177
  export declare const getSelectedOutlineScaleEdgeInfo: (points: readonly [OutlinePoint, OutlinePoint, OutlinePoint, OutlinePoint], edge: SelectedOutlineScaleEdge) => SelectedOutlineScaleEdgeInfo | null;
136
- export declare const getSelectedOutlineScaleDragStates: ({ dragTargets, getDragOverrides, }: {
178
+ export declare const getSelectedOutlineScaleDragStates: ({ dragTargets, getDragOverrides, timelinePosition, }: {
137
179
  readonly dragTargets: readonly SelectedOutlineScaleDragTarget[];
138
180
  readonly getDragOverrides: GetDragOverrides;
181
+ readonly timelinePosition: number;
139
182
  }) => SelectedOutlineScaleDragState[];
140
183
  export declare const getSelectedOutlineScaleDragValues: ({ axis, dragStates, scaleFactor, }: {
141
184
  readonly axis: "x" | "y";
@@ -145,14 +188,7 @@ export declare const getSelectedOutlineScaleDragValues: ({ axis, dragStates, sca
145
188
  export declare const getSelectedOutlineScaleDragChanges: ({ dragStates, lastValues, }: {
146
189
  readonly dragStates: readonly SelectedOutlineScaleDragState[];
147
190
  readonly lastValues: ReadonlyMap<string, string | number>;
148
- }) => {
149
- fileName: string;
150
- nodePath: SequencePropsSubscriptionKey;
151
- fieldKey: string;
152
- value: string | number;
153
- defaultValue: string | null;
154
- schema: SequenceSchema;
155
- }[];
191
+ }) => SelectedOutlineDragChange[];
156
192
  export declare const getSelectedOutlineRotationDragStates: ({ dragTargets, getDragOverrides, timelinePosition, }: {
157
193
  readonly dragTargets: readonly SelectedOutlineRotationDragTarget[];
158
194
  readonly getDragOverrides: GetDragOverrides;