@remotion/studio 4.0.460 → 4.0.462

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist/Studio.d.ts +0 -1
  2. package/dist/Studio.js +4 -4
  3. package/dist/components/AudioWaveform.js +17 -9
  4. package/dist/components/ExpandedTracksProvider.js +8 -3
  5. package/dist/components/MenuBuildIndicator.js +1 -1
  6. package/dist/components/MenuCompositionName.js +1 -0
  7. package/dist/components/RenderButton.js +1 -1
  8. package/dist/components/Timeline/SequencePropsObserver.js +1 -1
  9. package/dist/components/Timeline/SubscribeToNodePaths.d.ts +4 -3
  10. package/dist/components/Timeline/SubscribeToNodePaths.js +11 -1
  11. package/dist/components/Timeline/Timeline.js +11 -10
  12. package/dist/components/Timeline/TimelineBooleanField.d.ts +4 -4
  13. package/dist/components/Timeline/TimelineBooleanField.js +5 -5
  14. package/dist/components/Timeline/TimelineColorField.d.ts +11 -0
  15. package/dist/components/Timeline/TimelineColorField.js +181 -0
  16. package/dist/components/Timeline/TimelineDragHandler.js +37 -3
  17. package/dist/components/Timeline/TimelineEffectFieldRow.d.ts +11 -0
  18. package/dist/components/Timeline/TimelineEffectFieldRow.js +177 -0
  19. package/dist/components/Timeline/TimelineEnumField.d.ts +5 -5
  20. package/dist/components/Timeline/TimelineEnumField.js +7 -7
  21. package/dist/components/Timeline/TimelineExpandArrowButton.js +1 -1
  22. package/dist/components/Timeline/TimelineExpandedRow.d.ts +3 -3
  23. package/dist/components/Timeline/TimelineExpandedRow.js +8 -1
  24. package/dist/components/Timeline/TimelineExpandedSection.d.ts +2 -2
  25. package/dist/components/Timeline/TimelineExpandedSection.js +8 -21
  26. package/dist/components/Timeline/TimelineFieldRow.d.ts +3 -3
  27. package/dist/components/Timeline/TimelineFieldRow.js +65 -26
  28. package/dist/components/Timeline/TimelineHeightContainer.d.ts +1 -1
  29. package/dist/components/Timeline/TimelineHeightContainer.js +36 -3
  30. package/dist/components/Timeline/TimelineListItem.js +20 -18
  31. package/dist/components/Timeline/TimelineNumberField.d.ts +5 -5
  32. package/dist/components/Timeline/TimelineNumberField.js +12 -10
  33. package/dist/components/Timeline/TimelineRotationField.d.ts +5 -5
  34. package/dist/components/Timeline/TimelineRotationField.js +10 -10
  35. package/dist/components/Timeline/TimelineSchemaField.d.ts +11 -7
  36. package/dist/components/Timeline/TimelineSchemaField.js +27 -21
  37. package/dist/components/Timeline/TimelineSequence.js +2 -2
  38. package/dist/components/Timeline/TimelineSlider.js +2 -2
  39. package/dist/components/Timeline/TimelineStack/get-stack.js +17 -31
  40. package/dist/components/Timeline/TimelineStack/index.js +0 -10
  41. package/dist/components/Timeline/TimelineTimeIndicators.js +2 -2
  42. package/dist/components/Timeline/TimelineTracks.d.ts +1 -1
  43. package/dist/components/Timeline/TimelineTracks.js +42 -12
  44. package/dist/components/Timeline/TimelineTranslateField.d.ts +5 -5
  45. package/dist/components/Timeline/TimelineTranslateField.js +21 -37
  46. package/dist/components/Timeline/sequence-props-subscription-store.d.ts +2 -1
  47. package/dist/components/Timeline/sequence-props-subscription-store.js +11 -5
  48. package/dist/components/Timeline/use-sequence-props-subscription.d.ts +2 -1
  49. package/dist/components/Timeline/use-sequence-props-subscription.js +6 -4
  50. package/dist/components/Timeline/use-timeline-height.js +5 -14
  51. package/dist/error-overlay/react-overlay/utils/get-source-map.d.ts +3 -3
  52. package/dist/error-overlay/react-overlay/utils/get-source-map.js +5 -5
  53. package/dist/error-overlay/react-overlay/utils/unmapper.d.ts +0 -6
  54. package/dist/error-overlay/react-overlay/utils/unmapper.js +8 -1
  55. package/dist/esm/{chunk-nrgs0ad5.js → chunk-yvg1f56k.js} +4168 -3948
  56. package/dist/esm/index.mjs +20 -8
  57. package/dist/esm/internals.mjs +4168 -3948
  58. package/dist/esm/previewEntry.mjs +2913 -2705
  59. package/dist/esm/renderEntry.mjs +2 -5
  60. package/dist/helpers/calculate-timeline.js +34 -4
  61. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +4 -2
  62. package/dist/helpers/timeline-layout.d.ts +11 -15
  63. package/dist/helpers/timeline-layout.js +36 -28
  64. package/dist/icons/eyedropper.d.ts +4 -0
  65. package/dist/icons/eyedropper.js +6 -0
  66. package/dist/internals.d.ts +0 -1
  67. package/dist/previewEntry.js +1 -1
  68. package/dist/renderEntry.js +3 -3
  69. package/package.json +14 -24
  70. package/dist/audio-waveform-worker.d.ts +0 -1
  71. package/dist/audio-waveform-worker.js +0 -102
  72. package/dist/components/audio-waveform-worker-types.d.ts +0 -28
  73. package/dist/components/audio-waveform-worker-types.js +0 -2
  74. package/dist/components/draw-peaks.d.ts +0 -1
  75. package/dist/components/draw-peaks.js +0 -68
  76. package/dist/components/load-waveform-peaks.d.ts +0 -13
  77. package/dist/components/load-waveform-peaks.js +0 -76
  78. package/dist/components/parse-color.d.ts +0 -1
  79. package/dist/components/parse-color.js +0 -17
  80. package/dist/components/slice-waveform-peaks.d.ts +0 -7
  81. package/dist/components/slice-waveform-peaks.js +0 -15
  82. package/dist/components/waveform-peak-processor.d.ts +0 -23
  83. package/dist/components/waveform-peak-processor.js +0 -77
  84. package/dist/esm/audio-waveform-worker.mjs +0 -346
  85. package/dist/make-audio-waveform-worker.d.ts +0 -1
  86. package/dist/make-audio-waveform-worker.js +0 -10
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelineEffectFieldRow = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const studio_shared_1 = require("@remotion/studio-shared");
6
+ const react_1 = require("react");
7
+ const remotion_1 = require("remotion");
8
+ const timeline_layout_1 = require("../../helpers/timeline-layout");
9
+ const call_api_1 = require("../call-api");
10
+ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
11
+ const Padder_1 = require("./Padder");
12
+ const TimelineSchemaField_1 = require("./TimelineSchemaField");
13
+ const fieldRowBase = {
14
+ display: 'flex',
15
+ alignItems: 'center',
16
+ gap: 8,
17
+ paddingRight: timeline_layout_1.EXPANDED_SECTION_PADDING_RIGHT,
18
+ };
19
+ const fieldName = {
20
+ fontSize: 12,
21
+ color: 'rgba(255, 255, 255, 0.8)',
22
+ userSelect: 'none',
23
+ };
24
+ const fieldLabelRow = {
25
+ flex: '0 0 50%',
26
+ display: 'flex',
27
+ flexDirection: 'row',
28
+ alignItems: 'center',
29
+ gap: 6,
30
+ };
31
+ const Value = ({ field, nodePath, validatedLocation }) => {
32
+ var _a;
33
+ var _b;
34
+ const { setEffectDragOverrides, clearEffectDragOverrides, setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
35
+ const { getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
36
+ const { codeValues: visualModeCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
37
+ const effectStatus = remotion_1.Internals.getEffectCodeValuesCtx({
38
+ codeValues: visualModeCodeValues,
39
+ nodePath,
40
+ effectIndex: field.effectIndex,
41
+ });
42
+ const propStatus = effectStatus.type === 'can-update-effect'
43
+ ? ((_b = (_a = effectStatus.props) === null || _a === void 0 ? void 0 : _a[field.key]) !== null && _b !== void 0 ? _b : null)
44
+ : null;
45
+ const onDragValueChange = (0, react_1.useCallback)((value) => {
46
+ setEffectDragOverrides(nodePath, field.effectIndex, field.key, value);
47
+ }, [setEffectDragOverrides, nodePath, field.effectIndex, field.key]);
48
+ const onDragEnd = (0, react_1.useCallback)(() => {
49
+ clearEffectDragOverrides(nodePath, field.effectIndex);
50
+ }, [clearEffectDragOverrides, nodePath, field.effectIndex]);
51
+ const dragOverrideValue = (0, react_1.useMemo)(() => {
52
+ const overrides = getEffectDragOverrides(nodePath, field.effectIndex);
53
+ return overrides[field.key];
54
+ }, [getEffectDragOverrides, nodePath, field.effectIndex, field.key]);
55
+ const onSave = (0, react_1.useCallback)((value) => {
56
+ if (!validatedLocation) {
57
+ return Promise.reject(new Error('Cannot save'));
58
+ }
59
+ if (!propStatus) {
60
+ return Promise.reject(new Error('Cannot save'));
61
+ }
62
+ if (!propStatus.canUpdate) {
63
+ return Promise.reject(new Error('Cannot save'));
64
+ }
65
+ const defaultValue = field.fieldSchema.default !== undefined
66
+ ? JSON.stringify(field.fieldSchema.default)
67
+ : null;
68
+ const stringifiedValue = JSON.stringify(value);
69
+ if (value === propStatus.codeValue) {
70
+ return Promise.resolve();
71
+ }
72
+ if (defaultValue === stringifiedValue &&
73
+ propStatus.codeValue === undefined) {
74
+ return Promise.resolve();
75
+ }
76
+ let previousUpdate;
77
+ setCodeValues(nodePath, (prev) => {
78
+ previousUpdate = prev;
79
+ return (0, studio_shared_1.optimisticUpdateForEffectCodeValues)({
80
+ previous: prev,
81
+ effectIndex: field.effectIndex,
82
+ fieldKey: field.key,
83
+ value,
84
+ schema: field.effectSchema,
85
+ });
86
+ });
87
+ return (0, call_api_1.callApi)('/api/save-effect-props', {
88
+ fileName: validatedLocation.source,
89
+ sequenceNodePath: nodePath,
90
+ effectIndex: field.effectIndex,
91
+ key: field.key,
92
+ value: stringifiedValue,
93
+ defaultValue,
94
+ schema: field.effectSchema,
95
+ })
96
+ .then((data) => {
97
+ setCodeValues(nodePath, (prev) => {
98
+ if (!prev.canUpdate) {
99
+ return prev;
100
+ }
101
+ const idx = prev.effects.findIndex((e) => e.effectIndex === field.effectIndex);
102
+ if (idx === -1) {
103
+ return {
104
+ ...prev,
105
+ effects: [...prev.effects, data],
106
+ };
107
+ }
108
+ const next = [...prev.effects];
109
+ next[idx] = data;
110
+ return { ...prev, effects: next };
111
+ });
112
+ })
113
+ .catch((err) => {
114
+ setCodeValues(nodePath, (current) => {
115
+ if (previousUpdate) {
116
+ return previousUpdate;
117
+ }
118
+ return current;
119
+ });
120
+ (0, NotificationCenter_1.showNotification)(`Could not save effect prop: ${err instanceof Error ? err.message : String(err)}`, 4000);
121
+ });
122
+ }, [
123
+ field.effectIndex,
124
+ field.effectSchema,
125
+ field.fieldSchema.default,
126
+ field.key,
127
+ nodePath,
128
+ propStatus,
129
+ setCodeValues,
130
+ validatedLocation,
131
+ ]);
132
+ if (effectStatus.type === 'cannot-update-effect') {
133
+ if (effectStatus.reason === 'computed') {
134
+ return jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: "computed" });
135
+ }
136
+ if (effectStatus.reason === 'not-call-expression') {
137
+ return jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: "not inline" });
138
+ }
139
+ if (effectStatus.reason === 'not-found') {
140
+ return jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: "not found in code" });
141
+ }
142
+ throw new Error(`Unsupported effect status: ${effectStatus.reason}`);
143
+ }
144
+ if (effectStatus.type === 'cannot-update-sequence') {
145
+ if (effectStatus.reason === 'not-found') {
146
+ return jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: "not found in code" });
147
+ }
148
+ if (effectStatus.reason === 'error') {
149
+ return jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: "error" });
150
+ }
151
+ throw new Error(`Unsupported effect status: ${effectStatus.reason}`);
152
+ }
153
+ if (propStatus === null || !propStatus.canUpdate) {
154
+ return null;
155
+ }
156
+ const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
157
+ codeValue: propStatus,
158
+ dragOverrideValue,
159
+ defaultValue: field.fieldSchema.default,
160
+ shouldResortToDefaultValueIfUndefined: true,
161
+ });
162
+ return (jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineFieldValue, { field: field, propStatus: propStatus, onSave: onSave, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd, effectiveValue: effectiveValue }));
163
+ };
164
+ const TimelineEffectFieldRow = ({ field, validatedLocation, paddingLeft, nestedDepth, nodePath }) => {
165
+ var _a;
166
+ const style = (0, react_1.useMemo)(() => {
167
+ return {
168
+ ...fieldRowBase,
169
+ height: field.rowHeight,
170
+ paddingLeft,
171
+ };
172
+ }, [field.rowHeight, paddingLeft]);
173
+ return (jsx_runtime_1.jsxs("div", { style: style, children: [
174
+ jsx_runtime_1.jsx(Padder_1.Padder, { depth: nestedDepth + 1 }), jsx_runtime_1.jsx("div", { style: fieldLabelRow, children: jsx_runtime_1.jsx("span", { style: fieldName, children: (_a = field.description) !== null && _a !== void 0 ? _a : field.key }) }), jsx_runtime_1.jsx(Value, { field: field, nodePath: nodePath, validatedLocation: validatedLocation })
175
+ ] }));
176
+ };
177
+ exports.TimelineEffectFieldRow = TimelineEffectFieldRow;
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
- import type { SchemaFieldInfo } from '../../helpers/timeline-layout';
2
+ import type { CanUpdateSequencePropStatus } from 'remotion';
3
+ import type { SchemaFieldInfo, TimelineFieldOnDragValueChange, TimelineFieldOnSave } from '../../helpers/timeline-layout';
3
4
  export declare const TimelineEnumField: React.FC<{
4
5
  readonly field: SchemaFieldInfo;
5
- readonly codeValue: unknown;
6
+ readonly propStatus: CanUpdateSequencePropStatus;
6
7
  readonly effectiveValue: unknown;
7
- readonly canUpdate: boolean;
8
- readonly onSave: (key: string, value: unknown) => Promise<void>;
9
- readonly onDragValueChange: (key: string, value: unknown) => void;
8
+ readonly onSave: TimelineFieldOnSave;
9
+ readonly onDragValueChange: TimelineFieldOnDragValueChange;
10
10
  readonly onDragEnd: () => void;
11
11
  }>;
