@remotion/studio 4.0.462 → 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 (33) hide show
  1. package/dist/components/AssetSelector.js +2 -6
  2. package/dist/components/CompSelectorRef.js +2 -6
  3. package/dist/components/ExpandedTracksProvider.js +5 -20
  4. package/dist/components/Timeline/SubscribeToNodePaths.js +1 -6
  5. package/dist/components/Timeline/TimelineColorField.js +1 -1
  6. package/dist/components/Timeline/TimelineEffectFieldRow.js +21 -31
  7. package/dist/components/Timeline/TimelineEffectGroupRow.d.ts +17 -0
  8. package/dist/components/Timeline/TimelineEffectGroupRow.js +73 -0
  9. package/dist/components/Timeline/TimelineExpandedRow.js +4 -0
  10. package/dist/components/Timeline/TimelineFieldRow.js +5 -39
  11. package/dist/components/Timeline/TimelineLayerEye.d.ts +5 -3
  12. package/dist/components/Timeline/TimelineLayerEye.js +18 -1
  13. package/dist/components/Timeline/TimelineListItem.js +57 -14
  14. package/dist/components/Timeline/save-effect-prop.d.ts +12 -0
  15. package/dist/components/Timeline/save-effect-prop.js +42 -0
  16. package/dist/components/Timeline/save-prop-queue.d.ts +12 -0
  17. package/dist/components/Timeline/save-prop-queue.js +63 -0
  18. package/dist/components/Timeline/save-sequence-prop.d.ts +11 -0
  19. package/dist/components/Timeline/save-sequence-prop.js +38 -0
  20. package/dist/esm/chunk-5gtx3pza.js +9 -0
  21. package/dist/esm/{chunk-yvg1f56k.js → chunk-b0m62frw.js} +2327 -2028
  22. package/dist/esm/index.mjs +0 -16
  23. package/dist/esm/internals.mjs +2325 -2041
  24. package/dist/esm/previewEntry.mjs +2335 -2051
  25. package/dist/esm/renderEntry.mjs +3 -4
  26. package/dist/helpers/persist-boolean-map.d.ts +5 -0
  27. package/dist/helpers/persist-boolean-map.js +56 -0
  28. package/dist/helpers/persist-open-folders.d.ts +4 -3
  29. package/dist/helpers/persist-open-folders.js +4 -7
  30. package/dist/helpers/timeline-layout.d.ts +6 -1
  31. package/dist/helpers/timeline-layout.js +2 -0
  32. package/package.json +10 -10
  33. package/dist/esm/chunk-6jf1natv.js +0 -25
@@ -11,6 +11,7 @@ const write_static_file_1 = require("../api/write-static-file");
11
11
  const client_id_1 = require("../helpers/client-id");
12
12
  const colors_1 = require("../helpers/colors");
13
13
  const create_folder_tree_1 = require("../helpers/create-folder-tree");
14
+ const persist_boolean_map_1 = require("../helpers/persist-boolean-map");
14
15
  const persist_open_folders_1 = require("../helpers/persist-open-folders");
15
16
  const use_asset_drag_events_1 = __importDefault(require("../helpers/use-asset-drag-events"));
16
17
  const folders_1 = require("../state/folders");
@@ -68,13 +69,8 @@ const AssetSelector = ({ readOnlyStudio }) => {
68
69
  }, [assetFoldersExpanded, staticFiles]);
