@remotion/cli 4.1.0-alpha1 → 4.1.0-alpha11

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 (108) hide show
  1. package/dist/benchmark.js +16 -7
  2. package/dist/chalk/index.d.ts +2 -1
  3. package/dist/codemods/stringify-with-path.js +24 -19
  4. package/dist/compositions.js +9 -4
  5. package/dist/config/index.d.ts +24 -0
  6. package/dist/config/index.js +19 -1
  7. package/dist/editor/components/Canvas.js +4 -4
  8. package/dist/editor/components/CanvasOrLoading.js +20 -1
  9. package/dist/editor/components/CopyButton.js +5 -2
  10. package/dist/editor/components/Editor.js +1 -3
  11. package/dist/editor/components/FramePersistor.d.ts +0 -2
  12. package/dist/editor/components/FramePersistor.js +4 -24
  13. package/dist/editor/components/FullscreenToggle.d.ts +2 -0
  14. package/dist/editor/components/FullscreenToggle.js +25 -0
  15. package/dist/editor/components/GlobalKeybindings.js +1 -1
  16. package/dist/editor/components/InitialCompositionLoader.js +1 -22
  17. package/dist/editor/components/KeyboardShortcutsExplainer.js +1 -1
  18. package/dist/editor/components/NewComposition/InputDragger.js +13 -1
  19. package/dist/editor/components/NewComposition/RemInput.d.ts +2 -2
  20. package/dist/editor/components/NewComposition/RemInputTypeColor.d.ts +1 -1
  21. package/dist/editor/components/NewComposition/RemTextarea.d.ts +1 -1
  22. package/dist/editor/components/OpenEditorButton.js +5 -2
  23. package/dist/editor/components/PlayPause.js +4 -4
  24. package/dist/editor/components/PlaybackRateSelector.js +1 -1
  25. package/dist/editor/components/PreviewToolbar.js +3 -1
  26. package/dist/editor/components/QuickSwitcher/QuickSwitcherResult.js +3 -3
  27. package/dist/editor/components/RenderModal/DataEditor.d.ts +2 -0
  28. package/dist/editor/components/RenderModal/DataEditor.js +13 -10
  29. package/dist/editor/components/RenderModal/FrameRangeSetting.js +9 -25
  30. package/dist/editor/components/RenderModal/MultiRangeSlider.d.ts +12 -0
  31. package/dist/editor/components/RenderModal/MultiRangeSlider.js +50 -0
  32. package/dist/editor/components/RenderModal/RenderModal.js +7 -3
  33. package/dist/editor/components/RenderModal/RenderModalBasic.d.ts +2 -3
  34. package/dist/editor/components/RenderModal/RenderModalJSONPropsEditor.d.ts +1 -2
  35. package/dist/editor/components/RenderModal/RenderModalJSONPropsEditor.js +10 -11
  36. package/dist/editor/components/RenderModal/SchemaEditor/SchemaEditor.d.ts +2 -2
  37. package/dist/editor/components/RenderModal/SchemaEditor/SchemaEditor.js +26 -0
  38. package/dist/editor/components/RenderModal/SchemaEditor/SchemaErrorMessages.js +1 -3
  39. package/dist/editor/components/RenderModal/SchemaEditor/SchemaLabel.js +1 -2
  40. package/dist/editor/components/RenderModal/SchemaEditor/SchemaSaveButton.js +2 -1
  41. package/dist/editor/components/RenderModal/SchemaEditor/ZodArrayEditor.js +7 -7
  42. package/dist/editor/components/RenderModal/SchemaEditor/ZodBooleanEditor.d.ts +1 -1
  43. package/dist/editor/components/RenderModal/SchemaEditor/ZodBooleanEditor.js +1 -1
  44. package/dist/editor/components/RenderModal/SchemaEditor/ZodColorEditor.js +1 -1
  45. package/dist/editor/components/RenderModal/SchemaEditor/ZodDateEditor.js +1 -1
  46. package/dist/editor/components/RenderModal/SchemaEditor/ZodEffectEditor.js +2 -2
  47. package/dist/editor/components/RenderModal/SchemaEditor/ZodEnumEditor.js +1 -1
  48. package/dist/editor/components/RenderModal/SchemaEditor/ZodFieldValidation.js +1 -1
  49. package/dist/editor/components/RenderModal/SchemaEditor/ZodNonEditableValue.js +1 -1
  50. package/dist/editor/components/RenderModal/SchemaEditor/ZodNumberEditor.js +1 -1
  51. package/dist/editor/components/RenderModal/SchemaEditor/ZodObjectEditor.js +29 -10
  52. package/dist/editor/components/RenderModal/SchemaEditor/ZodOrNullishEditor.js +2 -2
  53. package/dist/editor/components/RenderModal/SchemaEditor/ZodStaticFileEditor.js +1 -1
  54. package/dist/editor/components/RenderModal/SchemaEditor/ZodStringEditor.js +1 -1
  55. package/dist/editor/components/RenderModal/SchemaEditor/ZodSwitch.js +0 -1
  56. package/dist/editor/components/RenderModal/SchemaEditor/local-state.js +9 -3
  57. package/dist/editor/components/RenderModal/human-readable-codec.d.ts +1 -1
  58. package/dist/editor/components/RenderQueue/actions.d.ts +1 -1
  59. package/dist/editor/components/RenderQueue/actions.js +12 -4
  60. package/dist/editor/components/RightPanel.js +45 -12
  61. package/dist/editor/components/SetTimelineInOutProvider.js +5 -4
  62. package/dist/editor/components/SidebarRenderButton.js +3 -1
  63. package/dist/editor/components/Timeline/TimelineDragHandler.js +45 -19
  64. package/dist/editor/components/TimelineInOutToggle.d.ts +2 -1
  65. package/dist/editor/components/TimelineInOutToggle.js +82 -67
  66. package/dist/editor/helpers/colors.d.ts +1 -1
  67. package/dist/editor/helpers/is-composition-still.d.ts +1 -1
  68. package/dist/editor/helpers/is-current-selected-still.js +5 -6
  69. package/dist/editor/helpers/use-menu-structure.js +25 -1
  70. package/dist/editor/icons/keys.js +1 -0
  71. package/dist/editor/state/canvas-ref.d.ts +2 -0
  72. package/dist/editor/state/canvas-ref.js +5 -0
  73. package/dist/editor/state/in-out.d.ts +3 -2
  74. package/dist/editor/state/in-out.js +22 -5
  75. package/dist/editor/state/marks.d.ts +3 -2
  76. package/dist/editor/state/marks.js +6 -6
  77. package/dist/get-composition-id.d.ts +6 -6
  78. package/dist/get-composition-id.js +13 -6
  79. package/dist/get-composition-with-dimension-override.d.ts +6 -6
  80. package/dist/get-composition-with-dimension-override.js +3 -3
  81. package/dist/handle-common-errors.js +8 -0
  82. package/dist/index.d.ts +13 -7
  83. package/dist/index.js +5 -2
  84. package/dist/log.d.ts +6 -1
  85. package/dist/parse-command-line.js +1 -1
  86. package/dist/preview-server/dev-middleware/range-parser.d.ts +1 -1
  87. package/dist/preview-server/dev-middleware/setup-hooks.js +1 -1
  88. package/dist/preview-server/render-queue/job.d.ts +2 -2
  89. package/dist/preview-server/render-queue/make-retry-payload.js +3 -2
  90. package/dist/preview-server/render-queue/open-directory-in-finder.js +11 -5
  91. package/dist/preview-server/render-queue/process-still.js +1 -1
  92. package/dist/preview-server/render-queue/process-video.js +1 -1
  93. package/dist/preview-server/routes/add-render.js +2 -2
  94. package/dist/preview-server/routes/update-default-props.js +1 -2
  95. package/dist/print-compositions.d.ts +2 -2
  96. package/dist/print-error.js +6 -3
  97. package/dist/progress-bar.js +2 -5
  98. package/dist/render-flows/render.d.ts +2 -2
  99. package/dist/render-flows/render.js +31 -22
  100. package/dist/render-flows/still.d.ts +2 -2
  101. package/dist/render-flows/still.js +20 -14
  102. package/dist/render.js +6 -1
  103. package/dist/setup-cache.js +1 -1
  104. package/dist/still.js +6 -1
  105. package/package.json +11 -11
  106. package/styles/styles.css +53 -0
  107. package/dist/editor/components/RenderModal/SchemaEditor/input-props-serialization.d.ts +0 -14
  108. package/dist/editor/components/RenderModal/SchemaEditor/input-props-serialization.js +0 -42
