@remotion/studio 4.0.438 → 4.0.439

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 (122) hide show
  1. package/dist/Studio.js +2 -2
  2. package/dist/api/helpers/calc-new-props.js +5 -8
  3. package/dist/api/update-default-props.d.ts +7 -3
  4. package/dist/api/update-default-props.js +7 -21
  5. package/dist/api/visual-control.js +6 -0
  6. package/dist/components/DefaultPropsEditor.d.ts +8 -0
  7. package/dist/components/DefaultPropsEditor.js +15 -0
  8. package/dist/components/Editor.js +0 -14
  9. package/dist/components/EditorContexts.js +6 -3
  10. package/dist/components/KeyboardShortcutsExplainer.js +6 -2
  11. package/dist/components/MenuBuildIndicator.js +1 -0
  12. package/dist/components/MenuToolbar.js +3 -1
  13. package/dist/components/NewComposition/InputDragger.js +2 -2
  14. package/dist/components/NewComposition/RemTextarea.js +4 -0
  15. package/dist/components/ObserveDefaultPropsContext.d.ts +11 -0
  16. package/dist/components/ObserveDefaultPropsContext.js +120 -0
  17. package/dist/components/OptionsPanel.js +90 -28
  18. package/dist/components/RenderModal/DataEditor.d.ts +4 -5
  19. package/dist/components/RenderModal/DataEditor.js +9 -111
  20. package/dist/components/RenderModal/RenderModalJSONPropsEditor.d.ts +1 -1
  21. package/dist/components/RenderModal/RenderModalJSONPropsEditor.js +52 -48
  22. package/dist/components/RenderModal/SchemaEditor/Fieldset.d.ts +0 -1
  23. package/dist/components/RenderModal/SchemaEditor/SchemaEditor.d.ts +4 -9
  24. package/dist/components/RenderModal/SchemaEditor/SchemaEditor.js +2 -61
  25. package/dist/components/RenderModal/SchemaEditor/SchemaErrorMessages.d.ts +0 -1
  26. package/dist/components/RenderModal/SchemaEditor/SchemaErrorMessages.js +2 -3
  27. package/dist/components/RenderModal/SchemaEditor/SchemaLabel.d.ts +0 -6
  28. package/dist/components/RenderModal/SchemaEditor/SchemaLabel.js +2 -5
  29. package/dist/components/RenderModal/SchemaEditor/SchemaSeparationLine.d.ts +3 -1
  30. package/dist/components/RenderModal/SchemaEditor/SchemaSeparationLine.js +1 -1
  31. package/dist/components/RenderModal/SchemaEditor/ZodArrayEditor.d.ts +1 -6
  32. package/dist/components/RenderModal/SchemaEditor/ZodArrayEditor.js +15 -26
  33. package/dist/components/RenderModal/SchemaEditor/ZodArrayItemEditor.d.ts +0 -5
  34. package/dist/components/RenderModal/SchemaEditor/ZodArrayItemEditor.js +7 -12
  35. package/dist/components/RenderModal/SchemaEditor/ZodBooleanEditor.d.ts +0 -7
  36. package/dist/components/RenderModal/SchemaEditor/ZodBooleanEditor.js +5 -15
  37. package/dist/components/RenderModal/SchemaEditor/ZodColorEditor.d.ts +1 -6
  38. package/dist/components/RenderModal/SchemaEditor/ZodColorEditor.js +30 -28
  39. package/dist/components/RenderModal/SchemaEditor/ZodDateEditor.d.ts +1 -6
  40. package/dist/components/RenderModal/SchemaEditor/ZodDateEditor.js +13 -17
  41. package/dist/components/RenderModal/SchemaEditor/ZodDefaultEditor.d.ts +0 -5
  42. package/dist/components/RenderModal/SchemaEditor/ZodDefaultEditor.js +2 -2
  43. package/dist/components/RenderModal/SchemaEditor/ZodDiscriminatedUnionEditor.d.ts +1 -6
  44. package/dist/components/RenderModal/SchemaEditor/ZodDiscriminatedUnionEditor.js +13 -28
  45. package/dist/components/RenderModal/SchemaEditor/ZodEffectEditor.d.ts +1 -5
  46. package/dist/components/RenderModal/SchemaEditor/ZodEffectEditor.js +11 -12
  47. package/dist/components/RenderModal/SchemaEditor/ZodEnumEditor.d.ts +1 -5
  48. package/dist/components/RenderModal/SchemaEditor/ZodEnumEditor.js +12 -16
  49. package/dist/components/RenderModal/SchemaEditor/ZodFieldValidation.d.ts +2 -2
  50. package/dist/components/RenderModal/SchemaEditor/ZodFieldValidation.js +1 -2
  51. package/dist/components/RenderModal/SchemaEditor/ZodMatrixEditor.d.ts +1 -6
  52. package/dist/components/RenderModal/SchemaEditor/ZodMatrixEditor.js +20 -30
  53. package/dist/components/RenderModal/SchemaEditor/ZodNonEditableValue.d.ts +0 -2
  54. package/dist/components/RenderModal/SchemaEditor/ZodNonEditableValue.js +3 -6
  55. package/dist/components/RenderModal/SchemaEditor/ZodNullableEditor.d.ts +0 -5
  56. package/dist/components/RenderModal/SchemaEditor/ZodNullableEditor.js +2 -2
  57. package/dist/components/RenderModal/SchemaEditor/ZodNumberEditor.d.ts +1 -6
  58. package/dist/components/RenderModal/SchemaEditor/ZodNumberEditor.js +16 -21
  59. package/dist/components/RenderModal/SchemaEditor/ZodObjectEditor.d.ts +2 -7
  60. package/dist/components/RenderModal/SchemaEditor/ZodObjectEditor.js +27 -49
  61. package/dist/components/RenderModal/SchemaEditor/ZodOptionalEditor.d.ts +0 -5
  62. package/dist/components/RenderModal/SchemaEditor/ZodOptionalEditor.js +2 -2
  63. package/dist/components/RenderModal/SchemaEditor/ZodOrNullishEditor.d.ts +1 -6
  64. package/dist/components/RenderModal/SchemaEditor/ZodOrNullishEditor.js +8 -15
  65. package/dist/components/RenderModal/SchemaEditor/ZodStaticFileEditor.d.ts +1 -6
  66. package/dist/components/RenderModal/SchemaEditor/ZodStaticFileEditor.js +10 -15
  67. package/dist/components/RenderModal/SchemaEditor/ZodStringEditor.d.ts +1 -6
  68. package/dist/components/RenderModal/SchemaEditor/ZodStringEditor.js +13 -17
  69. package/dist/components/RenderModal/SchemaEditor/ZodSwitch.d.ts +3 -6
  70. package/dist/components/RenderModal/SchemaEditor/ZodSwitch.js +27 -27
  71. package/dist/components/RenderModal/SchemaEditor/ZodTextareaEditor.d.ts +0 -5
  72. package/dist/components/RenderModal/SchemaEditor/ZodTextareaEditor.js +45 -17
  73. package/dist/components/RenderModal/SchemaEditor/ZodTupleEditor.d.ts +1 -6
  74. package/dist/components/RenderModal/SchemaEditor/ZodTupleEditor.js +15 -26
  75. package/dist/components/RenderModal/SchemaEditor/ZodTupleItemEditor.d.ts +0 -5
  76. package/dist/components/RenderModal/SchemaEditor/ZodTupleItemEditor.js +4 -11
  77. package/dist/components/RenderModal/SchemaEditor/ZodUnionEditor.d.ts +0 -5
  78. package/dist/components/RenderModal/SchemaEditor/ZodUnionEditor.js +6 -6
  79. package/dist/components/RenderModal/ServerRenderModal.js +9 -3
  80. package/dist/components/RenderModal/WebRenderModal.js +9 -3
  81. package/dist/components/RenderModal/get-render-modal-warnings.d.ts +1 -2
  82. package/dist/components/RenderModal/get-render-modal-warnings.js +4 -6
  83. package/dist/components/RenderQueue/actions.d.ts +1 -2
  84. package/dist/components/RenderQueue/actions.js +1 -13
  85. package/dist/components/Timeline/TimelineExpandedSection.js +7 -1
  86. package/dist/components/Timeline/TimelineFieldRow.d.ts +1 -0
  87. package/dist/components/Timeline/TimelineFieldRow.js +25 -3
  88. package/dist/components/Timeline/TimelineNumberField.js +4 -6
  89. package/dist/components/Timeline/TimelineRotationField.js +4 -6
  90. package/dist/components/Timeline/TimelineTranslateField.js +28 -13
  91. package/dist/components/TopPanel.js +10 -5
  92. package/dist/components/UndoRedoButtons.d.ts +2 -0
  93. package/dist/components/UndoRedoButtons.js +116 -0
  94. package/dist/components/VisualControls/VisualControlHandle.js +18 -18
  95. package/dist/components/VisualControls/VisualControlsUndoSync.d.ts +2 -0
  96. package/dist/components/VisualControls/VisualControlsUndoSync.js +23 -0
  97. package/dist/error-overlay/react-overlay/listen-to-runtime-errors.js +0 -1
  98. package/dist/esm/{chunk-ba0scebn.js → chunk-nnz9f1vq.js} +4233 -5091
  99. package/dist/esm/index.mjs +25 -28
  100. package/dist/esm/internals.mjs +4233 -5091
  101. package/dist/esm/previewEntry.mjs +4427 -5292
  102. package/dist/esm/renderEntry.mjs +6 -6
  103. package/dist/helpers/client-id.js +9 -0
  104. package/dist/helpers/document-title.d.ts +0 -1
  105. package/dist/helpers/document-title.js +1 -17
  106. package/dist/hot-middleware-client/process-update.js +6 -14
  107. package/dist/icons/redo.d.ts +3 -0
  108. package/dist/icons/redo.js +8 -0
  109. package/dist/icons/undo.d.ts +3 -0
  110. package/dist/icons/undo.js +8 -0
  111. package/dist/renderEntry.js +7 -6
  112. package/dist/visual-controls/VisualControls.js +9 -5
  113. package/dist/visual-controls/get-current-edited-value.js +5 -4
  114. package/dist/visual-controls/visual-control-store.d.ts +7 -0
  115. package/dist/visual-controls/visual-control-store.js +22 -0
  116. package/package.json +9 -9
  117. package/dist/components/GlobalPropsEditorUpdateButton.d.ts +0 -5
  118. package/dist/components/GlobalPropsEditorUpdateButton.js +0 -78
  119. package/dist/components/RenderModal/SchemaEditor/SchemaSaveButton.d.ts +0 -5
  120. package/dist/components/RenderModal/SchemaEditor/SchemaSaveButton.js +0 -18
  121. package/dist/components/RenderModal/SchemaEditor/local-state.d.ts +0 -25
  122. package/dist/components/RenderModal/SchemaEditor/local-state.js +0 -107
