@remotion/studio-server 4.0.474 → 4.0.476

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.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.formatAddition = exports.formatDeletion = exports.formatPropDelta = exports.addedPrefixIfNoColor = exports.strikeThroughOrRemovedPrefix = exports.strikeThrough = exports.numberValue = exports.stringValue = exports.punctuation = exports.equals = exports.attrName = exports.bg = exports.fg = exports.colorValue = exports.colorEnabled = void 0;
3
+ exports.formatAddition = exports.formatDeletion = exports.formatPropChangeDelta = exports.formatPropDelta = exports.addedPrefixIfNoColor = exports.strikeThroughOrRemovedPrefix = exports.strikeThrough = exports.inlineAddition = exports.numberValue = exports.stringValue = exports.punctuation = exports.equals = exports.attrName = exports.bg = exports.fg = exports.colorValue = exports.colorEnabled = void 0;
4
4
  const renderer_1 = require("@remotion/renderer");
5
5
  const colorEnabled = () => renderer_1.RenderInternals.chalk.enabled();
6
6
  exports.colorEnabled = colorEnabled;
@@ -35,6 +35,8 @@ const stringValue = (str) => (0, exports.fg)(230, 219, 116, str);
35
35
  exports.stringValue = stringValue;
36
36
  const numberValue = (str) => (0, exports.fg)(174, 129, 255, str);
37
37
  exports.numberValue = numberValue;
38
+ const inlineAddition = (str) => (0, exports.fg)(166, 226, 46, str);
39
+ exports.inlineAddition = inlineAddition;
38
40
  const strikeThrough = (str) => `\u001b[9m\u001b[38;2;255;85;85m${stripAnsi(str)}\u001b[39m\u001b[29m`;
39
41
  exports.strikeThrough = strikeThrough;
40
42
  const strikeThroughOrRemovedPrefix = (str) => (0, exports.colorEnabled)() ? (0, exports.strikeThrough)(str) : 'removed: ' + str;