69
70
  const toggleFolder = (0, react_1.useCallback)((folderName, parentName) => {
70
71
  setAssetFoldersExpanded((p) => {
71
- var _a;
72
72
  const key = [parentName, folderName].filter(Boolean).join('/');
73
- const prev = (_a = p[key]) !== null && _a !== void 0 ? _a : false;
74
- const foldersExpandedState = {
75
- ...p,
76
- [key]: !prev,
77
- };
73
+ const foldersExpandedState = (0, persist_boolean_map_1.toggleBooleanMapKey)(p, key);
78
74
  (0, persist_open_folders_1.persistExpandedFolders)('assets', foldersExpandedState);
79
75
  return foldersExpandedState;
80
76
  });
@@ -5,6 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
7
  const create_folder_tree_1 = require("../helpers/create-folder-tree");
8
+ const persist_boolean_map_1 = require("../helpers/persist-boolean-map");
8
9
  const persist_open_folders_1 = require("../helpers/persist-open-folders");
9
10
  const folders_1 = require("../state/folders");
10
11
  const InitialCompositionLoader_1 = require("./InitialCompositionLoader");
@@ -14,13 +15,8 @@ const CompSelectorRef = ({ children }) => {
14
15
  const selectComposition = (0, InitialCompositionLoader_1.useSelectComposition)();
15
16
  const toggleFolder = (0, react_1.useCallback)((folderName, parentName) => {
16
17
  setCompositionFoldersExpanded((p) => {
17
- var _a;
18
18
  const key = (0, persist_open_folders_1.openFolderKey)({ folderName, parentName });
19
- const prev = (_a = p[key]) !== null && _a !== void 0 ? _a : false;
20
- const foldersExpandedState = {
21
- ...p,
22
- [key]: !prev,
23
- };
19
+ const foldersExpandedState = (0, persist_boolean_map_1.toggleBooleanMapKey)(p, key);
24
20
  (0, persist_open_folders_1.persistExpandedFolders)('compositions', foldersExpandedState);
25
21
  return foldersExpandedState;
26
22
  });
@@ -4,30 +4,15 @@ exports.ExpandedTracksProvider = exports.ExpandedTracksSetterContext = exports.E
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const studio_shared_1 = require("@remotion/studio-shared");
6
6
  const react_1 = require("react");
7
+ const persist_boolean_map_1 = require("../helpers/persist-boolean-map");
7
8
  const nodePathInfoToExpandedKey = (info) => [
8
9
  (0, studio_shared_1.stringifySequenceExpandedRowKey)(info.sequenceSubscriptionKey),
9
10
  info.auxiliaryKeys.join('.'),
10
11
  info.index,
11
12
  ].join('.');
12
- const LOCAL_STORAGE_KEY = 'remotion.editor.expandedTracks';
13
+ const SESSION_STORAGE_KEY = 'remotion.editor.expandedTracks';
13
14
  const loadExpandedTracks = () => {
14
- if (typeof window === 'undefined') {
15
- return {};
16
- }
17
- const item = window.localStorage.getItem(LOCAL_STORAGE_KEY);
18
- if (item === null) {
19
- return {};
20
- }
21
- try {
22
- const parsed = JSON.parse(item);
23
- if (parsed && typeof parsed === 'object') {
24
- return parsed;
25
- }
26
- return {};
27
- }
28
- catch (_a) {
29
- return {};
30
- }
15
+ return (0, persist_boolean_map_1.loadPersistedBooleanMap)(SESSION_STORAGE_KEY);
31
16
  };
32
17
  exports.ExpandedTracksGetterContext = (0, react_1.createContext)({
33
18
  getIsExpanded: () => {
@@ -44,8 +29,8 @@ const ExpandedTracksProvider = ({ children }) => {
44
29
  const toggleTrack = (0, react_1.useCallback)((nodePathInfo) => {
45
30
  setExpandedTracks((prev) => {
46
31
  const key = nodePathInfoToExpandedKey(nodePathInfo);
47
- const next = { ...prev, [key]: !prev[key] };
48
- window.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(next));
32
+ const next = (0, persist_boolean_map_1.toggleBooleanMapKey)(prev, key);
33
+ (0, persist_boolean_map_1.persistBooleanMap)(SESSION_STORAGE_KEY, next);
49
34
  return next;
50
35
  });
51
36
  }, []);
@@ -2,17 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SubscribeToNodePaths = void 0;
4
4
  const react_1 = require("react");
5
- const no_react_1 = require("remotion/no-react");
6
5
  const use_resolved_stack_1 = require("./use-resolved-stack");
7
6
  const use_sequence_props_subscription_1 = require("./use-sequence-props-subscription");
8
7
  const SubscribeToNodePaths = ({ overrideId, schema, stack, effects }) => {
9
8
  const originalLocation = (0, use_resolved_stack_1.useResolvedStack)(stack);
10
9
  const effectSubscriptions = (0, react_1.useMemo)(() => {
11
- return effects
12
- .map((effect) => {
13
- return effect.schema;
14
- })
15
- .filter(no_react_1.NoReactInternals.truthy);
10
+ return effects.map((effect) => effect.schema);
16
11
  }, [effects]);
17
12
  (0, use_sequence_props_subscription_1.useSequencePropsSubscription)({
18
13
  overrideId,
@@ -176,6 +176,6 @@ const TimelineColorField = ({ field, effectiveValue, propStatus, onSave, onDragV
176
176
  return (jsx_runtime_1.jsxs("span", { style: containerStyle, children: [
177
177
  jsx_runtime_1.jsxs("span", { style: swatchWrapperStyle, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onClick: onSwatchClick, title: currentValue, children: [
178
178
  jsx_runtime_1.jsx("span", { style: swatchFill }), jsx_runtime_1.jsx("input", { ref: inputRef, type: "color", value: hexValue, onChange: onColorChange, onFocus: onFocus, onBlur: onBlur, disabled: !propStatus.canUpdate, name: field.key, tabIndex: tabIndex, style: hiddenInputStyle })
179
- ] }), showEyeDropper ? (jsx_runtime_1.jsx("button", { type: "button", onClick: onPickColor, disabled: !propStatus.canUpdate, style: eyedropperButtonBase, tabIndex: tabIndex, title: "Pick color from screen", "aria-label": "Pick color from screen", children: jsx_runtime_1.jsx(eyedropper_1.EyedropperIcon, { style: eyedropperIconStyle }) })) : null] }));
179
+ ] }), showEyeDropper ? (jsx_runtime_1.jsx("button", { type: "button", onClick: onPickColor, disabled: !propStatus.canUpdate, style: eyedropperButtonBase, tabIndex: tabIndex, title: "Pick color from screen", "aria-label": "Pick color from screen", children: jsx_runtime_1.jsx(eyedropper_1.EyedropperIcon, { style: eyedropperIconStyle, color: "rgba(255, 255, 255, 0.7)" }) })) : null] }));
180
180
  };
181
181
  exports.TimelineColorField = TimelineColorField;
@@ -7,8 +7,8 @@ const react_1 = require("react");
7
7
  const remotion_1 = require("remotion");
8
8
  const timeline_layout_1 = require("../../helpers/timeline-layout");
9
9
  const call_api_1 = require("../call-api");
10
- const NotificationCenter_1 = require("../Notifications/NotificationCenter");
11
10
  const Padder_1 = require("./Padder");
11
+ const save_prop_queue_1 = require("./save-prop-queue");
12
12
  const TimelineSchemaField_1 = require("./TimelineSchemaField");
13
13
  const fieldRowBase = {
14
14
  display: 'flex',
@@ -73,28 +73,26 @@ const Value = ({ field, nodePath, validatedLocation }) => {
73
73
  propStatus.codeValue === undefined) {
74
74
  return Promise.resolve();
75
75
  }
76
- let previousUpdate;
77
- setCodeValues(nodePath, (prev) => {
78
- previousUpdate = prev;
79
- return (0, studio_shared_1.optimisticUpdateForEffectCodeValues)({
76
+ return (0, save_prop_queue_1.enqueueSavePropChange)({
77
+ nodePath,
78
+ setCodeValues,
79
+ applyOptimistic: (prev) => (0, studio_shared_1.optimisticUpdateForEffectCodeValues)({
80
80
  previous: prev,
81
81
  effectIndex: field.effectIndex,
82
82
  fieldKey: field.key,
83
83
  value,
84
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) => {
85
+ }),
86
+ apiCall: () => (0, call_api_1.callApi)('/api/save-effect-props', {
87
+ fileName: validatedLocation.source,
88
+ sequenceNodePath: nodePath,
89
+ effectIndex: field.effectIndex,
90
+ key: field.key,
91
+ value: stringifiedValue,
92
+ defaultValue,
93
+ schema: field.effectSchema,
94
+ }),
95
+ mergeServerResponse: (prev, data) => {
98
96
  if (!prev.canUpdate) {
99
97
  return prev;
100
98
  }
@@ -105,19 +103,11 @@ const Value = ({ field, nodePath, validatedLocation }) => {
105
103
  effects: [...prev.effects, data],
106
104
  };
107
105
  }
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);
106
+ const nextEffects = [...prev.effects];
107
+ nextEffects[idx] = data;
108
+ return { ...prev, effects: nextEffects };
109
+ },
110
+ errorLabel: 'Could not save effect prop',
121
111
  });
122
112
  }, [
123
113
  field.effectIndex,
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import type { SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
3
+ import type { CodePosition } from '../../error-overlay/react-overlay/utils/get-source-map';
4
+ import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
5
+ import type { GetIsExpanded } from '../ExpandedTracksProvider';
6
+ export declare const TimelineEffectGroupRow: React.FC<{
7
+ readonly label: string;
8
+ readonly nodePathInfo: SequenceNodePathInfo;
9
+ readonly effectIndex: number;
10
+ readonly effectSchema: SequenceSchema;
11
+ readonly nodePath: SequencePropsSubscriptionKey;
12
+ readonly validatedLocation: CodePosition;
13
+ readonly nestedDepth: number;
14
+ readonly style: React.CSSProperties;
15
+ readonly getIsExpanded: GetIsExpanded;
16
+ readonly toggleTrack: (nodePathInfo: SequenceNodePathInfo) => void;
17
+ }>;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelineEffectGroupRow = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const remotion_1 = require("remotion");
7
+ const Padder_1 = require("./Padder");
8
+ const save_effect_prop_1 = require("./save-effect-prop");
9
+ const TimelineExpandArrowButton_1 = require("./TimelineExpandArrowButton");
10
+ const TimelineLayerEye_1 = require("./TimelineLayerEye");
11
+ const groupRowBase = {
12
+ display: 'flex',
13
+ alignItems: 'center',
14
+ };
15
+ const rowLabel = {
16
+ fontSize: 12,
17
+ color: 'rgba(255, 255, 255, 0.8)',
18
+ userSelect: 'none',
19
+ };
20
+ const TimelineEffectGroupRow = ({ label, nodePathInfo, effectIndex, effectSchema, nodePath, validatedLocation, nestedDepth, style, getIsExpanded, toggleTrack, }) => {
21
+ var _a;
22
+ var _b;
23
+ const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
24
+ const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
25
+ const effectStatus = (0, react_1.useMemo)(() => remotion_1.Internals.getEffectCodeValuesCtx({
26
+ codeValues,
27
+ nodePath,
28
+ effectIndex,
29
+ }), [codeValues, nodePath, effectIndex]);
30
+ const disabledStatus = effectStatus.type === 'can-update-effect'
31
+ ? ((_b = (_a = effectStatus.props) === null || _a === void 0 ? void 0 : _a.disabled) !== null && _b !== void 0 ? _b : null)
32
+ : null;
33
+ const isDisabled = (0, react_1.useMemo)(() => {
34
+ if (disabledStatus && disabledStatus.canUpdate) {
35
+ return Boolean(disabledStatus.codeValue);
36
+ }
37
+ return false;
38
+ }, [disabledStatus]);
39
+ const canToggle = disabledStatus !== null && disabledStatus.canUpdate;
40
+ const onToggle = (0, react_1.useCallback)((type) => {
41
+ if (!canToggle) {
42
+ return;
43
+ }
44
+ const newValue = type !== 'enable';
45
+ const fieldSchema = effectSchema.disabled;
46
+ const defaultValue = fieldSchema && fieldSchema.type === 'boolean'
47
+ ? JSON.stringify(fieldSchema.default)
48
+ : null;
49
+ (0, save_effect_prop_1.saveEffectProp)({
50
+ fileName: validatedLocation.source,
51
+ nodePath,
52
+ effectIndex,
53
+ fieldKey: 'disabled',
54
+ value: newValue,
55
+ defaultValue,
56
+ schema: effectSchema,
57
+ setCodeValues,
58
+ });
59
+ }, [
60
+ canToggle,
61
+ effectIndex,
62
+ effectSchema,
63
+ nodePath,
64
+ setCodeValues,
65
+ validatedLocation.source,
66
+ ]);
67
+ const isExpanded = getIsExpanded(nodePathInfo);
68
+ const mergedStyle = (0, react_1.useMemo)(() => ({ ...groupRowBase, ...style }), [style]);
69
+ return (jsx_runtime_1.jsxs("div", { style: mergedStyle, children: [
70
+ jsx_runtime_1.jsx(Padder_1.Padder, { depth: nestedDepth + 1 }), canToggle ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: "effect", hidden: isDisabled, onInvoked: onToggle })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: () => toggleTrack(nodePathInfo), label: `${label} section`, disabled: false }), jsx_runtime_1.jsx("span", { style: rowLabel, children: label })
71
+ ] }));
72
+ };
73
+ exports.TimelineEffectGroupRow = TimelineEffectGroupRow;
@@ -6,6 +6,7 @@ const react_1 = require("react");
6
6
  const timeline_layout_1 = require("../../helpers/timeline-layout");
7
7
  const Padder_1 = require("./Padder");
8
8
  const TimelineEffectFieldRow_1 = require("./TimelineEffectFieldRow");
9
+ const TimelineEffectGroupRow_1 = require("./TimelineEffectGroupRow");
9
10
  const TimelineExpandArrowButton_1 = require("./TimelineExpandArrowButton");
10
11
  const TimelineFieldRow_1 = require("./TimelineFieldRow");
11
12
  const TimelineListItem_1 = require("./TimelineListItem");
@@ -34,6 +35,9 @@ const TimelineExpandedRow = ({ node, depth, nestedDepth, getIsExpanded, toggleTr
34
35
  paddingLeft,
35
36
  }), [node, paddingLeft]);
36
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
+ }
37
41
  const isExpanded = getIsExpanded(node.nodePathInfo);
38
42
  return (jsx_runtime_1.jsxs("div", { style: groupStyle, children: [
39
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 })
@@ -2,13 +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
- const NotificationCenter_1 = require("../Notifications/NotificationCenter");
11
8
  const Padder_1 = require("./Padder");
9
+ const save_sequence_prop_1 = require("./save-sequence-prop");
12
10
  const TimelineSchemaField_1 = require("./TimelineSchemaField");
13
11
  const fieldRowBase = {
14
12
  display: 'flex',
@@ -59,46 +57,14 @@ const Value = ({ field, nodePath, validatedLocation, schema, codeValue }) => {
59
57
  codeValue.codeValue === undefined) {
60
58
  return Promise.resolve();
61
59
  }
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
- });
73
- return (0, call_api_1.callApi)('/api/save-sequence-props', {
60
+ return (0, save_sequence_prop_1.saveSequenceProp)({
74
61
  fileName: validatedLocation.source,
75
62
  nodePath,
76
- key: field.key,
77
- value: stringifiedValue,
63
+ fieldKey: field.key,
64
+ value,
78
65
  defaultValue,
79
66
  schema,
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);
67
+ setCodeValues,
102
68
  });
103
69
  }, [
104
70
  codeValue,
@@ -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.sequenceSubscriptionKey) !== 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 ||
@@ -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,8 +226,13 @@ 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 &&
@@ -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;
@@ -0,0 +1,12 @@
1
+ import type { CanUpdateSequencePropsResponse, SequencePropsSubscriptionKey } from 'remotion';
2
+ type SetCodeValues = (nodePath: SequencePropsSubscriptionKey, values: (prev: CanUpdateSequencePropsResponse) => CanUpdateSequencePropsResponse) => void;
3
+ export type EnqueueSaveOptions<TResponse> = {
4
+ nodePath: SequencePropsSubscriptionKey;
5
+ setCodeValues: SetCodeValues;
6
+ applyOptimistic: (prev: CanUpdateSequencePropsResponse) => CanUpdateSequencePropsResponse;
7
+ apiCall: () => Promise<TResponse>;
8
+ mergeServerResponse: (prev: CanUpdateSequencePropsResponse, response: TResponse) => CanUpdateSequencePropsResponse;
9
+ errorLabel: string;
10
+ };
11
+ export declare const enqueueSavePropChange: <TResponse>({ nodePath, setCodeValues, applyOptimistic, apiCall, mergeServerResponse, errorLabel, }: EnqueueSaveOptions<TResponse>) => Promise<void>;
12
+ export {};