@@ -78,9 +78,15 @@ const TimelineExpandedSection = ({ sequence, originalLocation, nestedDepth, node
78
78
  height: expandedHeight,
79
79
  };
80
80
  }, [expandedHeight]);
81
+ const keysToObserve = (0, react_1.useMemo)(() => {
82
+ if (!schemaFields) {
83
+ return [];
84
+ }
85
+ return schemaFields.map((f) => f.key);
86
+ }, [schemaFields]);
81
87
  return (jsx_runtime_1.jsx("div", { style: style, children: schemaFields
82
88
  ? schemaFields.map((field, i) => {
83
- return (jsx_runtime_1.jsxs(react_1.default.Fragment, { children: [i > 0 ? jsx_runtime_1.jsx("div", { style: separator }) : null, jsx_runtime_1.jsx(TimelineFieldRow_1.TimelineFieldRow, { field: field, overrideId: overrideId, validatedLocation: validatedLocation, nestedDepth: nestedDepth, nodePath: nodePath })
89
+ return (jsx_runtime_1.jsxs(react_1.default.Fragment, { children: [i > 0 ? jsx_runtime_1.jsx("div", { style: separator }) : null, jsx_runtime_1.jsx(TimelineFieldRow_1.TimelineFieldRow, { field: field, overrideId: overrideId, validatedLocation: validatedLocation, nestedDepth: nestedDepth, nodePath: nodePath, keysToObserve: keysToObserve })
84
90
  ] }, field.key));
85
91
  })
86
92
  : 'No schema' }));
@@ -8,4 +8,5 @@ export declare const TimelineFieldRow: React.FC<{
8
8
  readonly validatedLocation: CodePosition | null;
9
9
  readonly nestedDepth: number;
10
10
  readonly nodePath: SequenceNodePath | null;
11
+ readonly keysToObserve: string[];
11
12
  }>;
@@ -18,6 +18,7 @@ const fieldRowBase = {
18
18
  const fieldName = {
19
19
  fontSize: 12,
20
20
  color: 'rgba(255, 255, 255, 0.8)',
21
+ userSelect: 'none',
21
22
  };
22
23
  const fieldLabelRow = {
23
24
  flex: '0 0 50%',
@@ -26,7 +27,7 @@ const fieldLabelRow = {
26
27
  alignItems: 'center',
27
28
  gap: 6,
28
29
  };
29
- const TimelineFieldRow = ({ field, overrideId, validatedLocation, nestedDepth, nodePath }) => {
30
+ const TimelineFieldRow = ({ field, overrideId, validatedLocation, nestedDepth, nodePath, keysToObserve, }) => {
30
31
  var _a, _b, _c, _d;
31
32
  const { setDragOverrides, clearDragOverrides, dragOverrides, codeValues: allPropStatuses, } = (0, react_1.useContext)(remotion_1.Internals.VisualModeOverridesContext);
32
33
  const propStatuses = ((_a = allPropStatuses[overrideId]) !== null && _a !== void 0 ? _a : null);
@@ -42,6 +43,7 @@ const TimelineFieldRow = ({ field, overrideId, validatedLocation, nestedDepth, n
42
43
  defaultValue: field.fieldSchema.default,
43
44
  shouldResortToDefaultValueIfUndefined: true,
44
45
  });
46
+ const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeOverridesContext);
45
47
  const onSave = (0, react_1.useCallback)((key, value) => {
46
48
  if (!propStatuses || !validatedLocation || !nodePath) {
47
49
  return Promise.reject(new Error('Cannot save'));
@@ -59,8 +61,28 @@ const TimelineFieldRow = ({ field, overrideId, validatedLocation, nestedDepth, n
59
61
  key,
60
62
  value: JSON.stringify(value),
61
63
  defaultValue,
62
- }).then(() => undefined);
63
- }, [propStatuses, validatedLocation, nodePath, field.fieldSchema.default]);
64
+ observedKeys: keysToObserve,
65
+ }).then((data) => {
66
+ if (data.success) {
67
+ if (data.newStatus.canUpdate) {
68
+ setCodeValues(overrideId, data.newStatus.props);
69
+ }
70
+ else {
71
+ setCodeValues(overrideId, null);
72
+ }
73
+ return;
74
+ }
75
+ return Promise.reject(new Error(data.reason));
76
+ });
77
+ }, [
78
+ field.fieldSchema.default,
79
+ keysToObserve,
80
+ nodePath,
81
+ overrideId,
82
+ propStatuses,
83
+ setCodeValues,
84
+ validatedLocation,
85
+ ]);
64
86
  const onDragValueChange = (0, react_1.useCallback)((key, value) => {
65
87
  setDragOverrides(overrideId, key, value);
66
88
  }, [setDragOverrides, overrideId]);
@@ -12,20 +12,18 @@ const TimelineNumberField = ({ field, effectiveValue, canUpdate, onSave, onDragV
12
12
  setDragValue(newVal);
13
13
  onDragValueChange(field.key, newVal);
14
14
  }, [onDragValueChange, field.key]);
15
- (0, react_1.useEffect)(() => {
16
- setDragValue(null);
17
- onDragEnd();
18
- }, [field.currentValue, onDragEnd]);
19
15
  const onValueChangeEnd = (0, react_1.useCallback)((newVal) => {
20
16
  if (canUpdate && newVal !== codeValue) {
21
- onSave(field.key, newVal).catch(() => {
17
+ onSave(field.key, newVal).finally(() => {
22
18
  setDragValue(null);
19
+ onDragEnd();
23
20
  });
24
21
  }
25
22
  else {
26
23
  setDragValue(null);
24
+ onDragEnd();
27
25
  }
28
- }, [canUpdate, onSave, field.key, codeValue]);
26
+ }, [canUpdate, onSave, field.key, codeValue, onDragEnd]);
29
27
  const onTextChange = (0, react_1.useCallback)((newVal) => {
30
28
  if (canUpdate) {
31
29
  const parsed = Number(newVal);
@@ -22,21 +22,19 @@ const TimelineRotationField = ({ field, effectiveValue, codeValue, canUpdate, on
22
22
  setDragValue(newVal);
23
23
  onDragValueChange(field.key, `${newVal}deg`);
24
24
  }, [onDragValueChange, field.key]);
25
- (0, react_1.useEffect)(() => {
26
- setDragValue(null);
27
- onDragEnd();
28
- }, [field.currentValue, onDragEnd]);
29
25
  const onValueChangeEnd = (0, react_1.useCallback)((newVal) => {
30
26
  const newStr = `${newVal}deg`;
31
27
  if (canUpdate && newStr !== codeValue) {
32
- onSave(field.key, newStr).catch(() => {
28
+ onSave(field.key, newStr).finally(() => {
33
29
  setDragValue(null);
30
+ onDragEnd();
34
31
  });
35
32
  }
36
33
  else {
37
34
  setDragValue(null);
35
+ onDragEnd();
38
36
  }
39
- }, [canUpdate, onSave, field.key, codeValue]);
37
+ }, [canUpdate, onSave, field.key, codeValue, onDragEnd]);
40
38
  const onTextChange = (0, react_1.useCallback)((newVal) => {
41
39
  if (canUpdate) {
42
40
  const parsed = Number(newVal);
@@ -29,11 +29,6 @@ const TimelineTranslateField = ({ field, codeValue, effectiveValue, canUpdate, o
29
29
  const [dragY, setDragY] = (0, react_1.useState)(null);
30
30
  const [codeX, codeY] = (0, react_1.useMemo)(() => parseTranslate(String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : '0px 0px')), [effectiveValue]);
31
31
  const makeString = (0, react_1.useCallback)((x, y) => `${x}px ${y}px`, []);
32
- (0, react_1.useEffect)(() => {
33
- setDragX(null);
34
- setDragY(null);
35
- onDragEnd();
36
- }, [field.currentValue, onDragEnd]);
37
32
  const step = field.fieldSchema.type === 'translate' ? ((_a = field.fieldSchema.step) !== null && _a !== void 0 ? _a : 1) : 1;
38
33
  const stepDecimals = (0, react_1.useMemo)(() => (0, timeline_field_utils_1.getDecimalPlaces)(step), [step]);
39
34
  const formatter = (0, react_1.useCallback)((v) => {
@@ -52,14 +47,25 @@ const TimelineTranslateField = ({ field, codeValue, effectiveValue, canUpdate, o
52
47
  const currentY = dragY !== null && dragY !== void 0 ? dragY : codeY;
53
48
  const newStr = makeString(newVal, currentY);
54
49
  if (canUpdate && newStr !== codeValue) {
55
- onSave(field.key, newStr).catch(() => {
50
+ onSave(field.key, newStr).finally(() => {
56
51
  setDragX(null);
52
+ onDragEnd();
57
53
  });
58
54
  }
59
55
  else {
60
56
  setDragX(null);
57
+ onDragEnd();
61
58
  }
62
- }, [canUpdate, onSave, field.key, codeValue, dragY, codeY, makeString]);
59
+ }, [
60
+ dragY,
61
+ codeY,
62
+ makeString,
63
+ canUpdate,
64
+ codeValue,
65
+ onSave,
66
+ field.key,
67
+ onDragEnd,
68
+ ]);
63
69
  const onXTextChange = (0, react_1.useCallback)((newVal) => {
64
70
  if (canUpdate) {
65
71
  const parsed = Number(newVal);
@@ -68,13 +74,11 @@ const TimelineTranslateField = ({ field, codeValue, effectiveValue, canUpdate, o
68
74
  const newStr = makeString(parsed, currentY);
69
75
  if (newStr !== codeValue) {
70
76
  setDragX(parsed);
71
- onSave(field.key, newStr).catch(() => {
72
- setDragX(null);
73
- });
77
+ onSave(field.key, newStr);
74
78
  }
75
79
  }
76
80
  }
77
- }, [canUpdate, onSave, field.key, codeValue, dragY, codeY, makeString]);
81
+ }, [canUpdate, dragY, codeY, makeString, codeValue, onSave, field.key]);
78
82
  // --- Y callbacks ---
79
83
  const onYChange = (0, react_1.useCallback)((newVal) => {
80
84
  setDragY(newVal);
@@ -85,14 +89,25 @@ const TimelineTranslateField = ({ field, codeValue, effectiveValue, canUpdate, o
85
89
  const currentX = dragX !== null && dragX !== void 0 ? dragX : codeX;
86
90
  const newStr = makeString(currentX, newVal);
87
91
  if (canUpdate && newStr !== codeValue) {
88
- onSave(field.key, newStr).catch(() => {
92
+ onSave(field.key, newStr).finally(() => {
89
93
  setDragY(null);
94
+ onDragEnd();
90
95
  });
91
96
  }
92
97
  else {
93
98
  setDragY(null);
99
+ onDragEnd();
94
100
  }
95
- }, [canUpdate, onSave, field.key, codeValue, dragX, codeX, makeString]);
101
+ }, [
102
+ dragX,
103
+ codeX,
104
+ makeString,
105
+ canUpdate,
106
+ codeValue,
107
+ onSave,
108
+ field.key,
109
+ onDragEnd,
110
+ ]);
96
111
  const onYTextChange = (0, react_1.useCallback)((newVal) => {
97
112
  if (canUpdate) {
98
113
  const parsed = Number(newVal);
@@ -39,6 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.TopPanel = exports.useResponsiveSidebarStatus = void 0;
40
40
  const jsx_runtime_1 = require("react/jsx-runtime");
41
41
  const react_1 = __importStar(require("react"));
42
+ const remotion_1 = require("remotion");
42
43
  const mobile_layout_1 = require("../helpers/mobile-layout");
43
44
  const use_breakpoint_1 = require("../helpers/use-breakpoint");
44
45
  const editor_rulers_1 = require("../state/editor-rulers");
@@ -48,6 +49,7 @@ const CurrentCompositionSideEffects_1 = require("./CurrentCompositionSideEffects
48
49
  const use_is_ruler_visible_1 = require("./EditorRuler/use-is-ruler-visible");
49
50
  const ExplorerPanel_1 = require("./ExplorerPanel");
50
51
  const MobilePanel_1 = __importDefault(require("./MobilePanel"));
52
+ const ObserveDefaultPropsContext_1 = require("./ObserveDefaultPropsContext");
51
53
  const OptionsPanel_1 = require("./OptionsPanel");
52
54
  const PreviewToolbar_1 = require("./PreviewToolbar");
53
55
  const SplitterContainer_1 = require("./Splitter/SplitterContainer");
@@ -84,6 +86,7 @@ exports.useResponsiveSidebarStatus = useResponsiveSidebarStatus;
84
86
  const TopPanelInner = ({ readOnlyStudio, onMounted, drawRef, bufferStateDelayInMilliseconds }) => {
85
87
  const { setSidebarCollapsedState, sidebarCollapsedStateRight } = (0, react_1.useContext)(sidebar_1.SidebarContext);
86
88
  const rulersAreVisible = (0, use_is_ruler_visible_1.useIsRulerVisible)();
89
+ const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
87
90
  const actualStateLeft = (0, exports.useResponsiveSidebarStatus)();
88
91
  const actualStateRight = (0, react_1.useMemo)(() => {
89
92
  if (sidebarCollapsedStateRight === 'collapsed') {
@@ -107,10 +110,12 @@ const TopPanelInner = ({ readOnlyStudio, onMounted, drawRef, bufferStateDelayInM
107
110
  setSidebarCollapsedState({ left: null, right: 'collapsed' });
108
111
  }, [setSidebarCollapsedState]);
109
112
  const isMobileLayout = (0, mobile_layout_1.useMobileLayout)();
110
- return (jsx_runtime_1.jsxs("div", { style: container, children: [
111
- jsx_runtime_1.jsx("div", { style: row, children: jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { minFlex: 0.15, maxFlex: 0.4, defaultFlex: 0.2, id: "sidebar-to-preview", orientation: "vertical", children: [actualStateLeft === 'expanded' ? (isMobileLayout ? (jsx_runtime_1.jsx(MobilePanel_1.default, { onClose: onCollapseLeft, children: jsx_runtime_1.jsx(ExplorerPanel_1.ExplorerPanel, { readOnlyStudio: readOnlyStudio }) })) : (jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "flexer", children: jsx_runtime_1.jsx(ExplorerPanel_1.ExplorerPanel, { readOnlyStudio: readOnlyStudio }) }))) : null, actualStateLeft === 'expanded' ? (jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { allowToCollapse: "left", onCollapse: onCollapseLeft })) : null, jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "anti-flexer", children: jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { minFlex: 0.5, maxFlex: 0.8, defaultFlex: 0.7, id: "canvas-to-right-sidebar", orientation: "vertical", children: [
112
- jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "flexer", children: jsx_runtime_1.jsx("div", { ref: drawRef, style: canvasContainerStyle, children: jsx_runtime_1.jsx(CanvasIfSizeIsAvailable_1.CanvasIfSizeIsAvailable, {}) }) }), actualStateRight === 'expanded' ? (jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { allowToCollapse: "right", onCollapse: onCollapseRight })) : null, actualStateRight === 'expanded' ? (isMobileLayout ? (jsx_runtime_1.jsx(MobilePanel_1.default, { onClose: onCollapseRight, children: jsx_runtime_1.jsx(OptionsPanel_1.OptionsPanel, { readOnlyStudio: readOnlyStudio }) })) : (jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "anti-flexer", children: jsx_runtime_1.jsx(OptionsPanel_1.OptionsPanel, { readOnlyStudio: readOnlyStudio }) }))) : null] }) })
113
- ] }) }), jsx_runtime_1.jsx(PreviewToolbar_1.PreviewToolbar, { bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds, readOnlyStudio: readOnlyStudio }), jsx_runtime_1.jsx(CurrentCompositionSideEffects_1.CurrentCompositionKeybindings, { readOnlyStudio: readOnlyStudio }), jsx_runtime_1.jsx(CurrentCompositionSideEffects_1.TitleUpdater, {})
114
- ] }));
113
+ return (jsx_runtime_1.jsx(ObserveDefaultPropsContext_1.ObserveDefaultProps, { compositionId: (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition'
114
+ ? canvasContent.compositionId
115
+ : null, readOnlyStudio: readOnlyStudio, children: jsx_runtime_1.jsxs("div", { style: container, children: [
116
+ jsx_runtime_1.jsx("div", { style: row, children: jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { minFlex: 0.15, maxFlex: 0.4, defaultFlex: 0.2, id: "sidebar-to-preview", orientation: "vertical", children: [actualStateLeft === 'expanded' ? (isMobileLayout ? (jsx_runtime_1.jsx(MobilePanel_1.default, { onClose: onCollapseLeft, children: jsx_runtime_1.jsx(ExplorerPanel_1.ExplorerPanel, { readOnlyStudio: readOnlyStudio }) })) : (jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "flexer", children: jsx_runtime_1.jsx(ExplorerPanel_1.ExplorerPanel, { readOnlyStudio: readOnlyStudio }) }))) : null, actualStateLeft === 'expanded' ? (jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { allowToCollapse: "left", onCollapse: onCollapseLeft })) : null, jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "anti-flexer", children: jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { minFlex: 0.5, maxFlex: 0.8, defaultFlex: 0.7, id: "canvas-to-right-sidebar", orientation: "vertical", children: [
117
+ jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "flexer", children: jsx_runtime_1.jsx("div", { ref: drawRef, style: canvasContainerStyle, children: jsx_runtime_1.jsx(CanvasIfSizeIsAvailable_1.CanvasIfSizeIsAvailable, {}) }) }), actualStateRight === 'expanded' ? (jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { allowToCollapse: "right", onCollapse: onCollapseRight })) : null, actualStateRight === 'expanded' ? (isMobileLayout ? (jsx_runtime_1.jsx(MobilePanel_1.default, { onClose: onCollapseRight, children: jsx_runtime_1.jsx(OptionsPanel_1.OptionsPanel, { readOnlyStudio: readOnlyStudio }) })) : (jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "anti-flexer", children: jsx_runtime_1.jsx(OptionsPanel_1.OptionsPanel, { readOnlyStudio: readOnlyStudio }) }))) : null] }) })
118
+ ] }) }), jsx_runtime_1.jsx(PreviewToolbar_1.PreviewToolbar, { bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds, readOnlyStudio: readOnlyStudio }), jsx_runtime_1.jsx(CurrentCompositionSideEffects_1.CurrentCompositionKeybindings, { readOnlyStudio: readOnlyStudio }), jsx_runtime_1.jsx(CurrentCompositionSideEffects_1.TitleUpdater, {})
119
+ ] }) }));
115
120
  };
