@remotion/studio 4.0.461 → 4.0.463

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 (56) hide show
  1. package/dist/components/AssetSelector.js +2 -6
  2. package/dist/components/CompSelectorRef.js +2 -6
  3. package/dist/components/ExpandedTracksProvider.js +13 -23
  4. package/dist/components/Timeline/SubscribeToNodePaths.d.ts +4 -3
  5. package/dist/components/Timeline/SubscribeToNodePaths.js +6 -1
  6. package/dist/components/Timeline/Timeline.js +1 -1
  7. package/dist/components/Timeline/TimelineColorField.d.ts +11 -0
  8. package/dist/components/Timeline/TimelineColorField.js +181 -0
  9. package/dist/components/Timeline/TimelineEffectFieldRow.d.ts +11 -0
  10. package/dist/components/Timeline/TimelineEffectFieldRow.js +167 -0
  11. package/dist/components/Timeline/TimelineEffectGroupRow.d.ts +17 -0
  12. package/dist/components/Timeline/TimelineEffectGroupRow.js +73 -0
  13. package/dist/components/Timeline/TimelineExpandedRow.d.ts +3 -3
  14. package/dist/components/Timeline/TimelineExpandedRow.js +12 -1
  15. package/dist/components/Timeline/TimelineExpandedSection.d.ts +2 -2
  16. package/dist/components/Timeline/TimelineExpandedSection.js +7 -20
  17. package/dist/components/Timeline/TimelineFieldRow.d.ts +3 -3
  18. package/dist/components/Timeline/TimelineFieldRow.js +17 -45
  19. package/dist/components/Timeline/TimelineLayerEye.d.ts +5 -3
  20. package/dist/components/Timeline/TimelineLayerEye.js +18 -1
  21. package/dist/components/Timeline/TimelineListItem.js +61 -17
  22. package/dist/components/Timeline/TimelineNumberField.js +1 -1
  23. package/dist/components/Timeline/TimelineRotationField.js +1 -1
  24. package/dist/components/Timeline/TimelineSchemaField.d.ts +8 -2
  25. package/dist/components/Timeline/TimelineSchemaField.js +20 -11
  26. package/dist/components/Timeline/TimelineTracks.js +4 -4
  27. package/dist/components/Timeline/TimelineTranslateField.js +4 -2
  28. package/dist/components/Timeline/save-effect-prop.d.ts +12 -0
  29. package/dist/components/Timeline/save-effect-prop.js +42 -0
  30. package/dist/components/Timeline/save-prop-queue.d.ts +12 -0
  31. package/dist/components/Timeline/save-prop-queue.js +63 -0
  32. package/dist/components/Timeline/save-sequence-prop.d.ts +11 -0
  33. package/dist/components/Timeline/save-sequence-prop.js +38 -0
  34. package/dist/components/Timeline/sequence-props-subscription-store.d.ts +2 -1
  35. package/dist/components/Timeline/sequence-props-subscription-store.js +10 -4
  36. package/dist/components/Timeline/use-sequence-props-subscription.d.ts +2 -1
  37. package/dist/components/Timeline/use-sequence-props-subscription.js +3 -1
  38. package/dist/components/Timeline/use-timeline-height.js +3 -3
  39. package/dist/esm/chunk-5gtx3pza.js +9 -0
  40. package/dist/esm/{chunk-yzh34sp0.js → chunk-b0m62frw.js} +4511 -3740
  41. package/dist/esm/index.mjs +20 -24
  42. package/dist/esm/internals.mjs +4509 -3753
  43. package/dist/esm/previewEntry.mjs +3190 -2445
  44. package/dist/esm/renderEntry.mjs +3 -4
  45. package/dist/helpers/calculate-timeline.js +13 -5
  46. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +3 -2
  47. package/dist/helpers/persist-boolean-map.d.ts +5 -0
  48. package/dist/helpers/persist-boolean-map.js +56 -0
  49. package/dist/helpers/persist-open-folders.d.ts +4 -3
  50. package/dist/helpers/persist-open-folders.js +4 -7
  51. package/dist/helpers/timeline-layout.d.ts +13 -13
  52. package/dist/helpers/timeline-layout.js +23 -35
  53. package/dist/icons/eyedropper.d.ts +4 -0
  54. package/dist/icons/eyedropper.js +6 -0
  55. package/package.json +11 -12
  56. package/dist/esm/chunk-6jf1natv.js +0 -25
@@ -5,6 +5,8 @@ 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");
9
+ const TimelineEffectGroupRow_1 = require("./TimelineEffectGroupRow");
8
10
  const TimelineExpandArrowButton_1 = require("./TimelineExpandArrowButton");
9
11
  const TimelineFieldRow_1 = require("./TimelineFieldRow");
10
12
  const TimelineListItem_1 = require("./TimelineListItem");