@@ -7,7 +7,7 @@ const ComboBox_1 = require("../NewComposition/ComboBox");
7
7
  const comboboxStyle = {
8
8
  marginLeft: 8,
9
9
  };
10
- const TimelineEnumField = ({ field, codeValue, effectiveValue, canUpdate, onSave, onDragValueChange, onDragEnd, }) => {
10
+ const TimelineEnumField = ({ field, propStatus, effectiveValue, onSave, onDragValueChange, onDragEnd, }) => {
11
11
  const { fieldSchema } = field;
12
12
  if (fieldSchema.type !== 'enum') {
13
13
  throw new Error('TimelineEnumField rendered for non-enum field');
@@ -15,14 +15,14 @@ const TimelineEnumField = ({ field, codeValue, effectiveValue, canUpdate, onSave
15
15
  const variantKeys = Object.keys(fieldSchema.variants);
16
16
  const current = String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : fieldSchema.default);
17
17
  const onSelect = (0, react_1.useCallback)((newValue) => {
18
- if (!canUpdate || newValue === codeValue) {
18
+ if (!propStatus.canUpdate || newValue === propStatus.codeValue) {
19
19
  return;
20
20
  }
21
- onDragValueChange(field.key, newValue);
22
- onSave(field.key, newValue).finally(() => {
21
+ onDragValueChange(newValue);
22
+ onSave(newValue).finally(() => {
23
23
  onDragEnd();
24
24
  });
25
- }, [canUpdate, codeValue, field.key, onSave, onDragValueChange, onDragEnd]);
25
+ }, [propStatus, onSave, onDragValueChange, onDragEnd]);
26
26
  const items = (0, react_1.useMemo)(() => {
27
27
  return variantKeys.map((key) => ({
28
28
  type: 'item',
@@ -34,9 +34,9 @@ const TimelineEnumField = ({ field, codeValue, effectiveValue, canUpdate, onSave
34
34
  leftItem: null,
35
35
  subMenu: null,
36
36
  quickSwitcherLabel: null,
37
- disabled: !canUpdate,
37
+ disabled: !propStatus.canUpdate,
38
38
  }));
39
- }, [variantKeys, onSelect, canUpdate]);
39
+ }, [variantKeys, onSelect, propStatus]);
40
40
  return (jsx_runtime_1.jsx(ComboBox_1.Combobox, { small: true, title: field.key, selectedId: current, values: items, style: comboboxStyle }));
41
41
  };
42
42
  exports.TimelineEnumField = TimelineEnumField;
@@ -31,7 +31,7 @@ const TimelineExpandArrowButton = ({ isExpanded, onClick, label, disabled = fals
31
31
  opacity: disabled ? 0.5 : 1,
32
32
  };
33
33
  }, [isExpanded, disabled]);
34
- return (jsx_runtime_1.jsx("button", { type: "button", style: style, onClick: onClick, disabled: disabled, "aria-expanded": isExpanded, "aria-label": `${isExpanded ? 'Collapse' : 'Expand'} ${label}`, children: jsx_runtime_1.jsx("svg", { width: "12", height: "12", viewBox: "0 0 8 8", style: svgStyle, children: jsx_runtime_1.jsx("path", { d: "M2 1L6 4L2 7Z", fill: "white" }) }) }));
34
+ return (jsx_runtime_1.jsx("button", { type: "button", style: style, onClick: onClick, disabled: disabled, "aria-expanded": isExpanded, "aria-label": `${isExpanded ? 'Collapse' : 'Expand'} ${label}`, children: jsx_runtime_1.jsx("svg", { width: "12", height: "12", viewBox: "0 0 8 8", style: svgStyle, children: jsx_runtime_1.jsx("path", { d: "M2 1L6 4L2 7Z", fill: "#ccc" }) }) }));
35
35
  };
36
36
  exports.TimelineExpandArrowButton = TimelineExpandArrowButton;
37
37
  const TimelineExpandArrowSpacer = () => {
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { SequenceSchema, SequenceNodePath } from 'remotion';
2
+ import type { SequenceSchema, SequencePropsSubscriptionKey } from 'remotion';
3
3
  import type { CodePosition } from '../../error-overlay/react-overlay/utils/get-source-map';
4
4
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
5
5
  import type { TimelineTreeNode } from '../../helpers/timeline-layout';
@@ -10,7 +10,7 @@ export declare const TimelineExpandedRow: React.FC<{
10
10
  readonly nestedDepth: number;
11
11
  readonly getIsExpanded: GetIsExpanded;
12
12
  readonly toggleTrack: (nodePathInfo: SequenceNodePathInfo) => void;
13
- readonly validatedLocation: CodePosition | null;
14
- readonly nodePath: SequenceNodePath;
13
+ readonly validatedLocation: CodePosition;
14
+ readonly nodePath: SequencePropsSubscriptionKey;
15
15
  readonly schema: SequenceSchema;
16
16
  }>;
@@ -5,6 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const timeline_layout_1 = require("../../helpers/timeline-layout");
7
7
  const Padder_1 = require("./Padder");
8
+ const TimelineEffectFieldRow_1 = require("./TimelineEffectFieldRow");
8
9
  const TimelineExpandArrowButton_1 = require("./TimelineExpandArrowButton");
9
10
  const TimelineFieldRow_1 = require("./TimelineFieldRow");
10
11
  const TimelineListItem_1 = require("./TimelineListItem");
@@ -39,7 +40,13 @@ const TimelineExpandedRow = ({ node, depth, nestedDepth, getIsExpanded, toggleTr
39
40
  ] }));
40
41
  }