116
121
  exports.TopPanel = react_1.default.memo(TopPanelInner);
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const UndoRedoButtons: React.FC;
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UndoRedoButtons = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const ShortcutHint_1 = require("../error-overlay/remotion-overlay/ShortcutHint");
7
+ const client_id_1 = require("../helpers/client-id");
8
+ const use_keybinding_1 = require("../helpers/use-keybinding");
9
+ const redo_1 = require("../icons/redo");
10
+ const undo_1 = require("../icons/undo");
11
+ const call_api_1 = require("./call-api");
12
+ const InlineAction_1 = require("./InlineAction");
13
+ const iconStyle = {
14
+ width: 16,
15
+ height: 16,
16
+ };
17
+ const UndoRedoButtons = () => {
18
+ const [undoFile, setUndoFile] = (0, react_1.useState)(null);
19
+ const [redoFile, setRedoFile] = (0, react_1.useState)(null);
20
+ const { subscribeToEvent } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
21
+ const keybindings = (0, use_keybinding_1.useKeybinding)();
22
+ const undoInFlight = (0, react_1.useRef)(false);
23
+ const redoInFlight = (0, react_1.useRef)(false);
24
+ (0, react_1.useEffect)(() => {
25
+ const unsub = subscribeToEvent('undo-redo-stack-changed', (event) => {
26
+ if (event.type !== 'undo-redo-stack-changed') {
27
+ return;
28
+ }
29
+ setUndoFile(event.undoFile);
30
+ setRedoFile(event.redoFile);
31
+ });
32
+ return () => unsub();
33
+ }, [subscribeToEvent]);
34
+ const onUndo = (0, react_1.useCallback)(() => {
35
+ if (undoInFlight.current) {
36
+ return;
37
+ }
38
+ undoInFlight.current = true;
39
+ (0, call_api_1.callApi)('/api/undo', {})
40
+ .catch(() => {
41
+ // Ignore errors
42
+ })
43
+ .finally(() => {
44
+ undoInFlight.current = false;
45
+ });
46
+ }, []);
47
+ const onRedo = (0, react_1.useCallback)(() => {
48
+ if (redoInFlight.current) {
49
+ return;
50
+ }
51
+ redoInFlight.current = true;
52
+ (0, call_api_1.callApi)('/api/redo', {})
53
+ .catch(() => {
54
+ // Ignore errors
55
+ })
56
+ .finally(() => {
57
+ redoInFlight.current = false;
58
+ });
59
+ }, []);
60
+ (0, react_1.useEffect)(() => {
61
+ const undo = keybindings.registerKeybinding({
62
+ event: 'keydown',
63
+ key: 'z',
64
+ commandCtrlKey: true,
65
+ callback: (e) => {
66
+ if (e.shiftKey) {
67
+ return;
68
+ }
69
+ if (undoFile) {
70
+ onUndo();
71
+ }
72
+ },
73
+ preventDefault: true,
74
+ triggerIfInputFieldFocused: false,
75
+ keepRegisteredWhenNotHighestContext: false,
76
+ });
77
+ const redo = keybindings.registerKeybinding({
78
+ event: 'keydown',
79
+ key: 'y',
80
+ commandCtrlKey: true,
81
+ callback: () => {
82
+ if (redoFile) {
83
+ onRedo();
84
+ }
85
+ },
86
+ preventDefault: true,
87
+ triggerIfInputFieldFocused: false,
88
+ keepRegisteredWhenNotHighestContext: false,
89
+ });
90
+ return () => {
91
+ undo.unregister();
92
+ redo.unregister();
93
+ };
94
+ }, [keybindings, onRedo, onUndo, redoFile, undoFile]);
95
+ const undoTooltip = (0, use_keybinding_1.areKeyboardShortcutsDisabled)()
96
+ ? 'Undo'
97
+ : `Undo (${ShortcutHint_1.cmdOrCtrlCharacter}+Z)`;
98
+ const redoTooltip = (0, use_keybinding_1.areKeyboardShortcutsDisabled)()
99
+ ? 'Redo'
100
+ : `Redo (${ShortcutHint_1.cmdOrCtrlCharacter}+Y)`;
101
+ const renderUndo = (0, react_1.useCallback)((color) => {
102
+ return (jsx_runtime_1.jsx(undo_1.UndoIcon, { style: { ...iconStyle, color, opacity: undoFile ? 1 : 0.5 } }));
103
+ }, [undoFile]);
104
+ const renderRedo = (0, react_1.useCallback)((color) => {
105
+ return (jsx_runtime_1.jsx(redo_1.RedoIcon, { style: { ...iconStyle, color, opacity: redoFile ? 1 : 0.5 } }));
106
+ }, [redoFile]);
107
+ const canUndo = undoFile !== null;
108
+ const canRedo = redoFile !== null;
109
+ if (!canUndo && !canRedo) {
110
+ return null;
111
+ }
112
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
113
+ jsx_runtime_1.jsx(InlineAction_1.InlineAction, { onClick: onUndo, renderAction: renderUndo, title: undoTooltip, disabled: !canUndo }), jsx_runtime_1.jsx(InlineAction_1.InlineAction, { onClick: onRedo, renderAction: renderRedo, title: redoTooltip, disabled: !canRedo })
114
+ ] }));
115
+ };
116
+ exports.UndoRedoButtons = UndoRedoButtons;
@@ -11,7 +11,6 @@ const get_zod_if_possible_1 = require("../get-zod-if-possible");
11
11
  const layout_1 = require("../layout");