@@ -33,13 +35,22 @@ const TimelineExpandedRow = ({ node, depth, nestedDepth, getIsExpanded, toggleTr
33
35
  paddingLeft,
34
36
  }), [node, paddingLeft]);
35
37
  if (node.kind === 'group') {
38
+ if (node.effectInfo) {
39
+ return (jsx_runtime_1.jsx(TimelineEffectGroupRow_1.TimelineEffectGroupRow, { label: node.label, nodePathInfo: node.nodePathInfo, effectIndex: node.effectInfo.effectIndex, effectSchema: node.effectInfo.effectSchema, nodePath: nodePath, validatedLocation: validatedLocation, nestedDepth: nestedDepth, style: groupStyle, getIsExpanded: getIsExpanded, toggleTrack: toggleTrack }));
40
+ }
36
41
  const isExpanded = getIsExpanded(node.nodePathInfo);
37
42
  return (jsx_runtime_1.jsxs("div", { style: groupStyle, children: [
38
43
  jsx_runtime_1.jsx(Padder_1.Padder, { depth: nestedDepth + 1 }), jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: () => toggleTrack(node.nodePathInfo), label: `${node.label} section`, disabled: false }), jsx_runtime_1.jsx("span", { style: rowLabel, children: node.label })
39
44
  ] }));
40
45
  }
41
46
  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 }));
47
+ if (node.field.kind === 'effect-field') {
48
+ return (jsx_runtime_1.jsx(TimelineEffectFieldRow_1.TimelineEffectFieldRow, { field: node.field, validatedLocation: validatedLocation, paddingLeft: paddingLeft, nestedDepth: nestedDepth, nodePath: nodePath }));
49
+ }
50
+ if (node.field.kind === 'sequence-field') {
51
+ return (jsx_runtime_1.jsx(TimelineFieldRow_1.TimelineFieldRow, { field: node.field, validatedLocation: validatedLocation, paddingLeft: paddingLeft, nestedDepth: nestedDepth, nodePath: nodePath, schema: schema }));
52
+ }
53
+ throw new Error('Unexpected field kind: ' + JSON.stringify(node.field));
43
54
  }