@@ -49,6 +51,25 @@ const formatSimpleProp = (key, value) => {
49
51
  const formatNestedProp = (parentKey, childKey, value) => {
50
52
  return `${(0, exports.attrName)(parentKey)}${(0, exports.equals)('=')}${(0, exports.punctuation)('{{')}${(0, exports.punctuation)(childKey)}${(0, exports.punctuation)(':')} ${(0, exports.colorValue)(value)}${(0, exports.punctuation)('}}')}`;
51
53
  };
54
+ const formatValueDelta = ({ oldValueString, newValueString, }) => {
55
+ const withoutUnchangedOptions = shortenUnchangedInterpolateOptions({
56
+ oldValueString,
57
+ newValueString,
58
+ });
59
+ const shortened = removeUnchangedInterpolateOptionProperties(withoutUnchangedOptions);
60
+ const inlineDelta = formatInlineAdditionOrRemoval(shortened);
61
+ if (inlineDelta !== null) {
62
+ return inlineDelta;
63
+ }
64
+ return `${(0, exports.colorValue)(shortened.oldValueString)} ${(0, exports.punctuation)('→')} ${(0, exports.colorValue)(shortened.newValueString)}`;
65
+ };
66
+ const formatSimplePropChange = ({ key, oldValueString, newValueString, }) => {
67
+ return `${(0, exports.attrName)(key)}${(0, exports.equals)('=')}${(0, exports.punctuation)('{')}${formatValueDelta({ oldValueString, newValueString })}${(0, exports.punctuation)('}')}`;
68
+ };
69
+ const formatNestedPropChange = ({ key, oldValueString, newValueString, }) => {
70
+ const dotIdx = key.indexOf('.');
71
+ return `${(0, exports.attrName)(key.slice(0, dotIdx))}${(0, exports.equals)('=')}${(0, exports.punctuation)('{{')}${(0, exports.punctuation)(key.slice(dotIdx + 1))}${(0, exports.punctuation)(':')} ${formatValueDelta({ oldValueString, newValueString })}${(0, exports.punctuation)('}}')}`;
72
+ };
52
73
  const formatPropDelta = ({ key, valueString }) => {
53
74
  const dotIdx = key.indexOf('.');
54
75
  if (dotIdx === -1) {
@@ -57,6 +78,14 @@ const formatPropDelta = ({ key, valueString }) => {
57
78
  return formatNestedProp(key.slice(0, dotIdx), key.slice(dotIdx + 1), valueString);
58
79
  };
59
80
  exports.formatPropDelta = formatPropDelta;
81
+ const formatPropChangeDelta = ({ key, oldValueString, newValueString, }) => {
82
+ const dotIdx = key.indexOf('.');
83
+ if (dotIdx === -1) {
84
+ return formatSimplePropChange({ key, oldValueString, newValueString });
85
+ }
86
+ return formatNestedPropChange({ key, oldValueString, newValueString });
87
+ };
88
+ exports.formatPropChangeDelta = formatPropChangeDelta;
60
89
  const formatDeletion = (prop) => {
61
90
  const formatted = (0, exports.formatPropDelta)(prop);
62
91
  return (0, exports.strikeThroughOrRemovedPrefix)(formatted);
@@ -67,3 +96,229 @@ const formatAddition = (prop) => {
67
96
  return (0, exports.addedPrefixIfNoColor)(formatted);
68
97
  };
69
98
  exports.formatAddition = formatAddition;
99
+ const callStart = 'interpolate(';
100
+ const normalizeArg = (arg) => {
101
+ return arg
102
+ .replace(/\s+/g, ' ')
103
+ .replace(/,(\s*[}\]])/g, '$1')
104
+ .trim();
105
+ };
106
+ const shortenUnchangedOptionProperties = new Set([
107
+ 'extrapolateLeft',
108
+ 'extrapolateRight',
109
+ ]);
110
+ const splitTopLevelArgs = (argsSource) => {
111
+ const args = [];
112
+ let depth = 0;
113
+ let quote = null;
114
+ let start = 0;
115
+ for (let i = 0; i < argsSource.length; i++) {
116
+ const char = argsSource[i];
117
+ const previous = argsSource[i - 1];
118
+ if (quote) {
119
+ if (char === quote && previous !== '\\') {
120
+ quote = null;
121
+ }
122
+ continue;
123
+ }
124
+ if (char === "'" || char === '"' || char === '`') {
125
+ quote = char;
126
+ continue;
127
+ }
128
+ if (char === '(' || char === '[' || char === '{') {
129
+ depth++;
130
+ continue;
131
+ }
132
+ if (char === ')' || char === ']' || char === '}') {
133
+ depth--;
134
+ continue;
135
+ }
136
+ if (char === ',' && depth === 0) {
137
+ args.push(argsSource.slice(start, i).trim());
138
+ start = i + 1;
139
+ }
140
+ }
141
+ args.push(argsSource.slice(start).trim());
142
+ return args;
143
+ };
144
+ const getCommonPrefixLength = (oldValueString, newValueString) => {
145
+ const maxLength = Math.min(oldValueString.length, newValueString.length);
146
+ let index = 0;
147
+ while (index < maxLength && oldValueString[index] === newValueString[index]) {
148
+ index++;
149
+ }
150
+ return index;
151
+ };
152
+ const getCommonSuffixLength = ({ oldValueString, newValueString, prefixLength, }) => {
153
+ const maxLength = Math.min(oldValueString.length, newValueString.length) - prefixLength;
154
+ let index = 0;
155
+ while (index < maxLength &&
156
+ oldValueString[oldValueString.length - 1 - index] ===
157
+ newValueString[newValueString.length - 1 - index]) {
158
+ index++;
159
+ }
160
+ return index;
161
+ };
162
+ const minSharedInlineDeltaChars = 12;
163
+ const formatInlineAdditionOrRemoval = ({ oldValueString, newValueString, }) => {
164
+ if (!(0, exports.colorEnabled)()) {
165
+ return null;
166
+ }
167
+ const prefixLength = getCommonPrefixLength(oldValueString, newValueString);
168
+ const suffixLength = getCommonSuffixLength({
169
+ oldValueString,
170
+ newValueString,
171
+ prefixLength,
172
+ });
173
+ if (prefixLength + suffixLength < minSharedInlineDeltaChars) {
174
+ return null;
175
+ }
176
+ const oldMiddleEnd = oldValueString.length - suffixLength;
177
+ const newMiddleEnd = newValueString.length - suffixLength;
178
+ const oldMiddle = oldValueString.slice(prefixLength, oldMiddleEnd);
179
+ const newMiddle = newValueString.slice(prefixLength, newMiddleEnd);
180
+ if (oldMiddle.length === 0 && newMiddle.length > 0) {
181
+ return `${newValueString.slice(0, prefixLength)}${(0, exports.inlineAddition)(newMiddle)}${newValueString.slice(newMiddleEnd)}`;
182
+ }
183
+ if (newMiddle.length === 0 && oldMiddle.length > 0) {
184
+ return `${oldValueString.slice(0, prefixLength)}${(0, exports.strikeThrough)(oldMiddle)}${oldValueString.slice(oldMiddleEnd)}`;
185
+ }
186
+ return null;
187
+ };
188
+ const getObjectPropertyKey = (propertySource) => {
189
+ const colonIndex = propertySource.indexOf(':');
190
+ if (colonIndex === -1) {
191
+ return null;
192
+ }
193
+ const key = propertySource.slice(0, colonIndex).trim();
194
+ if (/^[A-Za-z_$][\w$]*$/.test(key)) {
195
+ return key;
196
+ }
197
+ if ((key.startsWith("'") && key.endsWith("'")) ||
198
+ (key.startsWith('"') && key.endsWith('"'))) {
199
+ return key.slice(1, -1);
200
+ }
201
+ return null;
202
+ };
203
+ const parseTopLevelObjectProperties = (objectSource) => {
204
+ const trimmed = objectSource.trim();
205
+ if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {
206
+ return null;
207
+ }
208
+ const properties = splitTopLevelArgs(trimmed.slice(1, -1))
209
+ .filter(Boolean)
210
+ .map((propertySource) => {
211
+ const key = getObjectPropertyKey(propertySource);
212
+ if (key === null) {
213
+ return null;
214
+ }
215
+ const colonIndex = propertySource.indexOf(':');
216
+ return {
217
+ key,
218
+ value: normalizeArg(propertySource.slice(colonIndex + 1)),
219
+ source: propertySource.trim(),
220
+ };
221
+ });
222
+ if (properties.some((property) => property === null)) {
223
+ return null;
224
+ }
225
+ return properties;
226
+ };
227
+ const parseInterpolateCall = (valueString) => {
228
+ const trimmed = valueString.trim();
229
+ if (!trimmed.startsWith(callStart) || !trimmed.endsWith(')')) {
230
+ return null;
231
+ }
232
+ let depth = 0;
233
+ let quote = null;
234
+ for (let i = 'interpolate'.length; i < trimmed.length; i++) {
235
+ const char = trimmed[i];
236
+ const previous = trimmed[i - 1];
237
+ if (quote) {
238
+ if (char === quote && previous !== '\\') {
239
+ quote = null;
240
+ }
241
+ continue;
242
+ }
243
+ if (char === "'" || char === '"' || char === '`') {
244
+ quote = char;
245
+ continue;
246
+ }
247
+ if (char === '(' || char === '[' || char === '{') {
248
+ depth++;
249
+ continue;
250
+ }
251
+ if (char === ')' || char === ']' || char === '}') {
252
+ depth--;
253
+ if (depth === 0 && i !== trimmed.length - 1) {
254
+ return null;
255
+ }
256
+ }
257
+ }
258
+ if (depth !== 0) {
259
+ return null;
260
+ }
261
+ return {
262
+ args: splitTopLevelArgs(trimmed.slice(callStart.length, -1)),
263
+ };
264
+ };
265
+ const shortenUnchangedInterpolateOptions = ({ oldValueString, newValueString, }) => {
266
+ const oldCall = parseInterpolateCall(oldValueString);
267
+ const newCall = parseInterpolateCall(newValueString);
268
+ if (!oldCall ||
269
+ !newCall ||
270
+ oldCall.args.length <= 3 ||
271
+ newCall.args.length <= 3) {
272
+ return { oldValueString, newValueString };
273
+ }
274
+ const oldOptions = oldCall.args.slice(3).map(normalizeArg);
275
+ const newOptions = newCall.args.slice(3).map(normalizeArg);
276
+ if (oldOptions.length !== newOptions.length ||
277
+ oldOptions.some((option, index) => option !== newOptions[index])) {
278
+ return { oldValueString, newValueString };
279
+ }
280
+ return {
281
+ oldValueString: `interpolate(${oldCall.args.slice(0, 3).join(', ')})`,
282
+ newValueString: `interpolate(${newCall.args.slice(0, 3).join(', ')})`,
283
+ };
284
+ };
285
+ const removeUnchangedInterpolateOptionProperties = ({ oldValueString, newValueString, }) => {
286
+ const oldCall = parseInterpolateCall(oldValueString);
287
+ const newCall = parseInterpolateCall(newValueString);
288
+ if (!oldCall ||
289
+ !newCall ||
290
+ oldCall.args.length <= 3 ||
291
+ newCall.args.length <= 3) {
292
+ return { oldValueString, newValueString };
293
+ }
294
+ const oldProperties = parseTopLevelObjectProperties(oldCall.args[3]);
295
+ const newProperties = parseTopLevelObjectProperties(newCall.args[3]);
296
+ if (!oldProperties || !newProperties) {
297
+ return { oldValueString, newValueString };
298
+ }
299
+ const propertiesToRemove = [...shortenUnchangedOptionProperties].filter((propertyName) => {
300
+ const oldProperty = oldProperties.find((property) => property.key === propertyName);
301
+ const newProperty = newProperties.find((property) => property.key === propertyName);
302
+ return (oldProperty !== undefined &&
303
+ newProperty !== undefined &&
304
+ oldProperty.value === newProperty.value);
305
+ });
306
+ if (propertiesToRemove.length === 0) {
307
+ return { oldValueString, newValueString };
308
+ }
309
+ const removeProperties = (call, properties) => {
310
+ const nextOptions = properties.filter((property) => !propertiesToRemove.includes(property.key));
311
+ const nextArgs = nextOptions.length === 0
312
+ ? [...call.args.slice(0, 3), ...call.args.slice(4)]
313
+ : [
314
+ ...call.args.slice(0, 3),
315
+ `{${nextOptions.map((property) => property.source).join(', ')}}`,
316
+ ...call.args.slice(4),
317
+ ];
318
+ return `interpolate(${nextArgs.join(', ')})`;
319
+ };
320
+ return {
321
+ oldValueString: removeProperties(oldCall, oldProperties),
322
+ newValueString: removeProperties(newCall, newProperties),
323
+ };
324
+ };
@@ -1,3 +1,20 @@
1
- import type { SaveSequencePropsRequest, SaveSequencePropsResponse } from '@remotion/studio-shared';
1
+ import type { SaveSequencePropEdit, SaveSequencePropsRequest, SaveSequencePropsResponse } from '@remotion/studio-shared';
2
+ import { type SequencePropsNodeUpdate } from '../../codemods/update-sequence-props/update-sequence-props';
2
3
  import type { ApiHandler } from '../api-types';
4
+ type ResolvedSequencePropEdit = {
5
+ index: number;
6
+ fileName: SaveSequencePropEdit['fileName'];
7
+ nodePath: SaveSequencePropEdit['nodePath'];
8
+ key: SaveSequencePropEdit['key'];
9
+ value: unknown;
10
+ valueString: string;
11
+ defaultValue: unknown | null;
12
+ defaultValueString: string | null;
13
+ schema: SaveSequencePropEdit['schema'];
14
+ };
15
+ export declare const convertSequencePropEditToCodemodChange: (edit: Pick<ResolvedSequencePropEdit, "defaultValue" | "key" | "nodePath" | "schema" | "value">) => SequencePropsNodeUpdate;
16
+ export declare const shouldSuppressHmrForSequencePropEdits: (edits: readonly {
17
+ key: string;
18
+ }[]) => boolean;
3
19
  export declare const saveSequencePropsHandler: ApiHandler<SaveSequencePropsRequest, SaveSequencePropsResponse>;
20
+ export {};
@@ -1,10 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.saveSequencePropsHandler = void 0;
3
+ exports.saveSequencePropsHandler = exports.shouldSuppressHmrForSequencePropEdits = exports.convertSequencePropEditToCodemodChange = void 0;
4
4
  const node_fs_1 = require("node:fs");
5
5
  const renderer_1 = require("@remotion/renderer");
6
6
  const studio_shared_1 = require("@remotion/studio-shared");
7
- const no_react_1 = require("remotion/no-react");
8
7
  const update_sequence_props_1 = require("../../codemods/update-sequence-props/update-sequence-props");
9
8
  const file_watcher_1 = require("../../file-watcher");
10
9
  const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
@@ -13,6 +12,24 @@ const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
13
12
  const can_update_sequence_props_1 = require("./can-update-sequence-props");
14
13
  const log_update_1 = require("./log-updates/log-update");
15
14
  const save_props_mutex_1 = require("./save-props-mutex");
15
+ const convertSequencePropEditToCodemodChange = (edit) => {
16
+ return {
17
+ nodePath: edit.nodePath.nodePath,
18
+ updates: [
19
+ {
20
+ key: edit.key,
21
+ value: edit.value,
22
+ defaultValue: edit.defaultValue,
23
+ },
24
+ ],
25
+ schema: edit.schema,
26
+ };
27
+ };
28
+ exports.convertSequencePropEditToCodemodChange = convertSequencePropEditToCodemodChange;
29
+ const shouldSuppressHmrForSequencePropEdits = (edits) => {
30
+ return edits.every((edit) => edit.key !== 'showInTimeline');
31
+ };
32
+ exports.shouldSuppressHmrForSequencePropEdits = shouldSuppressHmrForSequencePropEdits;
16
33
  const saveSequencePropsHandler = ({ input: { edits, clientId, undoLabel, redoLabel }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
17
34
  var _a;
18
35
  if (edits.length === 0) {
@@ -54,19 +71,7 @@ const saveSequencePropsHandler = ({ input: { edits, clientId, undoLabel, redoLab
54
71
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
55
72
  const { output, formatted, results: updateResults, } = await (0, update_sequence_props_1.updateMultipleSequenceProps)({
56
73
  input: fileContents,
57
- changes: group.edits.map((edit) => {
58
- return {
59
- nodePath: edit.nodePath.nodePath,
60
- updates: [
61
- {
62
- key: edit.key,
63
- value: edit.value,
64
- defaultValue: edit.defaultValue,
65
- },
66
- ],
67
- schema: no_react_1.NoReactInternals.sequenceSchema,
68
- };
69
- }),
74
+ changes: group.edits.map(exports.convertSequencePropEditToCodemodChange),
70
75
  prettierConfigOverride: null,
71
76
  });
72
77
  const [{ logLine: firstLogLine }] = updateResults;
@@ -89,17 +94,20 @@ const saveSequencePropsHandler = ({ input: { edits, clientId, undoLabel, redoLab
89
94
  }
90
95
  const undoMessage = `↩️ ${undoLabel}`;
91
96
  const redoMessage = `↪️ ${redoLabel}`;
97
+ const suppressHmr = (0, exports.shouldSuppressHmrForSequencePropEdits)(edits);
92
98
  (0, undo_stack_1.pushTransactionToUndoStack)({
93
99
  snapshots,
94
100
  logLevel,
95
101
  remotionRoot,
96
102
  description: { undoMessage, redoMessage },
97
103
  entryType: 'sequence-props',
98
- suppressHmrOnFileRestore: true,
104
+ suppressHmrOnFileRestore: suppressHmr,
99
105
  });
100
106
  for (const [absolutePath, output] of outputByPath) {
101
107
  (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
102
- (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
108
+ if (suppressHmr) {
109
+ (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
110
+ }
103
111
  (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
104
112
  }
105
113
  for (const { edits: groupEdits, fileRelativeToRoot } of editGroups.values()) {
@@ -30,11 +30,17 @@ const updateEffectKeyframeSettingsHandler = ({ input: { fileName, sequenceNodePa
30
30
  updates: [
31
31
  {
32
32
  key,
33
- operation: {
34
- type: 'settings',
35
- clamping: settings.clamping,
36
- posterize: settings.posterize,
37
- },
33
+ operation: settings.type === 'settings'
34
+ ? {
35
+ type: 'settings',
36
+ clamping: settings.clamping,
37
+ posterize: settings.posterize,
38
+ }
39
+ : {
40
+ type: 'easing',
41
+ segmentIndex: settings.segmentIndex,
42
+ easing: settings.easing,
43
+ },
38
44
  },
39
45
  ],
40
46
  });
@@ -27,11 +27,17 @@ const updateSequenceKeyframeSettingsHandler = ({ input: { fileName, nodePath, ke
27
27
  updates: [
28
28
  {
29
29
  key,
30
- operation: {
31
- type: 'settings',
32
- clamping: settings.clamping,
33
- posterize: settings.posterize,
34
- },
30
+ operation: settings.type === 'settings'
31
+ ? {
32
+ type: 'settings',
33
+ clamping: settings.clamping,
34
+ posterize: settings.posterize,
35
+ }
36
+ : {
37
+ type: 'easing',
38
+ segmentIndex: settings.segmentIndex,
39
+ easing: settings.easing,
40
+ },
35
41
  },
36
42
  ],
37
43
  });
@@ -3,7 +3,7 @@ export interface UndoEntryDescription {
3
3
  undoMessage: string;
4
4
  redoMessage: string;
5
5
  }
6
- type UndoEntryType = 'visual-control' | 'default-props' | 'sequence-props' | 'effect-props' | 'keyframe-delete' | 'add-effect' | 'delete-effect' | 'paste-effects' | 'reorder-effect' | 'reorder-sequence' | 'delete-jsx-node' | 'duplicate-jsx-node' | 'insert-jsx-element' | 'delete-composition' | 'rename-composition' | 'duplicate-composition' | 'delete-folder' | 'rename-folder';
6
+ type UndoEntryType = 'visual-control' | 'default-props' | 'sequence-props' | 'effect-props' | 'keyframe-add' | 'keyframe-delete' | 'add-effect' | 'delete-effect' | 'paste-effects' | 'reorder-effect' | 'reorder-sequence' | 'delete-jsx-node' | 'duplicate-jsx-node' | 'insert-jsx-element' | 'delete-composition' | 'rename-composition' | 'duplicate-composition' | 'delete-folder' | 'rename-folder';
7
7
  type UndoEntrySnapshot = {
8
8
  filePath: string;
9
9
  oldContents: string;
@@ -27,6 +27,8 @@ type UndoEntry = {
27
27
  entryType: 'sequence-props';
28
28
  } | {
29
29
  entryType: 'effect-props';
30
+ } | {
31
+ entryType: 'keyframe-add';
30
32
  } | {
31
33
  entryType: 'keyframe-delete';
32
34
  } | {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio-server"
4
4
  },
5
5
  "name": "@remotion/studio-server",
6
- "version": "4.0.474",
6
+ "version": "4.0.476",
7
7
  "description": "Run a Remotion Studio with a server backend",
8
8
  "main": "dist",
9
9
  "scripts": {
@@ -27,11 +27,11 @@
27
27
  "@babel/parser": "7.24.1",
28
28
  "semver": "7.5.3",
29
29
  "prettier": "3.8.1",
30
- "remotion": "4.0.474",
30
+ "remotion": "4.0.476",
31
31
  "recast": "0.23.11",
32
- "@remotion/bundler": "4.0.474",
33
- "@remotion/renderer": "4.0.474",
34
- "@remotion/studio-shared": "4.0.474",
32
+ "@remotion/bundler": "4.0.476",
33
+ "@remotion/renderer": "4.0.476",
34
+ "@remotion/studio-shared": "4.0.476",
35
35
  "memfs": "3.4.3",
36
36
  "open": "8.4.2"
37
37
  },
@@ -39,7 +39,7 @@
39
39
  "ast-types": "0.16.1",
40
40
  "react": "19.2.3",
41
41
  "@types/semver": "7.5.3",
42
- "@remotion/eslint-config-internal": "4.0.474",
42
+ "@remotion/eslint-config-internal": "4.0.476",
43
43
  "eslint": "9.19.0",
44
44
  "@types/node": "20.12.14",
45
45
  "@typescript/native-preview": "7.0.0-dev.20260217.1"