12
12
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
13
13
  const extract_enum_json_paths_1 = require("../RenderModal/SchemaEditor/extract-enum-json-paths");
14
- const local_state_1 = require("../RenderModal/SchemaEditor/local-state");
15
14
  const ZodSwitch_1 = require("../RenderModal/SchemaEditor/ZodSwitch");
16
15
  const actions_1 = require("../RenderQueue/actions");
17
16
  const get_original_stack_trace_1 = require("./get-original-stack-trace");
@@ -25,23 +24,14 @@ const VisualControlHandle = ({ value, keyName }) => {
25
24
  const state = (0, react_1.useContext)(VisualControls_1.VisualControlsContext);
26
25
  const { updateValue } = (0, react_1.useContext)(VisualControls_1.SetVisualControlsContext);
27
26
  const { fastRefreshes, increaseManualRefreshes } = (0, react_1.useContext)(fast_refresh_context_1.FastRefreshContext);
28
- const [saving, setSaving] = (0, react_1.useState)(false);
27
+ const [_saving, setSaving] = (0, react_1.useState)(false);
29
28
  const currentValue = (0, get_current_edited_value_1.getVisualControlEditedValue)({
30
29
  handles: state.handles,
31
30
  key: keyName,
32
31
  });
33
32
  const originalFileName = (0, get_original_stack_trace_1.useOriginalFileName)(value.stack);
34
- const { localValue, RevisionContextProvider, onChange } = (0, local_state_1.useLocalState)({
35
- schema: value.schema,
36
- setValue: (updater) => {
37
- updateValue(keyName, updater(currentValue));
38
- increaseManualRefreshes();
39
- },
40
- unsavedValue: currentValue,
41
- savedValue: value.valueInCode,
42
- });
43
33
  const disableSave = window.remotion_isReadOnlyStudio || originalFileName.type !== 'loaded';
44
- const onSave = (0, react_1.useCallback)((updater) => {
34
+ const saveToFile = (0, react_1.useCallback)((updater) => {
45
35
  if (disableSave) {
46
36
  return;
47
37
  }
@@ -64,11 +54,14 @@ const VisualControlHandle = ({ value, keyName }) => {
64
54
  changes: [
65
55
  {
66
56
  id: keyName,
67
- newValueSerialized: no_react_1.NoReactInternals.serializeJSONWithSpecialTypes({
68
- data: val,
69
- indent: 2,
70
- staticBase: window.remotion_staticBase,
71
- }).serializedString,
57
+ newValueSerialized: val === undefined
58
+ ? ''
59
+ : no_react_1.NoReactInternals.serializeJSONWithSpecialTypes({
60
+ data: val,
61
+ indent: 2,
62
+ staticBase: window.remotion_staticBase,
63
+ }).serializedString,
64
+ newValueIsUndefined: val === undefined,
72
65
  enumPaths,
73
66
  },
74
67
  ],
@@ -90,8 +83,15 @@ const VisualControlHandle = ({ value, keyName }) => {
90
83
  (0, react_1.useEffect)(() => {
91
84
  setSaving(false);
92
85
  }, [fastRefreshes]);
86
+ const setValue = (0, react_1.useCallback)((updater, { shouldSave }) => {
87
+ updateValue(keyName, updater(currentValue));
88
+ increaseManualRefreshes();
89
+ if (shouldSave) {
90
+ saveToFile(updater);
91
+ }
92
+ }, [currentValue, increaseManualRefreshes, keyName, saveToFile, updateValue]);
93
93
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
94
- jsx_runtime_1.jsx(VisualControlHandleHeader_1.VisualControlHandleHeader, { originalFileName: originalFileName }), jsx_runtime_1.jsx(layout_1.Spacing, { block: true, y: 0.5 }), jsx_runtime_1.jsx(RevisionContextProvider, { children: jsx_runtime_1.jsx(ZodSwitch_1.ZodSwitch, { mayPad: true, schema: value.schema, showSaveButton: !disableSave, saving: saving, saveDisabledByParent: false, onSave: onSave, jsonPath: [keyName], value: localValue.value, defaultValue: value.valueInCode, setValue: onChange, onRemove: null }) })
94
+ jsx_runtime_1.jsx(VisualControlHandleHeader_1.VisualControlHandleHeader, { originalFileName: originalFileName }), jsx_runtime_1.jsx(layout_1.Spacing, { block: true, y: 0.5 }), jsx_runtime_1.jsx(ZodSwitch_1.ZodSwitch, { mayPad: true, schema: value.schema, jsonPath: [keyName], value: currentValue, setValue: setValue, onRemove: null })
95
95
  ] }));
96
96
  };
97
97
  exports.VisualControlHandle = VisualControlHandle;
@@ -0,0 +1,2 @@
1
+ import type React from 'react';
2
+ export declare const VisualControlsUndoSync: React.FC;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VisualControlsUndoSync = void 0;
4
+ const react_1 = require("react");
5
+ const client_id_1 = require("../../helpers/client-id");
6
+ const VisualControls_1 = require("../../visual-controls/VisualControls");
7
+ const VisualControlsUndoSync = () => {
8
+ const { subscribeToEvent } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
9
+ const { updateValue } = (0, react_1.useContext)(VisualControls_1.SetVisualControlsContext);
10
+ (0, react_1.useEffect)(() => {
11
+ const unsub = subscribeToEvent('visual-control-values-changed', (event) => {
12
+ if (event.type !== 'visual-control-values-changed') {
13
+ return;
14
+ }
15
+ for (const entry of event.values) {
16
+ updateValue(entry.id, entry.isUndefined ? undefined : entry.value);
17
+ }
18
+ });
19
+ return () => unsub();
20
+ }, [subscribeToEvent, updateValue]);
21
+ return null;
22
+ };
23
+ exports.VisualControlsUndoSync = VisualControlsUndoSync;
@@ -38,7 +38,6 @@ const crashWithFrames = (crash) => (error) => {
38
38
  if (didHookOrderChange && !justRefreshedBecauseOfHooks) {
39
39
  // eslint-disable-next-line no-console
40
40
  console.log('Hook order changed. Reloading app...');
41
- window.remotion_unsavedProps = false;
42
41
  (0, url_state_1.reloadUrl)();
43
42
  }
44
43
  else {