@@ -4,5 +4,5 @@ type Props = React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>
4
4
  status: RemInputStatus;
5
5
  name: string;
6
6
  };
7
- export declare const RemInputTypeColor: React.ForwardRefExoticComponent<Pick<Props, "status" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>> & React.RefAttributes<HTMLInputElement>>;
7
+ export declare const RemInputTypeColor: React.ForwardRefExoticComponent<Pick<Props, "key" | "status" | keyof React.InputHTMLAttributes<HTMLInputElement>> & React.RefAttributes<HTMLInputElement>>;
8
8
  export {};
@@ -3,5 +3,5 @@ type Props = React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLTextAreaEleme
3
3
  status: 'error' | 'warning' | 'ok';
4
4
  };
5
5
  export declare const inputBaseStyle: React.CSSProperties;
6
- export declare const RemTextarea: React.ForwardRefExoticComponent<Pick<Props, "status" | "key" | keyof React.InputHTMLAttributes<HTMLTextAreaElement>> & React.RefAttributes<HTMLTextAreaElement>>;
6
+ export declare const RemTextarea: React.ForwardRefExoticComponent<Pick<Props, "key" | "status" | keyof React.InputHTMLAttributes<HTMLTextAreaElement>> & React.RefAttributes<HTMLTextAreaElement>>;
7
7
  export {};
@@ -12,8 +12,11 @@ const svgStyle = {
12
12
  };
13
13
  const buttonStyle = {
14
14
  border: 'none',
15
- width: '25px',
16
- height: '25px',
15
+ width: '20px',
16
+ height: '20px',
17
+ display: 'flex',
18
+ justifyContent: 'center',
19
+ alignItems: 'center',
17
20
  };
18
21
  const OpenEditorButton = () => {
19
22
  const [hovered, setHovered] = (0, react_1.useState)(false);
@@ -114,11 +114,11 @@ const PlayPause = ({ playbackRate, loop }) => {
114
114
  frameForward(1);
115
115
  }, [frameForward]);
116
116
  const jumpToStart = (0, react_1.useCallback)(() => {
117
- seek(0);
118
- }, [seek]);
117
+ seek(inFrame !== null && inFrame !== void 0 ? inFrame : 0);
118
+ }, [seek, inFrame]);
119
119
  const jumpToEnd = (0, react_1.useCallback)(() => {
120
- seek((0, imperative_state_1.getCurrentDuration)() - 1);
121
- }, [seek]);
120
+ seek(outFrame !== null && outFrame !== void 0 ? outFrame : (0, imperative_state_1.getCurrentDuration)() - 1);
121
+ }, [seek, outFrame]);
122
122
  const keybindings = (0, use_keybinding_1.useKeybinding)();
123
123
  (0, react_1.useEffect)(() => {
124
124
  const arrowLeft = keybindings.registerKeybinding({
@@ -9,7 +9,7 @@ const playbackrate_1 = require("../state/playbackrate");
9
9
  const ControlButton_1 = require("./ControlButton");
10
10
  const ComboBox_1 = require("./NewComposition/ComboBox");
11
11
  const commonPlaybackRates = [
12
- -4, -2, -1, -0.5, -0.25, 0.25, 0.5, 1, 2, 4,
12
+ -4, -2, -1, -0.5, -0.25, 0.25, 0.5, 1, 1.5, 2, 4,
13
13
  ];
14
14
  const getPlaybackRateLabel = (playbackRate) => {
15
15
  return `${playbackRate}x`;
@@ -9,6 +9,7 @@ const timeline_layout_1 = require("../helpers/timeline-layout");
9
9
  const loop_1 = require("../state/loop");
10
10
  const CheckboardToggle_1 = require("./CheckboardToggle");
11
11
  const FpsCounter_1 = require("./FpsCounter");
12
+ const FullscreenToggle_1 = require("./FullscreenToggle");
12
13
  const layout_1 = require("./layout");
13
14
  const LoopToggle_1 = require("./LoopToggle");
14
15
  const MuteToggle_1 = require("./MuteToggle");
@@ -45,6 +46,7 @@ const PreviewToolbar = () => {
45
46
  const { mediaMuted } = (0, react_1.useContext)(remotion_1.Internals.MediaVolumeContext);
46
47
  const { setMediaMuted } = (0, react_1.useContext)(remotion_1.Internals.SetMediaVolumeContext);
47
48
  const [loop, setLoop] = (0, react_1.useState)((0, loop_1.loadLoopOption)());
48
- return ((0, jsx_runtime_1.jsxs)("div", { style: container, className: "css-reset", children: [(0, jsx_runtime_1.jsxs)("div", { style: sideContainer, children: [(0, jsx_runtime_1.jsx)("div", { style: padding }), (0, jsx_runtime_1.jsx)(TimelineZoomControls_1.TimelineZoomControls, {})] }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(SizeSelector_1.SizeSelector, {}), (0, jsx_runtime_1.jsx)(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(PlayPause_1.PlayPause, { loop: loop, playbackRate: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(LoopToggle_1.LoopToggle, { loop: loop, setLoop: setLoop }), (0, jsx_runtime_1.jsx)(CheckboardToggle_1.CheckboardToggle, {}), (0, jsx_runtime_1.jsx)(TimelineInOutToggle_1.TimelineInOutPointToggle, {}), (0, jsx_runtime_1.jsx)(MuteToggle_1.MuteToggle, { muted: mediaMuted, setMuted: setMediaMuted }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsxs)("div", { style: sideContainer, children: [(0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(FpsCounter_1.FpsCounter, { playbackSpeed: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(RenderButton_1.RenderButton, {}), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1.5 })] }), (0, jsx_runtime_1.jsx)(PlaybackKeyboardShortcutsManager_1.PlaybackKeyboardShortcutsManager, { setPlaybackRate: setPlaybackRate }), (0, jsx_runtime_1.jsx)(PlaybackRatePersistor_1.PlaybackRatePersistor, {})] }));
49
+ const isFullscreenSupported = document.fullscreenEnabled || document.webkitFullscreenEnabled;
50
+ return ((0, jsx_runtime_1.jsxs)("div", { style: container, className: "css-reset", children: [(0, jsx_runtime_1.jsxs)("div", { style: sideContainer, children: [(0, jsx_runtime_1.jsx)("div", { style: padding }), (0, jsx_runtime_1.jsx)(TimelineZoomControls_1.TimelineZoomControls, {})] }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(SizeSelector_1.SizeSelector, {}), (0, jsx_runtime_1.jsx)(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(PlayPause_1.PlayPause, { loop: loop, playbackRate: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(LoopToggle_1.LoopToggle, { loop: loop, setLoop: setLoop }), (0, jsx_runtime_1.jsx)(CheckboardToggle_1.CheckboardToggle, {}), (0, jsx_runtime_1.jsx)(TimelineInOutToggle_1.TimelineInOutPointToggle, {}), (0, jsx_runtime_1.jsx)(MuteToggle_1.MuteToggle, { muted: mediaMuted, setMuted: setMediaMuted }), isFullscreenSupported && (0, jsx_runtime_1.jsx)(FullscreenToggle_1.FullScreenToggle, {}), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsxs)("div", { style: sideContainer, children: [(0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(FpsCounter_1.FpsCounter, { playbackSpeed: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(RenderButton_1.RenderButton, {}), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1.5 })] }), (0, jsx_runtime_1.jsx)(PlaybackKeyboardShortcutsManager_1.PlaybackKeyboardShortcutsManager, { setPlaybackRate: setPlaybackRate }), (0, jsx_runtime_1.jsx)(PlaybackRatePersistor_1.PlaybackRatePersistor, {})] }));
49
51
  };
50
52
  exports.PreviewToolbar = PreviewToolbar;
@@ -98,14 +98,14 @@ const QuickSwitcherResult = ({ result, selected }) => {
98
98
  fontSize: 15,
99
99
  };
100
100
  }, [hovered, result.type, selected]);
101
- return ((0, jsx_runtime_1.jsxs)("div", { ref: ref, style: style, onClick: result.onSelected, children: [result.type === 'composition' ? (result.compositionType === 'still' ? ((0, jsx_runtime_1.jsx)(still_1.StillIcon, { color: selected ? 'white' : colors_1.LIGHT_TEXT, style: iconStyle })) : ((0, jsx_runtime_1.jsx)(video_1.FilmIcon, { color: selected ? 'white' : colors_1.LIGHT_TEXT, style: iconStyle }))) : null, (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1 }), (0, jsx_runtime_1.jsx)("div", { style: labelContainer, children: result.type === 'search-result' ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: labelStyle,
101
+ return ((0, jsx_runtime_1.jsxs)("div", { ref: ref, style: style, onClick: result.onSelected, children: [result.type === 'composition' ? (result.compositionType === 'still' ? ((0, jsx_runtime_1.jsx)(still_1.StillIcon, { color: selected ? 'white' : colors_1.LIGHT_TEXT, style: iconStyle })) : ((0, jsx_runtime_1.jsx)(video_1.FilmIcon, { color: selected ? 'white' : colors_1.LIGHT_TEXT, style: iconStyle }))) : null, (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1 }), (0, jsx_runtime_1.jsx)("div", { style: labelContainer, children: result.type === 'search-result' ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", {
102
102
  // eslint-disable-next-line react/no-danger
103
103
  dangerouslySetInnerHTML: {
104
104
  __html: result.titleLine,
105
- } }), (0, jsx_runtime_1.jsx)("div", { style: labelStyle,
105
+ }, style: labelStyle }), (0, jsx_runtime_1.jsx)("div", {
106
106
  // eslint-disable-next-line react/no-danger
107
107
  dangerouslySetInnerHTML: {
108
108
  __html: result.subtitleLine,
109
- } })] })) : ((0, jsx_runtime_1.jsx)("div", { style: labelStyle, children: result.title })) })] }, result.id));
109
+ }, style: labelStyle })] })) : ((0, jsx_runtime_1.jsx)("div", { style: labelStyle, children: result.title })) })] }, result.id));
110
110
  };