44
55
  return (jsx_runtime_1.jsxs("div", { style: labelOnlyStyle, children: [
45
56
  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 { getCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
59
+ const { codeValues: visualModeCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
60
60
  const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
61
- const validatedLocation = (0, react_1.useMemo)(() => {
62
- var _a;
63
- if (!originalLocation ||
64
- !originalLocation.source ||
65
- !originalLocation.line) {
66
- return null;
67
- }
68
- return {
69
- source: originalLocation.source,
70
- line: originalLocation.line,
71
- column: (_a = originalLocation.column) !== null && _a !== void 0 ? _a : 0,
72
- };
73
- }, [originalLocation]);
74
61
  const tree = (0, react_1.useMemo)(() => (0, timeline_layout_1.buildTimelineTree)({
75
62
  sequence,
76
63
  nodePathInfo,
77
64
  getDragOverrides,
78
- getCodeValues,
79
- }), [sequence, nodePathInfo, getDragOverrides, getCodeValues]);
65
+ codeValues: visualModeCodeValues,
66
+ }), [sequence, nodePathInfo, getDragOverrides, visualModeCodeValues]);
80
67
  const flat = (0, react_1.useMemo)(() => (0, timeline_layout_1.flattenVisibleTreeNodes)({ nodes: tree, getIsExpanded }), [tree, getIsExpanded]);
81
68
  const expandedHeight = (0, react_1.useMemo)(() => (0, timeline_layout_1.getExpandedTrackHeight)({
82
69
  sequence,
83
70
  nodePathInfo,
84
71
  getIsExpanded,
85
- getCodeValues,
86
- }), [sequence, nodePathInfo, getIsExpanded, 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,12 +2,11 @@
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");
6
5
  const react_1 = require("react");
7
6
  const remotion_1 = require("remotion");
8
7
  const timeline_layout_1 = require("../../helpers/timeline-layout");
9
- const call_api_1 = require("../call-api");
10
8
  const Padder_1 = require("./Padder");
9
+ const save_sequence_prop_1 = require("./save-sequence-prop");
11
10
  const TimelineSchemaField_1 = require("./TimelineSchemaField");
12
11
  const fieldRowBase = {
13
12
  display: 'flex',
@@ -27,16 +26,9 @@ const fieldLabelRow = {
27
26
  alignItems: 'center',
28
27
  gap: 6,
29
28
  };
30
- const TimelineFieldRow = ({ field, validatedLocation, paddingLeft, nestedDepth, nodePath, schema, }) => {
31
- var _a, _b;
32
- const { getCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
29
+ const Value = ({ field, nodePath, validatedLocation, schema, codeValue }) => {
33
30
  const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
34
31
  const { setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
35
- const codeValuesForOverride = getCodeValues(nodePath);
36
- const codeValue = (_a = codeValuesForOverride === null || codeValuesForOverride === void 0 ? void 0 : codeValuesForOverride[field.key]) !== null && _a !== void 0 ? _a : null;
37
- if (codeValue === null) {
38
- throw new Error('Unexpectedly got null code value for field' + field.key);
39
- }
40
32
  const dragOverrideValue = (0, react_1.useMemo)(() => {
41
33
  var _a;
42
34
  return nodePath === null
@@ -45,16 +37,12 @@ const TimelineFieldRow = ({ field, validatedLocation, paddingLeft, nestedDepth,
45
37
  }, [getDragOverrides, nodePath, field.key]);
46
38
  const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
47
39
  codeValue,
48
- runtimeValue: field.currentRuntimeValue,
49
40
  dragOverrideValue,
50
41
  defaultValue: field.fieldSchema.default,
51
42
  shouldResortToDefaultValueIfUndefined: true,
52
43
  });
53
44
  const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
54
45
  const onSave = (0, react_1.useCallback)((value) => {
55
- if (!codeValuesForOverride || !validatedLocation || !nodePath) {
56
- return Promise.reject(new Error('Cannot save'));
57
- }
58
46
  if (!codeValue || !codeValue.canUpdate) {
59
47
  return Promise.reject(new Error('Cannot save'));
60
48
  }
@@ -69,42 +57,17 @@ const TimelineFieldRow = ({ field, validatedLocation, paddingLeft, nestedDepth,
69
57
  codeValue.codeValue === undefined) {
70
58
  return Promise.resolve();
71
59
  }
72
- let previousUpdate;
73
- // Optimistic update to prevent flicker
74
- setCodeValues(nodePath, (prev) => {
75
- previousUpdate = prev;
76
- return (0, studio_shared_1.optimisticUpdateForCodeValues)({
77
- previous: prev,
78
- fieldKey: field.key,
79
- value,
80
- schema,
81
- });
82
- });
83
- return (0, call_api_1.callApi)('/api/save-sequence-props', {
60
+ return (0, save_sequence_prop_1.saveSequenceProp)({
84
61
  fileName: validatedLocation.source,
85
62
  nodePath,
86
- key: field.key,
87
- value: stringifiedValue,
63
+ fieldKey: field.key,
64
+ value,
88
65
  defaultValue,
89
66
  schema,
90
- })
91
- .then((data) => {
92
- setCodeValues(nodePath, () => data);
93
- })
94
- .catch(() => {
95
- // In case something went wrong, undo optimistic update
96
- if (previousUpdate) {
97
- setCodeValues(nodePath, (current) => {
98
- if (previousUpdate) {
99
- return previousUpdate;
100
- }
101
- return current;
102
- });
103
- }
67
+ setCodeValues,
104
68
  });
105
69
  }, [
106
70
  codeValue,
107
- codeValuesForOverride,
108
71
  field.fieldSchema.default,
109
72
  field.key,
110
73
  nodePath,
@@ -124,6 +87,13 @@ const TimelineFieldRow = ({ field, validatedLocation, paddingLeft, nestedDepth,
124
87
  }
125
88
  clearDragOverrides(nodePath);
126
89
  }, [clearDragOverrides, nodePath]);
90
+ return (jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineFieldValue, { field: field, propStatus: codeValue, onSave: onSave, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd, effectiveValue: effectiveValue }));
91
+ };
92
+ const TimelineFieldRow = ({ field, validatedLocation, paddingLeft, nestedDepth, nodePath, schema, }) => {
93
+ var _a, _b;
94
+ const { codeValues: visualModeCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
95
+ const codeValuesForOverride = remotion_1.Internals.getCodeValuesCtx(visualModeCodeValues, nodePath);
96
+ const codeValue = (_a = codeValuesForOverride === null || codeValuesForOverride === void 0 ? void 0 : codeValuesForOverride[field.key]) !== null && _a !== void 0 ? _a : null;
127
97
  const style = (0, react_1.useMemo)(() => {
128
98
  return {
129
99
  ...fieldRowBase,
@@ -131,8 +101,10 @@ const TimelineFieldRow = ({ field, validatedLocation, paddingLeft, nestedDepth,
131
101
  paddingLeft,
132
102
  };
133
103
  }, [field.rowHeight, paddingLeft]);
104
+ if (codeValue === null) {
105
+ return null;
106
+ }
134
107
  return (jsx_runtime_1.jsxs("div", { style: style, children: [
135
- 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, effectiveValue: effectiveValue })
136
- ] }));
108
+ 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 }))] }));
137
109
  };
138
110
  exports.TimelineFieldRow = TimelineFieldRow;
@@ -1,5 +1,7 @@
1
+ import React from 'react';
1
2
  export declare const TimelineLayerEye: React.FC<{
2
- onInvoked: (type: 'enable' | 'disable') => void;
3
- hidden: boolean;
4
- type: 'eye' | 'speaker';
3
+ readonly onInvoked: (type: 'enable' | 'disable') => void;
4
+ readonly hidden: boolean;
5
+ readonly type: 'eye' | 'speaker' | 'effect';
5
6
  }>;
7
+ export declare const TimelineLayerEyeSpacer: React.FC;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TimelineLayerEye = void 0;
3
+ exports.TimelineLayerEyeSpacer = exports.TimelineLayerEye = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const colors_1 = require("../../helpers/colors");
@@ -9,6 +9,10 @@ const eyeIcon = {
9
9
  color: 'currentColor',
10
10
  pointerEvents: 'none',
11
11
  };
12
+ const effectIcon = {
13
+ ...eyeIcon,
14
+ width: 15,
15
+ };
12
16
  const speakerIcon = {
13
17
  ...eyeIcon,
14
18
  height: 10,
@@ -34,6 +38,9 @@ const TimelineLayerEye = ({ onInvoked, hidden, type }) => {
34
38
  if (type === 'speaker') {
35
39
  return (jsx_runtime_1.jsx("svg", { viewBox: "0 0 10 14", fill: "none", style: speakerIcon, children: jsx_runtime_1.jsx("path", { d: "M9.40938 0.0869018C9.76875 0.249402 10 0.605652 10 0.999402V12.9994C10 13.3932 9.76875 13.7494 9.40938 13.9119C9.05 14.0744 8.62813 14.0088 8.33438 13.7463L4.11875 9.9994H2C0.896875 9.9994 0 9.10253 0 7.9994V5.9994C0 4.89628 0.896875 3.9994 2 3.9994H4.11875L8.33438 0.252527C8.62813 -0.0099732 9.05 -0.0724732 9.40938 0.0869018Z", fill: color }) }));
36
40
  }
41
+ if (type === 'effect') {
42
+ return (jsx_runtime_1.jsx("svg", { viewBox: "0 0 16 16", fill: "none", style: effectIcon, children: jsx_runtime_1.jsx("path", { d: "M4.405 4.48C4.575 3.82 4.865 3.325 5.275 2.995C5.695 2.665 6.25 2.5 6.94 2.5H9.235V4.06H7.045C6.555 4.06 6.235 4.3 6.085 4.78L5.83 5.68H7.975V7.255H5.395L3.805 13H2.02L3.625 7.255H1.96V5.68H4.075L4.405 4.48ZM8.57102 9.085L6.87602 5.68H8.79602L9.86102 7.99L11.991 5.68H14.331L10.686 9.415L12.426 13H10.491L9.35102 10.585L7.02602 13H4.68602L8.57102 9.085Z", fill: "white" }) }));
43
+ }
37
44
  return (jsx_runtime_1.jsx("svg", { style: eyeIcon, viewBox: "0 0 24 16", fill: "none", children: jsx_runtime_1.jsx("path", { d: "M24 7.551C24 7.551 19.748 16 12.015 16C4.835 16 0 7.551 0 7.551C0 7.551 4.446 0 12.015 0C19.709 0 24 7.551 24 7.551ZM17 8C17 5.243 14.757 3 12 3C9.243 3 7 5.243 7 8C7 10.757 9.243 13 12 13C14.757 13 17 10.757 17 8Z", fill: color }) }));
38
45
  }, [hidden, type]);
39
46
  const onPointerDown = (0, react_1.useCallback)((e) => {
@@ -54,3 +61,13 @@ const TimelineLayerEye = ({ onInvoked, hidden, type }) => {
54
61
  return (jsx_runtime_1.jsx("div", { style: container, onPointerEnter: onPointerEnter, onPointerDown: onPointerDown, children: renderAction(colors_1.LIGHT_COLOR) }));
55
62
  };
56
63
  exports.TimelineLayerEye = TimelineLayerEye;
64
+ const spacerStyle = {
65
+ width: 16,
66
+ height: 16,
67
+ marginRight: 6,
68
+ flexShrink: 0,
69
+ };
70
+ const TimelineLayerEyeSpacer = () => {
71
+ return jsx_runtime_1.jsx("div", { style: spacerStyle });
72
+ };
73
+ exports.TimelineLayerEyeSpacer = TimelineLayerEyeSpacer;
@@ -12,6 +12,7 @@ const ContextMenu_1 = require("../ContextMenu");
12
12
  const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
13
13
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
14
14
  const Padder_1 = require("./Padder");
15
+ const save_sequence_prop_1 = require("./save-sequence-prop");
15
16
  const TimelineExpandArrowButton_1 = require("./TimelineExpandArrowButton");
16
17
  const TimelineExpandedSection_1 = require("./TimelineExpandedSection");
17
18
  const TimelineLayerEye_1 = require("./TimelineLayerEye");
@@ -19,14 +20,16 @@ const TimelineStack_1 = require("./TimelineStack");
19
20
  const use_resolved_stack_1 = require("./use-resolved-stack");
20
21
  exports.INDENT = 10;
21
22
  const TimelineListItem = ({ nestedDepth, sequence, isCompact, nodePathInfo }) => {
22
- var _a, _b;
23
- const nodePath = (_a = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.nodePath) !== null && _a !== void 0 ? _a : null;
23
+ var _a;
24
+ var _b, _c;
25
+ const nodePath = (_b = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _b !== void 0 ? _b : null;
24
26
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
25
27
  const previewConnected = previewServerState.type === 'connected';
26
- const { hidden, setHidden } = (0, react_1.useContext)(remotion_1.Internals.SequenceVisibilityToggleContext);
27
28
  const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
28
29
  const { toggleTrack } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksSetterContext);
29
- const originalLocation = (0, use_resolved_stack_1.useResolvedStack)((_b = sequence.stack) !== null && _b !== void 0 ? _b : null);
30
+ const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
31
+ const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
32
+ const originalLocation = (0, use_resolved_stack_1.useResolvedStack)((_c = sequence.stack) !== null && _c !== void 0 ? _c : null);
30
33
  const validatedLocation = (0, react_1.useMemo)(() => {
31
34
  var _a;
32
35
  if (!originalLocation ||
@@ -59,7 +62,7 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact, nodePathInfo }) =>
59
62
  try {
60
63
  const result = await (0, call_api_1.callApi)('/api/duplicate-jsx-node', {
61
64
  fileName: validatedLocation.source,
62
- nodePath,
65
+ nodePath: nodePath.nodePath,
63
66
  });
64
67
  if (result.success) {
65
68
  (0, NotificationCenter_1.showNotification)('Duplicated sequence in source file', 2000);
@@ -88,7 +91,7 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact, nodePathInfo }) =>
88
91
  try {
89
92
  const result = await (0, call_api_1.callApi)('/api/delete-jsx-node', {
90
93
  fileName: validatedLocation.source,
91
- nodePath,
94
+ nodePath: nodePath.nodePath,
92
95
  });
93
96
  if (result.success) {
94
97
  (0, NotificationCenter_1.showNotification)('Removed sequence from source file', 2000);
@@ -155,18 +158,53 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact, nodePathInfo }) =>
155
158
  }
156
159
  toggleTrack(nodePathInfo);
157
160
  }, [nodePathInfo, toggleTrack]);
161
+ const codeValuesForOverride = (0, react_1.useMemo)(() => {
162
+ return nodePath
163
+ ? remotion_1.Internals.getCodeValuesCtx(codeValues, nodePath)
164
+ : undefined;
165
+ }, [codeValues, nodePath]);
166
+ const codeHiddenStatus = codeValuesForOverride === null || codeValuesForOverride === void 0 ? void 0 : codeValuesForOverride.hidden;
158
167
  const isItemHidden = (0, react_1.useMemo)(() => {
159
168
  var _a;
160
- return (_a = hidden[sequence.id]) !== null && _a !== void 0 ? _a : false;
161
- }, [hidden, sequence.id]);
169
+ const codeValue = codeHiddenStatus && codeHiddenStatus.canUpdate
170
+ ? codeHiddenStatus.codeValue
171
+ : undefined;
172
+ const runtimeValue = (_a = sequence.controls) === null || _a === void 0 ? void 0 : _a.currentRuntimeValueDotNotation.hidden;
173
+ const effective = (codeValue !== null && codeValue !== void 0 ? codeValue : runtimeValue);
174
+ return effective !== null && effective !== void 0 ? effective : false;
175
+ }, [codeHiddenStatus, (_a = sequence.controls) === null || _a === void 0 ? void 0 : _a.currentRuntimeValueDotNotation]);
162
176
  const onToggleVisibility = (0, react_1.useCallback)((type) => {
163
- setHidden((prev) => {
164
- return {
165
- ...prev,
166
- [sequence.id]: type !== 'enable',
167
- };
177
+ if (!sequence.controls ||
178
+ !nodePath ||
179
+ !validatedLocation ||
180
+ !codeValuesForOverride ||
181
+ !codeHiddenStatus ||
182
+ !codeHiddenStatus.canUpdate) {
183
+ return;
184
+ }
185
+ const newValue = type !== 'enable';
186
+ const { schema } = sequence.controls;
187
+ const fieldSchema = schema.hidden;
188
+ const defaultValue = fieldSchema && fieldSchema.type === 'boolean'
189
+ ? JSON.stringify(fieldSchema.default)
190
+ : null;
191
+ (0, save_sequence_prop_1.saveSequenceProp)({
192
+ fileName: validatedLocation.source,
193
+ nodePath,
194
+ fieldKey: 'hidden',
195
+ value: newValue,
196
+ defaultValue,
197
+ schema,
198
+ setCodeValues,
168
199
  });
169
- }, [sequence.id, setHidden]);
200
+ }, [
201
+ codeHiddenStatus,
202
+ codeValuesForOverride,
203
+ nodePath,
204
+ sequence.controls,
205
+ setCodeValues,
206
+ validatedLocation,
207
+ ]);
170
208
  const outer = (0, react_1.useMemo)(() => {
171
209
  return {
172
210
  height: (0, timeline_layout_1.getTimelineLayerHeight)(sequence.type) + timeline_layout_1.TIMELINE_ITEM_BORDER_BOTTOM,
@@ -188,12 +226,18 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact, nodePathInfo }) =>
188
226
  };
189
227
  }, []);
190
228
  const hasExpandableContent = Boolean(sequence.controls) || sequence.effects.length > 0;
191
- const trackRow = (jsx_runtime_1.jsx("div", { style: outer, children: jsx_runtime_1.jsxs("div", { style: inner, children: [
192
- jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility }), jsx_runtime_1.jsx(Padder_1.Padder, { depth: nestedDepth }), previewConnected ? (hasExpandableContent ? (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: onToggleExpand, label: "track properties", disabled: nodePathInfo === null })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {}))) : null, jsx_runtime_1.jsx(TimelineStack_1.TimelineStack, { sequence: sequence, isCompact: isCompact, originalLocation: originalLocation })
229
+ const canToggleVisibility = Boolean(sequence.controls) &&
230
+ nodePath !== null &&
231
+ validatedLocation !== null &&
232
+ codeHiddenStatus !== undefined &&
233
+ codeHiddenStatus !== null &&
234
+ codeHiddenStatus.canUpdate;
235
+ const trackRow = (jsx_runtime_1.jsx("div", { style: outer, children: jsx_runtime_1.jsxs("div", { style: inner, children: [canToggleVisibility ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), jsx_runtime_1.jsx(Padder_1.Padder, { depth: nestedDepth }), previewConnected ? (hasExpandableContent ? (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: onToggleExpand, label: "track properties", disabled: nodePathInfo === null })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {}))) : null, jsx_runtime_1.jsx(TimelineStack_1.TimelineStack, { sequence: sequence, isCompact: isCompact, originalLocation: originalLocation })
193
236
  ] }) }));