41
42
  if (node.field) {
42
- return (jsx_runtime_1.jsx(TimelineFieldRow_1.TimelineFieldRow, { field: node.field, validatedLocation: validatedLocation, paddingLeft: paddingLeft, nestedDepth: nestedDepth, nodePath: nodePath, schema: schema }));
43
+ if (node.field.kind === 'effect-field') {
44
+ return (jsx_runtime_1.jsx(TimelineEffectFieldRow_1.TimelineEffectFieldRow, { field: node.field, validatedLocation: validatedLocation, paddingLeft: paddingLeft, nestedDepth: nestedDepth, nodePath: nodePath }));
45
+ }
46
+ if (node.field.kind === 'sequence-field') {
47
+ return (jsx_runtime_1.jsx(TimelineFieldRow_1.TimelineFieldRow, { field: node.field, validatedLocation: validatedLocation, paddingLeft: paddingLeft, nestedDepth: nestedDepth, nodePath: nodePath, schema: schema }));
48
+ }
49
+ throw new Error('Unexpected field kind: ' + JSON.stringify(node.field));
43
50
  }
44
51
  return (jsx_runtime_1.jsxs("div", { style: labelOnlyStyle, children: [
45
52
  jsx_runtime_1.jsx(Padder_1.Padder, { depth: nestedDepth + 1 }), jsx_runtime_1.jsx("span", { style: rowLabel, children: node.label })
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
2
  import { type TSequence } from 'remotion';
3
- import type { OriginalPosition } from '../../error-overlay/react-overlay/utils/get-source-map';
3
+ import type { CodePosition } from '../../error-overlay/react-overlay/utils/get-source-map';
4
4
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
5
5
  export declare const TimelineExpandedSection: React.FC<{
6
6
  readonly sequence: TSequence;
7
- readonly originalLocation: OriginalPosition | null;
7
+ readonly validatedLocation: CodePosition;
8
8
  readonly nodePathInfo: SequenceNodePathInfo;
9
9
  readonly nestedDepth: number;
10
10
  }>;
@@ -53,37 +53,24 @@ const separator = {
53
53
  height: 1,
54
54
  backgroundColor: colors_1.TIMELINE_TRACK_SEPARATOR,
55
55
  };
56
- const TimelineExpandedSection = ({ sequence, originalLocation, nodePathInfo, nestedDepth }) => {
56
+ const TimelineExpandedSection = ({ sequence, validatedLocation, nodePathInfo, nestedDepth }) => {
57
57
  const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
58
58
  const { toggleTrack } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksSetterContext);
59
- const { getDragOverrides, getCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeGettersContext);
60
- const validatedLocation = (0, react_1.useMemo)(() => {
61
- var _a;
62
- if (!originalLocation ||
63
- !originalLocation.source ||
64
- !originalLocation.line) {
65
- return null;
66
- }
67
- return {
68
- source: originalLocation.source,
69
- line: originalLocation.line,
70
- column: (_a = originalLocation.column) !== null && _a !== void 0 ? _a : 0,
71
- };
72
- }, [originalLocation]);
59
+ const { codeValues: visualModeCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
60
+ const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
73
61
  const tree = (0, react_1.useMemo)(() => (0, timeline_layout_1.buildTimelineTree)({
74
62
  sequence,
75
63
  nodePathInfo,
76
64
  getDragOverrides,
77
- getCodeValues,
78
- }), [sequence, nodePathInfo, getDragOverrides, getCodeValues]);
65
+ codeValues: visualModeCodeValues,
66
+ }), [sequence, nodePathInfo, getDragOverrides, visualModeCodeValues]);
79
67
  const flat = (0, react_1.useMemo)(() => (0, timeline_layout_1.flattenVisibleTreeNodes)({ nodes: tree, getIsExpanded }), [tree, getIsExpanded]);
80
68
  const expandedHeight = (0, react_1.useMemo)(() => (0, timeline_layout_1.getExpandedTrackHeight)({
81
69
  sequence,
82
70
  nodePathInfo,
83
71
  getIsExpanded,
84
- getDragOverrides,
85
- getCodeValues,
86
- }), [sequence, nodePathInfo, getIsExpanded, getDragOverrides, getCodeValues]);
72
+ codeValues: visualModeCodeValues,
73
+ }), [sequence, nodePathInfo, getIsExpanded, visualModeCodeValues]);
87
74
  const style = (0, react_1.useMemo)(() => {
88
75
  return {
89
76
  ...expandedSectionBase,
@@ -95,7 +82,7 @@ const TimelineExpandedSection = ({ sequence, originalLocation, nodePathInfo, nes
95
82
  return jsx_runtime_1.jsx("div", { style: style, children: "No schema" });
96
83
  }
97
84
  return (jsx_runtime_1.jsx("div", { style: style, children: flat.map(({ node, depth }, i) => {
98
- return (jsx_runtime_1.jsxs(react_1.default.Fragment, { children: [i > 0 ? jsx_runtime_1.jsx("div", { style: separator }) : null, jsx_runtime_1.jsx(TimelineExpandedRow_1.TimelineExpandedRow, { node: node, depth: depth, nestedDepth: nestedDepth, getIsExpanded: getIsExpanded, toggleTrack: toggleTrack, validatedLocation: validatedLocation, nodePath: nodePathInfo.nodePath, schema: schema })
85
+ return (jsx_runtime_1.jsxs(react_1.default.Fragment, { children: [i > 0 ? jsx_runtime_1.jsx("div", { style: separator }) : null, jsx_runtime_1.jsx(TimelineExpandedRow_1.TimelineExpandedRow, { node: node, depth: depth, nestedDepth: nestedDepth, getIsExpanded: getIsExpanded, toggleTrack: toggleTrack, validatedLocation: validatedLocation, nodePath: nodePathInfo.sequenceSubscriptionKey, schema: schema })
99
86
  ] }, JSON.stringify(node.nodePathInfo)));
100
87
  }) }));
101
88
  };
@@ -1,13 +1,13 @@
1
1
  import React from 'react';
2
- import type { SequenceNodePath } from 'remotion';
2
+ import type { SequencePropsSubscriptionKey } from 'remotion';
3
3
  import type { SequenceSchema } from 'remotion';
4
4
  import type { CodePosition } from '../../error-overlay/react-overlay/utils/get-source-map';
5
5
  import type { SchemaFieldInfo } from '../../helpers/timeline-layout';
6
6
  export declare const TimelineFieldRow: React.FC<{
7
7
  readonly field: SchemaFieldInfo;
8
- readonly validatedLocation: CodePosition | null;
8
+ readonly validatedLocation: CodePosition;
9
9
  readonly paddingLeft: number;
10
10
  readonly nestedDepth: number;
11
- readonly nodePath: SequenceNodePath;
11
+ readonly nodePath: SequencePropsSubscriptionKey;
12
12
  readonly schema: SequenceSchema;
13
13
  }>;
@@ -2,10 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TimelineFieldRow = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const studio_shared_1 = require("@remotion/studio-shared");
5
6
  const react_1 = require("react");
6
7
  const remotion_1 = require("remotion");
7
8
  const timeline_layout_1 = require("../../helpers/timeline-layout");
8
9
  const call_api_1 = require("../call-api");
10
+ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
9
11
  const Padder_1 = require("./Padder");
10
12
  const TimelineSchemaField_1 = require("./TimelineSchemaField");
11
13
  const fieldRowBase = {
@@ -26,12 +28,9 @@ const fieldLabelRow = {
26
28
  alignItems: 'center',
27
29
  gap: 6,
28
30
  };
29
- const TimelineFieldRow = ({ field, validatedLocation, paddingLeft, nestedDepth, nodePath, schema, }) => {
30
- var _a, _b, _c;
31
- const { getDragOverrides, getCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeGettersContext);
31
+ const Value = ({ field, nodePath, validatedLocation, schema, codeValue }) => {
32
+ const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
32
33
  const { setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
33
- const codeValuesForOverride = getCodeValues(nodePath);
34
- const codeValue = (_a = codeValuesForOverride === null || codeValuesForOverride === void 0 ? void 0 : codeValuesForOverride[field.key]) !== null && _a !== void 0 ? _a : null;
35
34
  const dragOverrideValue = (0, react_1.useMemo)(() => {
36
35
  var _a;
37
36
  return nodePath === null
@@ -40,57 +39,95 @@ const TimelineFieldRow = ({ field, validatedLocation, paddingLeft, nestedDepth,
40
39
  }, [getDragOverrides, nodePath, field.key]);
41
40
  const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
42
41
  codeValue,
43
- runtimeValue: field.currentRuntimeValue,
44
42
  dragOverrideValue,
45
43
  defaultValue: field.fieldSchema.default,
46
44
  shouldResortToDefaultValueIfUndefined: true,
47
45
  });
48
46
  const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
49
- const onSave = (0, react_1.useCallback)((key, value) => {
50
- if (!codeValuesForOverride || !validatedLocation || !nodePath) {
51
- return Promise.reject(new Error('Cannot save'));
52
- }
53
- const status = codeValuesForOverride[key];
54
- if (!status || !status.canUpdate) {
47
+ const onSave = (0, react_1.useCallback)((value) => {
48
+ if (!codeValue || !codeValue.canUpdate) {
55
49
  return Promise.reject(new Error('Cannot save'));
56
50
  }
57
51
  const defaultValue = field.fieldSchema.default !== undefined
58
52
  ? JSON.stringify(field.fieldSchema.default)
59
53
  : null;
54
+ const stringifiedValue = JSON.stringify(value);
55
+ if (value === codeValue.codeValue) {
56
+ return Promise.resolve();
57
+ }
58
+ if (defaultValue === stringifiedValue &&
59
+ codeValue.codeValue === undefined) {
60
+ return Promise.resolve();
61
+ }
62
+ let previousUpdate;
63
+ // Optimistic update to prevent flicker
64
+ setCodeValues(nodePath, (prev) => {
65
+ previousUpdate = prev;
66
+ return (0, studio_shared_1.optimisticUpdateForCodeValues)({
67
+ previous: prev,
68
+ fieldKey: field.key,
69
+ value,
70
+ schema,
71
+ });
72
+ });
60
73
  return (0, call_api_1.callApi)('/api/save-sequence-props', {
61
74
  fileName: validatedLocation.source,
62
75
  nodePath,
63
- key,
64
- value: JSON.stringify(value),
76
+ key: field.key,
77
+ value: stringifiedValue,
65
78
  defaultValue,
66
79
  schema,
67
- }).then((data) => {
68
- if (data.success) {
69
- setCodeValues(nodePath, data.newStatus);
70
- return;
71
- }
72
- return Promise.reject(new Error(data.reason));
80
+ })
81
+ .then((data) => {
82
+ setCodeValues(nodePath, (prev) => {
83
+ if (!data.canUpdate) {
84
+ return data;
85
+ }
86
+ return {
87
+ canUpdate: true,
88
+ props: data.props,
89
+ effects: prev.canUpdate ? prev.effects : [],
90
+ };
91
+ });
92
+ })
93
+ .catch((err) => {
94
+ // In case something went wrong, undo optimistic update
95
+ setCodeValues(nodePath, (current) => {
96
+ if (previousUpdate) {
97
+ return previousUpdate;
98
+ }
99
+ return current;
100
+ });
101
+ (0, NotificationCenter_1.showNotification)(`Could not save sequence prop: ${err instanceof Error ? err.message : String(err)}`, 4000);
73
102
  });
74
103
  }, [
75
- codeValuesForOverride,
104
+ codeValue,
76
105
  field.fieldSchema.default,
106
+ field.key,
77
107
  nodePath,
78
108
  schema,
79
109
  setCodeValues,
80
110
  validatedLocation,
81
111
  ]);
82
- const onDragValueChange = (0, react_1.useCallback)((key, value) => {
112
+ const onDragValueChange = (0, react_1.useCallback)((value) => {
83
113
  if (nodePath === null) {
84
114
  throw new Error('Cannot drag value');
85
115
  }
86
- setDragOverrides(nodePath, key, value);
87
- }, [setDragOverrides, nodePath]);
116
+ setDragOverrides(nodePath, field.key, value);
117
+ }, [setDragOverrides, nodePath, field.key]);
88
118
  const onDragEnd = (0, react_1.useCallback)(() => {
89
119
  if (nodePath === null) {
90
120
  throw new Error('Cannot clear drag value');
91
121
  }
92
122
  clearDragOverrides(nodePath);
93
123
  }, [clearDragOverrides, nodePath]);
124
+ return (jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineFieldValue, { field: field, propStatus: codeValue, onSave: onSave, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd, effectiveValue: effectiveValue }));
125
+ };
126
+ const TimelineFieldRow = ({ field, validatedLocation, paddingLeft, nestedDepth, nodePath, schema, }) => {
127
+ var _a, _b;
128
+ const { codeValues: visualModeCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
129
+ const codeValuesForOverride = remotion_1.Internals.getCodeValuesCtx(visualModeCodeValues, nodePath);
130
+ const codeValue = (_a = codeValuesForOverride === null || codeValuesForOverride === void 0 ? void 0 : codeValuesForOverride[field.key]) !== null && _a !== void 0 ? _a : null;
94
131
  const style = (0, react_1.useMemo)(() => {
95
132
  return {
96
133
  ...fieldRowBase,
@@ -98,8 +135,10 @@ const TimelineFieldRow = ({ field, validatedLocation, paddingLeft, nestedDepth,
98
135
  paddingLeft,
99
136
  };
100
137
  }, [field.rowHeight, paddingLeft]);
138
+ if (codeValue === null) {
139
+ return null;
140
+ }
101
141
  return (jsx_runtime_1.jsxs("div", { style: style, children: [
102
- jsx_runtime_1.jsx(Padder_1.Padder, { depth: nestedDepth + 1 }), jsx_runtime_1.jsx("div", { style: fieldLabelRow, children: jsx_runtime_1.jsx("span", { style: fieldName, children: (_b = field.description) !== null && _b !== void 0 ? _b : field.key }) }), jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineFieldValue, { field: field, propStatus: codeValue, onSave: onSave, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd, canUpdate: (_c = codeValue === null || codeValue === void 0 ? void 0 : codeValue.canUpdate) !== null && _c !== void 0 ? _c : false, effectiveValue: effectiveValue, codeValue: codeValue })
103
- ] }));
142
+ jsx_runtime_1.jsx(Padder_1.Padder, { depth: nestedDepth + 1 }), jsx_runtime_1.jsx("div", { style: fieldLabelRow, children: jsx_runtime_1.jsx("span", { style: fieldName, children: (_b = field.description) !== null && _b !== void 0 ? _b : field.key }) }), codeValue.canUpdate ? (jsx_runtime_1.jsx(Value, { field: field, nodePath: nodePath, validatedLocation: validatedLocation, schema: schema, codeValue: codeValue })) : (jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineNonEditableStatus, { propStatus: codeValue }))] }));
104
143
  };
105
144
  exports.TimelineFieldRow = TimelineFieldRow;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { TrackWithHash } from '../../helpers/get-timeline-sequence-sort-key';
3
- export declare const TimelineHeightContainer: React.FC<{
3
+ export declare const TimelineHeightContainer: React.NamedExoticComponent<{
4
4
  readonly shown: TrackWithHash[];
5
5
  readonly hasBeenCut: boolean;
6
6
  readonly children: React.ReactNode;
@@ -1,8 +1,41 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.TimelineHeightContainer = void 0;
4
37
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const react_1 = require("react");
38
+ const react_1 = __importStar(require("react"));
6
39
  const use_timeline_height_1 = require("./use-timeline-height");
7
40
  const baseStyle = {
8
41
  display: 'flex',
@@ -10,9 +43,9 @@ const baseStyle = {
10
43
  minHeight: '100%',
11
44
  overflowX: 'hidden',
12
45
  };
13
- const TimelineHeightContainer = ({ shown, hasBeenCut, children }) => {
46
+ const TimelineHeightContainerInner = ({ shown, hasBeenCut, children }) => {
14
47
  const height = (0, use_timeline_height_1.useTimelineHeight)({ shown, hasBeenCut });
15
48
  const style = (0, react_1.useMemo)(() => ({ ...baseStyle, height }), [height]);
16
49
  return jsx_runtime_1.jsx("div", { style: style, children: children });
17
50
  };
18
- exports.TimelineHeightContainer = TimelineHeightContainer;
51
+ exports.TimelineHeightContainer = react_1.default.memo(TimelineHeightContainerInner);