111
111
  exports.QuickSwitcherResult = QuickSwitcherResult;
@@ -17,4 +17,6 @@ export declare const DataEditor: React.FC<{
17
17
  setInputProps: React.Dispatch<React.SetStateAction<Record<string, unknown>>>;
18
18
  mayShowSaveButton: boolean;
19
19
  propsEditType: PropsEditType;
20
+ saving: boolean;
21
+ setSaving: React.Dispatch<React.SetStateAction<boolean>>;
20
22
  }>;
@@ -39,7 +39,6 @@ const SegmentedControl_1 = require("../SegmentedControl");
39
39
  const get_render_modal_warnings_1 = require("./get-render-modal-warnings");
40
40
  const RenderModalJSONPropsEditor_1 = require("./RenderModalJSONPropsEditor");
41
41
  const extract_enum_json_paths_1 = require("./SchemaEditor/extract-enum-json-paths");
42
- const input_props_serialization_1 = require("./SchemaEditor/input-props-serialization");
43
42
  const SchemaEditor_1 = require("./SchemaEditor/SchemaEditor");
44
43
  const SchemaErrorMessages_1 = require("./SchemaEditor/SchemaErrorMessages");
45
44
  const WarningIndicatorButton_1 = require("./WarningIndicatorButton");
@@ -88,10 +87,8 @@ const getPersistedShowWarningState = () => {
88
87
  const setPersistedShowWarningState = (val) => {
89
88
  localStorage.setItem(persistanceKey, String(Boolean(val)));
90
89
  };
91
- const DataEditor = ({ unresolvedComposition, inputProps, setInputProps, mayShowSaveButton, propsEditType, }) => {
90
+ const DataEditor = ({ unresolvedComposition, inputProps, setInputProps, mayShowSaveButton, propsEditType, saving, setSaving, }) => {
92
91
  const [mode, setMode] = (0, react_1.useState)('schema');
93
- const [valBeforeSafe, setValBeforeSafe] = (0, react_1.useState)(inputProps);
94
- const [saving, setSaving] = (0, react_1.useState)(false);
95
92
  const [showWarning, setShowWarningWithoutPersistance] = (0, react_1.useState)(() => getPersistedShowWarningState());
96
93
  const inJSONEditor = mode === 'json';
97
94
  const serializedJSON = (0, react_1.useMemo)(() => {
@@ -99,7 +96,7 @@ const DataEditor = ({ unresolvedComposition, inputProps, setInputProps, mayShowS
99
96
  return null;
100
97
  }
101
98
  const value = inputProps;
102
- return (0, input_props_serialization_1.serializeJSONWithDate)({
99
+ return remotion_1.Internals.serializeJSONWithDate({
103
100
  data: value,
104
101
  indent: 2,
105
102
  staticBase: window.remotion_staticBase,
@@ -215,7 +212,6 @@ const DataEditor = ({ unresolvedComposition, inputProps, setInputProps, mayShowS
215
212
  (0, NotificationCenter_1.sendErrorNotification)('Cannot update default props: No Zod schema');
216
213
  return;
217
214
  }
218
- setValBeforeSafe(inputProps);
219
215
  (0, actions_1.updateDefaultProps)(unresolvedComposition.id, inputProps, (0, extract_enum_json_paths_1.extractEnumJsonPaths)(schema, z, [])).then((response) => {
220
216
  if (!response.success) {
221
217
  (0, NotificationCenter_1.sendErrorNotification)('Cannot update default props: ' + response.reason);
@@ -224,14 +220,15 @@ const DataEditor = ({ unresolvedComposition, inputProps, setInputProps, mayShowS
224
220
  }, [unresolvedComposition.id, inputProps, schema, z]);
225
221
  (0, react_1.useEffect)(() => {
226
222
  setSaving(false);
227
- }, [fastRefreshes]);
223
+ }, [fastRefreshes, setSaving]);
228
224
  const onSave = (0, react_1.useCallback)((updater) => {
225
+ var _a;
229
226
  if (schema === 'no-zod' || schema === 'no-schema' || z === null) {
230
227
  (0, NotificationCenter_1.sendErrorNotification)('Cannot update default props: No Zod schema');
231
228
  return;
232
229
  }
233
230
  setSaving(true);
234
- (0, actions_1.updateDefaultProps)(unresolvedComposition.id, updater(unresolvedComposition.defaultProps), (0, extract_enum_json_paths_1.extractEnumJsonPaths)(schema, z, []))
231
+ (0, actions_1.updateDefaultProps)(unresolvedComposition.id, updater((_a = unresolvedComposition.defaultProps) !== null && _a !== void 0 ? _a : {}), (0, extract_enum_json_paths_1.extractEnumJsonPaths)(schema, z, []))
235
232
  .then((response) => {
236
233
  if (!response.success) {
237
234
  console.log(response.stack);
@@ -242,7 +239,13 @@ const DataEditor = ({ unresolvedComposition, inputProps, setInputProps, mayShowS
242
239
  (0, NotificationCenter_1.sendErrorNotification)(`Cannot update default props: ${err.message}`);
243
240
  setSaving(false);
244
241
  });
245
- }, [unresolvedComposition.defaultProps, unresolvedComposition.id, schema, z]);
242
+ }, [
243
+ schema,
244
+ z,
245
+ setSaving,
246
+ unresolvedComposition.id,
247
+ unresolvedComposition.defaultProps,
248
+ ]);
246
249
  const connectionStatus = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx).type;
247
250
  const warnings = (0, react_1.useMemo)(() => {
248
251
  return (0, get_render_modal_warnings_1.getRenderModalWarnings)({
@@ -291,6 +294,6 @@ const DataEditor = ({ unresolvedComposition, inputProps, setInputProps, mayShowS
291
294
  }
292
295
  return ((0, jsx_runtime_1.jsxs)("div", { style: outer, children: [(0, jsx_runtime_1.jsxs)("div", { style: controlContainer, children: [(0, jsx_runtime_1.jsxs)("div", { style: tabWrapper, children: [(0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: modeItems, needsWrapping: false }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), warnings.length > 0 ? ((0, jsx_runtime_1.jsx)(WarningIndicatorButton_1.WarningIndicatorButton, { setShowWarning: setShowWarning, showWarning: showWarning, warningCount: warnings.length })) : null] }), showWarning && warnings.length > 0
293
296
  ? warnings.map((warning) => ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1 }), (0, jsx_runtime_1.jsx)(ValidationMessage_1.ValidationMessage, { message: warning, align: "flex-start", type: "warning" })] }, warning)))
294
- : null] }), mode === 'schema' ? ((0, jsx_runtime_1.jsx)(SchemaEditor_1.SchemaEditor, { value: inputProps, setValue: setInputProps, schema: schema, zodValidationResult: zodValidationResult, defaultProps: unresolvedComposition.defaultProps, onSave: onSave, showSaveButton: showSaveButton, saving: saving, saveDisabledByParent: !zodValidationResult.success })) : ((0, jsx_runtime_1.jsx)(RenderModalJSONPropsEditor_1.RenderModalJSONPropsEditor, { value: inputProps !== null && inputProps !== void 0 ? inputProps : {}, setValue: setInputProps, onSave: onUpdate, valBeforeSafe: valBeforeSafe, showSaveButton: showSaveButton, serializedJSON: serializedJSON, defaultProps: unresolvedComposition.defaultProps, schema: schema }))] }));
297
+ : null] }), mode === 'schema' ? ((0, jsx_runtime_1.jsx)(SchemaEditor_1.SchemaEditor, { value: inputProps, setValue: setInputProps, schema: schema, zodValidationResult: zodValidationResult, defaultProps: unresolvedComposition.defaultProps, onSave: onSave, showSaveButton: showSaveButton, saving: saving, saveDisabledByParent: !zodValidationResult.success })) : ((0, jsx_runtime_1.jsx)(RenderModalJSONPropsEditor_1.RenderModalJSONPropsEditor, { value: inputProps !== null && inputProps !== void 0 ? inputProps : {}, setValue: setInputProps, onSave: onUpdate, showSaveButton: showSaveButton, serializedJSON: serializedJSON, defaultProps: unresolvedComposition.defaultProps, schema: schema }))] }));
295
298
  };
296
299
  exports.DataEditor = DataEditor;
@@ -3,13 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FrameRangeSetting = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
- const InputDragger_1 = require("../NewComposition/InputDragger");
7
- const RemInput_1 = require("../NewComposition/RemInput");
8
6
  const layout_1 = require("./layout");
7
+ const MultiRangeSlider_1 = require("./MultiRangeSlider");
8
+ const numberWrapper = {
9
+ minWidth: '39px',
10
+ display: 'flex',
11
+ justifyContent: 'flex-end',
12
+ alignItems: 'center',
13
+ fontSize: '14px',
14
+ };
9
15
  const FrameRangeSetting = ({ startFrame, endFrame, setEndFrame, durationInFrames, setStartFrame }) => {
10
- const maxStartFrame = endFrame - 1;
11
16
  const minStartFrame = 0;
12
- const minEndFrame = startFrame + 1;
13
17
  const maxEndFrame = durationInFrames - 1;
14
18
  const onStartFrameChangedDirectly = (0, react_1.useCallback)((newStartFrame) => {
15
19
  setStartFrame(newStartFrame);
@@ -17,26 +21,6 @@ const FrameRangeSetting = ({ startFrame, endFrame, setEndFrame, durationInFrames
17
21
  const onEndFrameChangedDirectly = (0, react_1.useCallback)((newEndFrame) => {
18
22
  setEndFrame(newEndFrame);
19
23
  }, [setEndFrame]);
20
- const onStartFrameChanged = (0, react_1.useCallback)((e) => {
21
- setStartFrame((q) => {
22
- const newStartFrame = parseInt(e, 10);
23
- if (Number.isNaN(newStartFrame)) {
24
- return q;
25
- }
26
- const newStartFrameClamped = Math.min(maxStartFrame, Math.max(newStartFrame, minStartFrame));
27
- return newStartFrameClamped;
28
- });
29
- }, [maxStartFrame, setStartFrame]);
30
- const onEndFrameChanged = (0, react_1.useCallback)((e) => {
31
- setEndFrame((q) => {
32
- const newEndFrame = parseInt(e, 10);
33
- if (Number.isNaN(newEndFrame)) {
34
- return q;
35
- }
36
- const newEndFrameClamped = Math.min(maxEndFrame, Math.max(newEndFrame, minEndFrame));
37
- return newEndFrameClamped;
38
- });
39
- }, [maxEndFrame, minEndFrame, setEndFrame]);
40
- return ((0, jsx_runtime_1.jsxs)("div", { style: layout_1.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_1.label, children: "Frame range" }), (0, jsx_runtime_1.jsxs)("div", { style: layout_1.rightRow, children: [(0, jsx_runtime_1.jsx)(RemInput_1.RightAlignInput, { children: (0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger, { value: startFrame, onTextChange: onStartFrameChanged, placeholder: `${minStartFrame}-${maxStartFrame}`, onValueChange: onStartFrameChangedDirectly, name: "startFrame", step: 1, min: minStartFrame, max: maxStartFrame, status: "ok", rightAlign: true }) }), (0, jsx_runtime_1.jsx)(RemInput_1.RightAlignInput, { children: (0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger, { value: endFrame, onTextChange: onEndFrameChanged, placeholder: `${minEndFrame}-${maxEndFrame}`, onValueChange: onEndFrameChangedDirectly, name: "endFrame", step: 1, min: minEndFrame, max: maxEndFrame, status: "ok", rightAlign: true }) })] })] }));
24
+ return ((0, jsx_runtime_1.jsxs)("div", { style: layout_1.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_1.label, children: "Frame range" }), (0, jsx_runtime_1.jsxs)("div", { style: layout_1.rightRow, children: [(0, jsx_runtime_1.jsx)("div", { style: numberWrapper, children: startFrame }), (0, jsx_runtime_1.jsx)(MultiRangeSlider_1.MultiRangeSlider, { min: minStartFrame, max: maxEndFrame, start: startFrame, end: endFrame, step: 1, onLeftThumbDrag: onStartFrameChangedDirectly, onRightThumbDrag: onEndFrameChangedDirectly }), (0, jsx_runtime_1.jsx)("div", { style: numberWrapper, children: endFrame })] })] }));
41
25
  };