194
237
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, children: trackRow })) : (trackRow), previewConnected &&
195
238
  isExpanded &&
196
239
  hasExpandableContent &&
197
- nodePathInfo ? (jsx_runtime_1.jsx(TimelineExpandedSection_1.TimelineExpandedSection, { sequence: sequence, originalLocation: originalLocation, nodePathInfo: nodePathInfo, nestedDepth: nestedDepth })) : null] }));
240
+ nodePathInfo &&
241
+ validatedLocation ? (jsx_runtime_1.jsx(TimelineExpandedSection_1.TimelineExpandedSection, { sequence: sequence, validatedLocation: validatedLocation, nodePathInfo: nodePathInfo, nestedDepth: nestedDepth })) : null] }));
198
242
  };
199
243
  exports.TimelineListItem = TimelineListItem;
@@ -31,7 +31,7 @@ const TimelineNumberField = ({ field, effectiveValue, onSave, onDragValueChange,
31
31
  propStatus.canUpdate &&
32
32
  parsed !== propStatus.codeValue) {
33
33
  setDragValue(parsed);
34
- onSave(parsed).catch(() => {
34
+ onSave(parsed).finally(() => {
35
35
  setDragValue(null);
36
36
  });
37
37
  }
@@ -53,7 +53,7 @@ const TimelineRotationField = ({ field, effectiveValue, propStatus, onSave, onDr
53
53
  const newStr = `${parsed}deg`;
54
54
  if (newStr !== propStatus.codeValue) {
55
55
  setDragValue(parsed);
56
- onSave(newStr).catch(() => {
56
+ onSave(newStr).finally(() => {
57
57
  setDragValue(null);
58
58
  });
59
59
  }
@@ -1,11 +1,17 @@
1
1
  import React from 'react';
2
- import type { CanUpdateSequencePropStatus } from 'remotion';
2
+ import type { CanUpdateSequencePropStatusFalse, CanUpdateSequencePropStatusTrue } from 'remotion';
3
3
  import type { SchemaFieldInfo, TimelineFieldOnDragValueChange, TimelineFieldOnSave } from '../../helpers/timeline-layout';
4
+ export declare const UnsupportedStatus: React.FC<{
5
+ readonly label: string;
6
+ }>;
7
+ export declare const TimelineNonEditableStatus: React.FC<{
8
+ readonly propStatus: CanUpdateSequencePropStatusFalse;
9
+ }>;
4
10
  export declare const TimelineFieldValue: React.FC<{
5
11
  readonly field: SchemaFieldInfo;
6
12
  readonly onSave: TimelineFieldOnSave;
7
13
  readonly onDragValueChange: TimelineFieldOnDragValueChange;
8
14
  readonly onDragEnd: () => void;
9
- readonly propStatus: CanUpdateSequencePropStatus;
15
+ readonly propStatus: CanUpdateSequencePropStatusTrue;
10
16
  readonly effectiveValue: unknown;
11
17
  }>;
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TimelineFieldValue = void 0;
3
+ exports.TimelineFieldValue = exports.TimelineNonEditableStatus = exports.UnsupportedStatus = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const TimelineBooleanField_1 = require("./TimelineBooleanField");
6
+ const TimelineColorField_1 = require("./TimelineColorField");
6
7
  const TimelineEnumField_1 = require("./TimelineEnumField");
7
8
  const TimelineNumberField_1 = require("./TimelineNumberField");
8
9
  const TimelineRotationField_1 = require("./TimelineRotationField");
@@ -20,19 +21,24 @@ const notEditableBackground = {
20
21
  const inlineWrapper = {
21
22
  fontSize: 12,
22
23
  };
24
+ const UnsupportedStatus = ({ label }) => {
25
+ return jsx_runtime_1.jsx("span", { style: unsupportedLabel, children: label });
26
+ };
27
+ exports.UnsupportedStatus = UnsupportedStatus;
28
+ const TimelineNonEditableStatus = ({ propStatus }) => {
29
+ if (propStatus.canUpdate) {
30
+ return null;
31
+ }
32
+ if (propStatus.reason === 'computed') {
33
+ return jsx_runtime_1.jsx("span", { style: unsupportedLabel, children: "computed" });
34
+ }
35
+ throw new Error(`Unsupported prop status: ${propStatus.reason}`);
36
+ };
37
+ exports.TimelineNonEditableStatus = TimelineNonEditableStatus;
23
38
  const TimelineFieldValue = ({ field, onSave, onDragValueChange, onDragEnd, propStatus, effectiveValue, }) => {
24
39
  const wrapperStyle = !propStatus.canUpdate
25
40
  ? notEditableBackground
26
41
  : undefined;
27
- if (!field.supported) {
28
- return jsx_runtime_1.jsx("span", { style: unsupportedLabel, children: "unsupported" });
29
- }
30
- if (!propStatus.canUpdate) {
31
- if (propStatus.reason === 'computed') {
32
- return jsx_runtime_1.jsx("span", { style: unsupportedLabel, children: "computed" });
33
- }
34
- throw new Error(`Unsupported prop status: ${propStatus.reason}`);
35
- }
36
42
  if (field.typeName === 'number') {
37
43
  return (jsx_runtime_1.jsx("span", { style: wrapperStyle, children: jsx_runtime_1.jsx(TimelineNumberField_1.TimelineNumberField, { field: field, effectiveValue: effectiveValue, onSave: onSave, propStatus: propStatus, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd }) }));
38
44
  }
@@ -45,9 +51,12 @@ const TimelineFieldValue = ({ field, onSave, onDragValueChange, onDragEnd, propS
45
51
  if (field.typeName === 'boolean') {
46
52
  return (jsx_runtime_1.jsx("span", { style: wrapperStyle, children: jsx_runtime_1.jsx(TimelineBooleanField_1.TimelineBooleanField, { field: field, propStatus: propStatus, onSave: onSave, effectiveValue: effectiveValue }) }));
47
53
  }
54
+ if (field.typeName === 'color') {
55
+ return (jsx_runtime_1.jsx("span", { style: wrapperStyle, children: jsx_runtime_1.jsx(TimelineColorField_1.TimelineColorField, { field: field, propStatus: propStatus, onSave: onSave, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd, effectiveValue: effectiveValue }) }));
56
+ }
48
57
  if (field.typeName === 'enum') {
49
58
  return (jsx_runtime_1.jsx("span", { style: inlineWrapper, children: jsx_runtime_1.jsx(TimelineEnumField_1.TimelineEnumField, { field: field, propStatus: propStatus, onSave: onSave, effectiveValue: effectiveValue, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd }) }));
50
59
  }
51
- return (jsx_runtime_1.jsx("span", { style: { ...unsupportedLabel, fontStyle: 'normal' }, children: String(effectiveValue) }));
60
+ throw new Error(`Unsupported field type: ${field.typeName}`);
52
61
  };
53
62
  exports.TimelineFieldValue = TimelineFieldValue;
@@ -52,18 +52,18 @@ const content = {
52
52
  const timelineContent = {
53
53
  minHeight: '100%',
54
54
  };
55
- const getExpandedPlaceholderStyle = ({ sequence, nodePathInfo, getIsExpanded, getCodeValues, }) => ({
55
+ const getExpandedPlaceholderStyle = ({ sequence, nodePathInfo, getIsExpanded, codeValues, }) => ({
56
56
  height: (0, timeline_layout_1.getExpandedTrackHeight)({
57
57
  sequence,
58
58
  nodePathInfo,
59
59
  getIsExpanded,
60
- getCodeValues,
60
+ codeValues,
61
61
  }) + timeline_layout_1.TIMELINE_ITEM_BORDER_BOTTOM,
62
62
  });
63
63
  const TimelineTracksInner = ({ timeline, hasBeenCut }) => {
64
64
  const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
65
65
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
66
- const { getCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
66
+ const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
67
67
  const previewServerConnected = previewServerState.type === 'connected';
68
68
  const timelineStyle = (0, react_1.useMemo)(() => {
69
69
  return {
@@ -86,7 +86,7 @@ const TimelineTracksInner = ({ timeline, hasBeenCut }) => {
86
86
  sequence: track.sequence,
87
87
  nodePathInfo: track.nodePathInfo,
88
88
  getIsExpanded,
89
- getCodeValues,
89
+ codeValues,
90
90
  }) })) : null] }, track.sequence.id));
91
91
  })] }), hasBeenCut ? jsx_runtime_1.jsx(MaxTimelineTracks_1.MaxTimelineTracksReached, {}) : null] }));
92
92
  };