42
26
  exports.FrameRangeSetting = FrameRangeSetting;
@@ -0,0 +1,12 @@
1
+ import type { FC } from 'react';
2
+ interface MultiRangeSliderProps {
3
+ min: number;
4
+ max: number;
5
+ start: number;
6
+ end: number;
7
+ step: number;
8
+ onLeftThumbDrag: (newVal: number) => void;
9
+ onRightThumbDrag: (newVal: number) => void;
10
+ }
11
+ export declare const MultiRangeSlider: FC<MultiRangeSliderProps>;
12
+ export {};
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MultiRangeSlider = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const colors_1 = require("../../helpers/colors");
7
+ const container = {
8
+ borderColor: 'black',
9
+ borderStyle: 'solid',
10
+ height: 39,
11
+ width: 220,
12
+ position: 'relative',
13
+ backgroundColor: colors_1.INPUT_BACKGROUND,
14
+ marginLeft: 8,
15
+ marginRight: 8,
16
+ borderRadius: 2,
17
+ };
18
+ const slider = {
19
+ position: 'relative',
20
+ height: 38,
21
+ width: 220,
22
+ };
23
+ const sliderRange = {
24
+ position: 'absolute',
25
+ top: 0,
26
+ backgroundColor: colors_1.BLUE,
27
+ height: 39,
28
+ };
29
+ const MultiRangeSlider = ({ min, max, start, end, step, onLeftThumbDrag, onRightThumbDrag, }) => {
30
+ const getPercent = (0, react_1.useCallback)((value) => Math.round(((value - min) / (max - min)) * 100), [min, max]);
31
+ const rangeStyle = (0, react_1.useMemo)(() => {
32
+ const minPercent = getPercent(start);
33
+ const maxPercent = getPercent(end);
34
+ return {
35
+ ...sliderRange,
36
+ left: `${minPercent}%`,
37
+ width: `${maxPercent - minPercent}%`,
38
+ };
39
+ }, [end, getPercent, start]);
40
+ const onChangeLeft = (0, react_1.useCallback)((event) => {
41
+ const value = Math.min(Number(event.target.value), end - 1);
42
+ onLeftThumbDrag(value);
43
+ }, [end, onLeftThumbDrag]);
44
+ const onChangeRight = (0, react_1.useCallback)((event) => {
45
+ const value = Math.max(Number(event.target.value), start + 1);
46
+ onRightThumbDrag(value);
47
+ }, [onRightThumbDrag, start]);
48
+ return ((0, jsx_runtime_1.jsx)("div", { style: container, children: (0, jsx_runtime_1.jsxs)("div", { style: slider, children: [(0, jsx_runtime_1.jsx)("input", { type: "range", min: min, max: max, value: start, step: step, onChange: onChangeLeft, className: "__remotion_thumb" }), (0, jsx_runtime_1.jsx)("input", { type: "range", min: min, max: max, value: end, step: step, onChange: onChangeRight, className: "__remotion_thumb" }), (0, jsx_runtime_1.jsx)("div", { style: rangeStyle })] }) }));
49
+ };
50
+ exports.MultiRangeSlider = MultiRangeSlider;
@@ -118,6 +118,7 @@ const RenderModal = ({ initialFrame, initialVideoImageFormat, initialStillImageF
118
118
  const isMounted = (0, react_1.useRef)(true);
119
119
  const [state, dispatch] = (0, react_1.useReducer)(reducer, initialState);
120
120
  const [unclampedFrame, setFrame] = (0, react_1.useState)(() => initialFrame);
121
+ const [saving, setSaving] = (0, react_1.useState)(false);
121
122
  const [stillImageFormat, setStillImageFormat] = (0, react_1.useState)(() => initialStillImageFormat);
122
123
  const [videoImageFormat, setVideoImageFormat] = (0, react_1.useState)(() => initialVideoImageFormat);
123
124
  const [concurrency, setConcurrency] = (0, react_1.useState)(() => initialConcurrency);
@@ -567,7 +568,7 @@ const RenderModal = ({ initialFrame, initialVideoImageFormat, initialStillImageF
567
568
  }
568
569
  }, [onClickStill, onClickVideo, renderDisabled, renderMode]);
569
570
  (0, react_1.useEffect)(() => {
570
- registerKeybinding({
571
+ const enter = registerKeybinding({
571
572
  callback() {
572
573
  trigger();
573
574
  },
@@ -575,13 +576,16 @@ const RenderModal = ({ initialFrame, initialVideoImageFormat, initialStillImageF
575
576
  key: 'Enter',
576
577
  event: 'keydown',
577
578
  preventDefault: true,
578
- triggerIfInputFieldFocused: false,
579
+ triggerIfInputFieldFocused: true,
579
580
  });
581
+ return () => {
582
+ enter.unregister();
583
+ };
580
584
  }, [registerKeybinding, trigger]);
581
585
  return ((0, jsx_runtime_1.jsxs)("div", { style: outer, children: [(0, jsx_runtime_1.jsx)(ModalHeader_1.NewCompHeader, { title: `Render ${resolvedComposition.id}` }), (0, jsx_runtime_1.jsxs)("div", { style: container, children: [(0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: renderTabOptions, needsWrapping: false }), (0, jsx_runtime_1.jsx)("div", { style: flexer }), (0, jsx_runtime_1.jsxs)(Button_1.Button, { autoFocus: true, onClick: trigger, disabled: renderDisabled, style: {
582
586
  ...buttonStyle,
583
587
  backgroundColor: outnameValidation.valid ? colors_1.BLUE : colors_1.BLUE_DISABLED,
584
- }, children: [state.type === 'idle' ? `Render ${renderMode}` : 'Rendering...', (0, jsx_runtime_1.jsx)(ShortcutHint_1.ShortcutHint, { keyToPress: "\u21B5", cmdOrCtrl: true })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: horizontalLayout, children: [(0, jsx_runtime_1.jsxs)("div", { style: leftSidebar, children: [shownTabs.includes('general') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'general', onClick: () => setTab('general'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(file_1.FileIcon, { style: icon }) }), "General"] })) : null, shownTabs.includes('data') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'data', onClick: () => setTab('data'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(data_1.DataIcon, { style: icon }) }), "Input Props"] })) : null, shownTabs.includes('picture') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'picture', onClick: () => setTab('picture'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(frame_1.PicIcon, { style: icon }) }), "Picture"] })) : null, shownTabs.includes('audio') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'audio', onClick: () => setTab('audio'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(audio_1.AudioIcon, { style: icon }) }), "Audio"] })) : null, shownTabs.includes('gif') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'gif', onClick: () => setTab('gif'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(gif_1.GifIcon, { style: icon }) }), "GIF"] })) : null, shownTabs.includes('advanced') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'advanced', onClick: () => setTab('advanced'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(gear_1.GearIcon, { style: icon }) }), "Other"] })) : null] }), (0, jsx_runtime_1.jsx)("div", { style: rightPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: tab === 'general' ? ((0, jsx_runtime_1.jsx)(RenderModalBasic_1.RenderModalBasic, { codec: codec, resolvedComposition: resolvedComposition, frame: frame, imageFormatOptions: imageFormatOptions, outName: outName, proResProfile: proResProfile, renderMode: renderMode, setVideoCodec: setCodec, setFrame: setFrame, setOutName: setOutName, setProResProfile: setProResProfile, endFrame: endFrame, setEndFrame: setEndFrame, setStartFrame: setStartFrame, startFrame: startFrame, validationMessage: outnameValidation.valid ? null : outnameValidation.error.message })) : tab === 'picture' ? ((0, jsx_runtime_1.jsx)(RenderModalPicture_1.RenderModalPicture, { renderMode: renderMode, scale: scale, setScale: setScale, pixelFormat: pixelFormat, setPixelFormat: setPixelFormat, imageFormatOptions: imageFormatOptions, crf: crf, setCrf: setCrf, customTargetVideoBitrate: customTargetVideoBitrate, maxCrf: maxCrf, minCrf: minCrf, jpegQuality: jpegQuality, qualityControlType: qualityControlType, setJpegQuality: setJpegQuality, setCustomTargetVideoBitrateValue: setCustomTargetVideoBitrateValue, setQualityControl: setQualityControl, videoImageFormat: videoImageFormat, stillImageFormat: stillImageFormat, shouldDisplayQualityControlPicker: supportsBothQualityControls })) : tab === 'audio' ? ((0, jsx_runtime_1.jsx)(RenderModalAudio_1.RenderModalAudio, { muted: muted, renderMode: renderMode, setMuted: setMuted, codec: codec, audioCodec: audioCodec, setAudioCodec: setAudioCodec, enforceAudioTrack: enforceAudioTrack, setEnforceAudioTrackState: setEnforceAudioTrackState, customTargetAudioBitrate: customTargetAudioBitrate, setCustomTargetAudioBitrateValue: setCustomTargetAudioBitrateValue, setShouldHaveCustomTargetAudioBitrate: setShouldHaveCustomTargetAudioBitrate, shouldHaveCustomTargetAudioBitrate: shouldHaveCustomTargetAudioBitrate })) : tab === 'gif' ? ((0, jsx_runtime_1.jsx)(RenderModalGif_1.RenderModalGif, { everyNthFrame: everyNthFrame, limitNumberOfGifLoops: limitNumberOfGifLoops, numberOfGifLoopsSetting: numberOfGifLoopsSetting, setEveryNthFrameSetting: setEveryNthFrameSetting, setLimitNumberOfGifLoops: setLimitNumberOfGifLoops, setNumberOfGifLoopsSetting: setNumberOfGifLoopsSetting })) : tab === 'data' ? ((0, jsx_runtime_1.jsx)(DataEditor_1.DataEditor, { inputProps: inputProps, setInputProps: setInputProps, unresolvedComposition: unresolvedComposition, mayShowSaveButton: false, propsEditType: "input-props" })) : ((0, jsx_runtime_1.jsx)(RenderModalAdvanced_1.RenderModalAdvanced, { concurrency: concurrency, maxConcurrency: maxConcurrency, minConcurrency: minConcurrency, renderMode: renderMode, setConcurrency: setConcurrency, setVerboseLogging: setVerboseLogging, verbose: verbose, delayRenderTimeout: delayRenderTimeout, setDelayRenderTimeout: setDelayRenderTimeout, disallowParallelEncoding: disallowParallelEncoding, setDisallowParallelEncoding: setDisallowParallelEncoding, setDisableWebSecurity: setDisableWebSecurity, setIgnoreCertificateErrors: setIgnoreCertificateErrors, setHeadless: setHeadless, headless: headless, ignoreCertificateErrors: ignoreCertificateErrors, disableWebSecurity: disableWebSecurity, openGlOption: openGlOption, setOpenGlOption: setOpenGlOption, setEnvVariables: setEnvVariables, envVariables: envVariables })) })] })] }));
588
+ }, children: [state.type === 'idle' ? `Render ${renderMode}` : 'Rendering...', (0, jsx_runtime_1.jsx)(ShortcutHint_1.ShortcutHint, { keyToPress: "\u21B5", cmdOrCtrl: true })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: horizontalLayout, children: [(0, jsx_runtime_1.jsxs)("div", { style: leftSidebar, children: [shownTabs.includes('general') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'general', onClick: () => setTab('general'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(file_1.FileIcon, { style: icon }) }), "General"] })) : null, shownTabs.includes('data') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'data', onClick: () => setTab('data'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(data_1.DataIcon, { style: icon }) }), "Input Props"] })) : null, shownTabs.includes('picture') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'picture', onClick: () => setTab('picture'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(frame_1.PicIcon, { style: icon }) }), "Picture"] })) : null, shownTabs.includes('audio') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'audio', onClick: () => setTab('audio'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(audio_1.AudioIcon, { style: icon }) }), "Audio"] })) : null, shownTabs.includes('gif') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'gif', onClick: () => setTab('gif'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(gif_1.GifIcon, { style: icon }) }), "GIF"] })) : null, shownTabs.includes('advanced') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'advanced', onClick: () => setTab('advanced'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(gear_1.GearIcon, { style: icon }) }), "Other"] })) : null] }), (0, jsx_runtime_1.jsx)("div", { style: rightPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: tab === 'general' ? ((0, jsx_runtime_1.jsx)(RenderModalBasic_1.RenderModalBasic, { codec: codec, resolvedComposition: resolvedComposition, frame: frame, imageFormatOptions: imageFormatOptions, outName: outName, proResProfile: proResProfile, renderMode: renderMode, setVideoCodec: setCodec, setFrame: setFrame, setOutName: setOutName, setProResProfile: setProResProfile, endFrame: endFrame, setEndFrame: setEndFrame, setStartFrame: setStartFrame, startFrame: startFrame, validationMessage: outnameValidation.valid ? null : outnameValidation.error.message })) : tab === 'picture' ? ((0, jsx_runtime_1.jsx)(RenderModalPicture_1.RenderModalPicture, { renderMode: renderMode, scale: scale, setScale: setScale, pixelFormat: pixelFormat, setPixelFormat: setPixelFormat, imageFormatOptions: imageFormatOptions, crf: crf, setCrf: setCrf, customTargetVideoBitrate: customTargetVideoBitrate, maxCrf: maxCrf, minCrf: minCrf, jpegQuality: jpegQuality, qualityControlType: qualityControlType, setJpegQuality: setJpegQuality, setCustomTargetVideoBitrateValue: setCustomTargetVideoBitrateValue, setQualityControl: setQualityControl, videoImageFormat: videoImageFormat, stillImageFormat: stillImageFormat, shouldDisplayQualityControlPicker: supportsBothQualityControls })) : tab === 'audio' ? ((0, jsx_runtime_1.jsx)(RenderModalAudio_1.RenderModalAudio, { muted: muted, renderMode: renderMode, setMuted: setMuted, codec: codec, audioCodec: audioCodec, setAudioCodec: setAudioCodec, enforceAudioTrack: enforceAudioTrack, setEnforceAudioTrackState: setEnforceAudioTrackState, customTargetAudioBitrate: customTargetAudioBitrate, setCustomTargetAudioBitrateValue: setCustomTargetAudioBitrateValue, setShouldHaveCustomTargetAudioBitrate: setShouldHaveCustomTargetAudioBitrate, shouldHaveCustomTargetAudioBitrate: shouldHaveCustomTargetAudioBitrate })) : tab === 'gif' ? ((0, jsx_runtime_1.jsx)(RenderModalGif_1.RenderModalGif, { everyNthFrame: everyNthFrame, limitNumberOfGifLoops: limitNumberOfGifLoops, numberOfGifLoopsSetting: numberOfGifLoopsSetting, setEveryNthFrameSetting: setEveryNthFrameSetting, setLimitNumberOfGifLoops: setLimitNumberOfGifLoops, setNumberOfGifLoopsSetting: setNumberOfGifLoopsSetting })) : tab === 'data' ? ((0, jsx_runtime_1.jsx)(DataEditor_1.DataEditor, { inputProps: inputProps, setInputProps: setInputProps, unresolvedComposition: unresolvedComposition, mayShowSaveButton: false, propsEditType: "input-props", saving: saving, setSaving: setSaving })) : ((0, jsx_runtime_1.jsx)(RenderModalAdvanced_1.RenderModalAdvanced, { concurrency: concurrency, maxConcurrency: maxConcurrency, minConcurrency: minConcurrency, renderMode: renderMode, setConcurrency: setConcurrency, setVerboseLogging: setVerboseLogging, verbose: verbose, delayRenderTimeout: delayRenderTimeout, setDelayRenderTimeout: setDelayRenderTimeout, disallowParallelEncoding: disallowParallelEncoding, setDisallowParallelEncoding: setDisallowParallelEncoding, setDisableWebSecurity: setDisableWebSecurity, setIgnoreCertificateErrors: setIgnoreCertificateErrors, setHeadless: setHeadless, headless: headless, ignoreCertificateErrors: ignoreCertificateErrors, disableWebSecurity: disableWebSecurity, openGlOption: openGlOption, setOpenGlOption: setOpenGlOption, setEnvVariables: setEnvVariables, envVariables: envVariables })) })] })] }));
585
589
  };