@@ -65,7 +65,9 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
65
65
  const newStr = makeString(parsed, currentY);
66
66
  if (newStr !== propStatus.codeValue) {
67
67
  setDragX(parsed);
68
- onSave(newStr);
68
+ onSave(newStr).finally(() => {
69
+ setDragX(null);
70
+ });
69
71
  }
70
72
  }
71
73
  }
@@ -98,7 +100,7 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
98
100
  const newStr = makeString(currentX, parsed);
99
101
  if (newStr !== propStatus.codeValue) {
100
102
  setDragY(parsed);
101
- onSave(newStr).catch(() => {
103
+ onSave(newStr).finally(() => {
102
104
  setDragY(null);
103
105
  });
104
106
  }
@@ -0,0 +1,12 @@
1
+ import type { SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
2
+ import type { SetCodeValues } from './save-sequence-prop';
3
+ export declare const saveEffectProp: ({ fileName, nodePath, effectIndex, fieldKey, value, defaultValue, schema, setCodeValues, }: {
4
+ fileName: string;
5
+ nodePath: SequencePropsSubscriptionKey;
6
+ effectIndex: number;
7
+ fieldKey: string;
8
+ value: unknown;
9
+ defaultValue: string | null;
10
+ schema: SequenceSchema;
11
+ setCodeValues: SetCodeValues;
12
+ }) => Promise<void>;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.saveEffectProp = void 0;
4
+ const studio_shared_1 = require("@remotion/studio-shared");
5
+ const call_api_1 = require("../call-api");
6
+ const save_prop_queue_1 = require("./save-prop-queue");
7
+ const saveEffectProp = ({ fileName, nodePath, effectIndex, fieldKey, value, defaultValue, schema, setCodeValues, }) => {
8
+ return (0, save_prop_queue_1.enqueueSavePropChange)({
9
+ nodePath,
10
+ setCodeValues,
11
+ applyOptimistic: (prev) => (0, studio_shared_1.optimisticUpdateForEffectCodeValues)({
12
+ previous: prev,
13
+ effectIndex,
14
+ fieldKey,
15
+ value,
16
+ schema,
17
+ }),
18
+ apiCall: () => (0, call_api_1.callApi)('/api/save-effect-props', {
19
+ fileName,
20
+ sequenceNodePath: nodePath,
21
+ effectIndex,
22
+ key: fieldKey,
23
+ value: JSON.stringify(value),
24
+ defaultValue,
25
+ schema,
26
+ }),
27
+ mergeServerResponse: (prev, data) => {
28
+ if (!prev.canUpdate) {
29
+ return prev;
30
+ }
31
+ const idx = prev.effects.findIndex((e) => e.effectIndex === effectIndex);
32
+ if (idx === -1) {
33
+ return { ...prev, effects: [...prev.effects, data] };
34
+ }
35
+ const nextEffects = [...prev.effects];
36
+ nextEffects[idx] = data;
37
+ return { ...prev, effects: nextEffects };
38
+ },
39
+ errorLabel: 'Could not save effect prop',
40
+ });
41
+ };
42
+ exports.saveEffectProp = saveEffectProp;