586
590
  const RenderModalWithLoader = (props) => {
587
591
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
@@ -1,7 +1,6 @@
1
1
  import type { Codec, ProResProfile } from '@remotion/renderer';
2
2
  import React from 'react';
3
- import type { TCompMetadata } from 'remotion';
4
- import type { AnyZodObject } from 'zod';
3
+ import type { VideoConfig } from 'remotion';
5
4
  import type { SegmentedControlItem } from '../SegmentedControl';
6
5
  import type { RenderType } from './RenderModalAdvanced';
7
6
  export declare const RenderModalBasic: React.FC<{
@@ -14,7 +13,7 @@ export declare const RenderModalBasic: React.FC<{
14
13
  setProResProfile: React.Dispatch<React.SetStateAction<ProResProfile>>;
15
14
  frame: number;
16
15
  setFrame: React.Dispatch<React.SetStateAction<number>>;
17
- resolvedComposition: TCompMetadata<AnyZodObject, Record<string, unknown> | undefined>;
16
+ resolvedComposition: VideoConfig;
18
17
  setOutName: (value: React.SetStateAction<string>) => void;
19
18
  setEndFrame: React.Dispatch<React.SetStateAction<number | null>>;
20
19
  startFrame: number;
@@ -1,12 +1,11 @@
1
1
  import React from 'react';
2
+ import type { SerializedJSONWithCustomFields } from 'remotion';
2
3
  import type { z } from 'zod';
3
- import type { SerializedJSONWithCustomFields } from './SchemaEditor/input-props-serialization';
4
4
  export type EditType = 'inputProps' | 'defaultProps';
5
5
  export declare const RenderModalJSONPropsEditor: React.FC<{
6
6
  value: unknown;
7
7
  setValue: React.Dispatch<React.SetStateAction<Record<string, unknown>>>;
8
8
  onSave: () => void;
9
- valBeforeSafe: unknown;
10
9
  showSaveButton: boolean;
11
10
  serializedJSON: SerializedJSONWithCustomFields | null;
12
11
  defaultProps: Record<string, unknown>;
@@ -26,13 +26,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.RenderModalJSONPropsEditor = void 0;
27
27
  const jsx_runtime_1 = require("react/jsx-runtime");
28
28
  const react_1 = __importStar(require("react"));
29
+ const remotion_1 = require("remotion");
29
30
  const Button_1 = require("../../../preview-server/error-overlay/remotion-overlay/Button");
30
31
  const colors_1 = require("../../helpers/colors");
31
32
  const use_keybinding_1 = require("../../helpers/use-keybinding");
32
33
  const layout_1 = require("../layout");
33
34
  const RemTextarea_1 = require("../NewComposition/RemTextarea");
34
35
  const ValidationMessage_1 = require("../NewComposition/ValidationMessage");
35
- const input_props_serialization_1 = require("./SchemaEditor/input-props-serialization");
36
+ const deep_equal_1 = require("./SchemaEditor/deep-equal");
36
37
  const ZodErrorMessages_1 = require("./SchemaEditor/ZodErrorMessages");
37
38
  const style = {
38
39
  fontFamily: 'monospace',
@@ -46,7 +47,7 @@ const scrollable = {
46
47
  };
47
48
  const parseJSON = (str, schema) => {
48
49
  try {
49
- const value = (0, input_props_serialization_1.deserializeJSONWithCustomFields)(str);
50
+ const value = remotion_1.Internals.deserializeJSONWithCustomFields(str);
50
51
  const zodValidation = schema.safeParse(value);
51
52
  return { str, value, validJSON: true, zodValidation };
52
53
  }
@@ -54,7 +55,7 @@ const parseJSON = (str, schema) => {
54
55
  return { str, validJSON: false, error: e.message };
55
56
  }
56
57
  };
57
- const RenderModalJSONPropsEditor = ({ setValue, value, defaultProps, onSave, valBeforeSafe, showSaveButton, serializedJSON, schema, }) => {
58
+ const RenderModalJSONPropsEditor = ({ setValue, value, defaultProps, onSave, showSaveButton, serializedJSON, schema, }) => {
58
59
  if (serializedJSON === null) {
59
60
  throw new Error('expecting serializedJSON to be defined');
60
61
  }
@@ -92,8 +93,8 @@ const RenderModalJSONPropsEditor = ({ setValue, value, defaultProps, onSave, val
92
93
  }
93
94
  }, [schema, setValue]);
94
95
  const hasChanged = (0, react_1.useMemo)(() => {
95
- return value && JSON.stringify(value) !== JSON.stringify(valBeforeSafe);
96
- }, [valBeforeSafe, value]);
96
+ return !(0, deep_equal_1.deepEqual)(value, defaultProps);
97
+ }, [defaultProps, value]);
97
98
  const onQuickSave = (0, react_1.useCallback)(() => {
98
99
  if (hasChanged) {
99
100
  onSave();
@@ -117,9 +118,9 @@ const RenderModalJSONPropsEditor = ({ setValue, value, defaultProps, onSave, val
117
118
  };
118
119
  }, [keybindings, onQuickSave, onSave]);
119
120
  const reset = (0, react_1.useCallback)(() => {
120
- setLocalValue(parseJSON(serializedJSON.serializedString, schema));
121
121
  setValue(defaultProps);
122
- }, [defaultProps, schema, serializedJSON.serializedString, setValue]);
122
+ setLocalValue(parseJSON(JSON.stringify(defaultProps, null, 2), schema));
123
+ }, [defaultProps, schema, setValue]);
123
124
  const textAreaStyle = (0, react_1.useMemo)(() => {
124
125
  const fail = !localValue.validJSON || !localValue.zodValidation.success;
125
126
  if (!fail) {
@@ -130,10 +131,8 @@ const RenderModalJSONPropsEditor = ({ setValue, value, defaultProps, onSave, val
130
131
  borderColor: colors_1.FAIL_COLOR,
131
132
  };
132
133
  }, [localValue]);
133
- return ((0, jsx_runtime_1.jsxs)("div", { style: scrollable, children: [(0, jsx_runtime_1.jsx)(RemTextarea_1.RemTextarea, { onChange: onChange, value: localValue.str, status: localValue.validJSON ? 'ok' : 'error', style: textAreaStyle }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1 }), localValue.validJSON === false ? ((0, jsx_runtime_1.jsx)(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: localValue.error, type: "error" })) : localValue.zodValidation.success === false ? ((0, jsx_runtime_1.jsx)(ZodErrorMessages_1.ZodErrorMessages, { zodValidationResult: localValue.zodValidation, viewTab: "json" })) : null, (0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1 }), (0, jsx_runtime_1.jsxs)(layout_1.Row, { children: [(0, jsx_runtime_1.jsx)(Button_1.Button, { disabled: !localValue.validJSON ||
134
- !(localValue.validJSON && !localValue.zodValidation.success), onClick: reset, children: "Reset" }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(Button_1.Button, { disabled: !localValue.validJSON, onClick: onPretty, children: "Format" }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1 }), (0, jsx_runtime_1.jsx)(Button_1.Button, { onClick: onSave, disabled: !(localValue.validJSON && localValue.zodValidation.success) ||
134
+ return ((0, jsx_runtime_1.jsxs)("div", { style: scrollable, children: [(0, jsx_runtime_1.jsx)(RemTextarea_1.RemTextarea, { onChange: onChange, value: localValue.str, status: localValue.validJSON ? 'ok' : 'error', style: textAreaStyle }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1 }), localValue.validJSON === false ? ((0, jsx_runtime_1.jsx)(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: localValue.error, type: "error" })) : localValue.zodValidation.success === false ? ((0, jsx_runtime_1.jsx)(ZodErrorMessages_1.ZodErrorMessages, { zodValidationResult: localValue.zodValidation, viewTab: "json" })) : null, (0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1 }), (0, jsx_runtime_1.jsxs)(layout_1.Row, { children: [(0, jsx_runtime_1.jsx)(Button_1.Button, { disabled: !(hasChanged || !localValue.validJSON), onClick: reset, children: "Reset" }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(Button_1.Button, { disabled: !localValue.validJSON, onClick: onPretty, children: "Format" }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1 }), showSaveButton ? ((0, jsx_runtime_1.jsx)(Button_1.Button, { onClick: onSave, disabled: !(localValue.validJSON && localValue.zodValidation.success) ||
135
135
  !localValue.validJSON ||
136
- !hasChanged ||
137
- !showSaveButton, children: "Save" })] })] }));
136
+ !hasChanged, children: "Save" })) : null] })] }));
138
137
  };
139
138
  exports.RenderModalJSONPropsEditor = RenderModalJSONPropsEditor;
@@ -2,11 +2,11 @@ import React from 'react';
2
2
  import type { AnyZodObject, z } from 'zod';
3
3
  export declare const SchemaEditor: React.FC<{
4
4
  schema: AnyZodObject;
5
- value: unknown;
5
+ value: Record<string, unknown>;
6
6
  setValue: React.Dispatch<React.SetStateAction<Record<string, unknown>>>;
7
7
  zodValidationResult: z.SafeParseReturnType<unknown, unknown>;
8
8
  defaultProps: Record<string, unknown>;
9
- onSave: (updater: (oldState: unknown) => unknown) => void;
9
+ onSave: (updater: (oldState: Record<string, unknown>) => Record<string, unknown>) => void;
10
10
  showSaveButton: boolean;
11
11
  saving: boolean;
12
12
  saveDisabledByParent: boolean;
@@ -3,8 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SchemaEditor = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
+ const use_keybinding_1 = require("../../../helpers/use-keybinding");
6
7
  const get_zod_if_possible_1 = require("../../get-zod-if-possible");
7
8
  const is_menu_item_1 = require("../../Menu/is-menu-item");
9
+ const deep_equal_1 = require("./deep-equal");
8
10
  const SchemaErrorMessages_1 = require("./SchemaErrorMessages");
9
11
  const ZodObjectEditor_1 = require("./ZodObjectEditor");
10
12
  const scrollable = {
@@ -13,10 +15,34 @@ const scrollable = {
13
15
  overflowY: 'auto',
14
16
  };
15
17
  const SchemaEditor = ({ schema, value, setValue, zodValidationResult, defaultProps, onSave, showSaveButton, saving, saveDisabledByParent, }) => {
18
+ const keybindings = (0, use_keybinding_1.useKeybinding)();
16
19
  const z = (0, get_zod_if_possible_1.useZodIfPossible)();
17
20
  if (!z) {
18
21
  throw new Error('expected zod');
19
22
  }
23
+ const hasChanged = (0, react_1.useMemo)(() => {
24
+ return !(0, deep_equal_1.deepEqual)(defaultProps, value);
25
+ }, [defaultProps, value]);
26
+ const onQuickSave = (0, react_1.useCallback)(() => {
27
+ if (hasChanged && showSaveButton) {
28
+ onSave(() => {
29
+ return value;
30
+ });
31
+ }
32
+ }, [hasChanged, onSave, showSaveButton, value]);
33
+ (0, react_1.useEffect)(() => {
34
+ const save = keybindings.registerKeybinding({
35
+ event: 'keydown',
36
+ key: 's',
37
+ commandCtrlKey: true,
38
+ callback: onQuickSave,
39
+ preventDefault: true,
40
+ triggerIfInputFieldFocused: true,
41
+ });
42
+ return () => {
43
+ save.unregister();
44
+ };
45
+ }, [keybindings, onQuickSave, onSave]);
20
46
  const def = schema._def;
21
47
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
48
  const typeName = def.typeName;
@@ -32,9 +32,7 @@ const errorContainer = {
32
32
  overflowY: 'auto',
33
33
  };
34
34
  const openDocs = () => {
35
- window.open(
36
- // TODO: Make sure to update this link when we release v4
37
- 'https://v4.remotion.dev/docs/parametrized-rendering#define-a-schema-');
35
+ window.open('https://www.remotion.dev/docs/parameterized-rendering#define-a-schema-');
38
36
  };
39
37
  const ZodNotInstalled = () => {
40
38
  return ((0, jsx_runtime_1.jsxs)("div", { style: explainer, children: [(0, jsx_runtime_1.jsxs)("div", { style: errorExplanation, children: ["Install ", (0, jsx_runtime_1.jsx)("code", { style: styles_1.inlineCodeSnippet, children: "zod" }), " as a dependency to interactively control the props of the composition."] }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 2, block: true }), (0, jsx_runtime_1.jsx)(Button_1.Button, { onClick: openDocs, children: "Learn how" })] }));
@@ -9,7 +9,6 @@ const InlineRemoveButton_1 = require("../InlineRemoveButton");
9
9
  const get_schema_label_1 = require("./get-schema-label");
10
10
  const SchemaResetButton_1 = require("./SchemaResetButton");
11
11
  const SchemaSaveButton_1 = require("./SchemaSaveButton");
12
- const colors_2 = require("../../../helpers/colors");
13
12
  const compactStyles = {
14
13
  fontSize: 15,
15
14
  color: colors_1.LIGHT_TEXT,
@@ -24,7 +23,7 @@ const SchemaLabel = ({ jsonPath, isDefaultValue, onReset, onSave, showSaveButton
24
23
  return {
25
24
  fontFamily: 'monospace',
26
25
  fontSize: 14,
27
- color: valid ? colors_1.LIGHT_TEXT : colors_2.FAIL_COLOR,
26
+ color: valid ? colors_1.LIGHT_TEXT : colors_1.FAIL_COLOR,
28
27
  lineHeight: '24px',
29
28
  };
30
29
  }, [valid]);
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SchemaSaveButton = 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 InlineAction_1 = require("../../InlineAction");
7
8
  const icon = {
8
9
  height: 14,
@@ -10,7 +11,7 @@ const icon = {
10
11
  };
11
12
  const SchemaSaveButton = ({ onClick, disabled }) => {
12
13
  const renderAction = (0, react_1.useCallback)((color) => {
13
- return ((0, jsx_runtime_1.jsx)("svg", { style: icon, viewBox: "0 0 448 512", children: (0, jsx_runtime_1.jsx)("path", { fill: disabled ? 'grey' : color, d: "M64 32C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V173.3c0-17-6.7-33.3-18.7-45.3L352 50.7C340 38.7 323.7 32 306.7 32H64zm0 96c0-17.7 14.3-32 32-32H288c17.7 0 32 14.3 32 32v64c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V128zM224 288a64 64 0 1 1 0 128 64 64 0 1 1 0-128z" }) }));
14
+ return ((0, jsx_runtime_1.jsx)("svg", { style: icon, viewBox: "0 0 448 512", children: (0, jsx_runtime_1.jsx)("path", { fill: disabled ? colors_1.LIGHT_TEXT : color, d: "M64 32C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V173.3c0-17-6.7-33.3-18.7-45.3L352 50.7C340 38.7 323.7 32 306.7 32H64zm0 96c0-17.7 14.3-32 32-32H288c17.7 0 32 14.3 32 32v64c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V128zM224 288a64 64 0 1 1 0 128 64 64 0 1 1 0-128z" }) }));
14
15
  }, [disabled]);
15
16
  return ((0, jsx_runtime_1.jsx)(InlineAction_1.InlineAction, { renderAction: renderAction, onClick: onClick, disabled: disabled }));
16
17
  };
@@ -26,19 +26,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.ZodArrayEditor = void 0;
27
27
  const jsx_runtime_1 = require("react/jsx-runtime");
28
28
  const react_1 = __importStar(require("react"));
29
+ const plus_1 = require("../../../icons/plus");
29
30
  const get_zod_if_possible_1 = require("../../get-zod-if-possible");
31
+ const InlineAction_1 = require("../../InlineAction");
32
+ const layout_1 = require("../layout");
30
33
  const create_zod_values_1 = require("./create-zod-values");
31
34
  const deep_equal_1 = require("./deep-equal");
32
- const local_state_1 = require("./local-state");
33
- const ZodArrayItemEditor_1 = require("./ZodArrayItemEditor");
34
35
  const Fieldset_1 = require("./Fieldset");
35
- const SchemaVerticalGuide_1 = require("./SchemaVerticalGuide");
36
- const layout_1 = require("../layout");
36
+ const local_state_1 = require("./local-state");
37
+ const SchemaLabel_1 = require("./SchemaLabel");
37
38
  const SchemaSeparationLine_1 = require("./SchemaSeparationLine");
38
- const InlineAction_1 = require("../../InlineAction");
39
- const plus_1 = require("../../../icons/plus");
39
+ const SchemaVerticalGuide_1 = require("./SchemaVerticalGuide");
40
+ const ZodArrayItemEditor_1 = require("./ZodArrayItemEditor");
40
41
  const ZodFieldValidation_1 = require("./ZodFieldValidation");
41
- const SchemaLabel_1 = require("./SchemaLabel");
42
42
  const ZodArrayEditor = ({ schema, jsonPath, setValue, defaultValue, value, onSave, showSaveButton, onRemove, saving, saveDisabledByParent, mayPad, }) => {
43
43
  const { localValue, onChange, RevisionContextProvider, reset } = (0, local_state_1.useLocalState)({
44
44
  value,