@remotion/studio-server 4.0.482 → 4.0.484

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.
@@ -82,6 +82,16 @@ const makeEasingExpression = ({ easing, easingLocalName, }) => {
82
82
  b.objectProperty(b.identifier('damping'), (0, update_nested_prop_1.parseValueExpression)(easing.damping)),
83
83
  b.objectProperty(b.identifier('mass'), (0, update_nested_prop_1.parseValueExpression)(easing.mass)),
84
84
  b.objectProperty(b.identifier('stiffness'), (0, update_nested_prop_1.parseValueExpression)(easing.stiffness)),
85
+ ...(easing.allowTail === null
86
+ ? []
87
+ : [
88
+ b.objectProperty(b.identifier('allowTail'), b.booleanLiteral(easing.allowTail)),
89
+ ]),
90
+ ...(easing.durationRestThreshold === null
91
+ ? []
92
+ : [
93
+ b.objectProperty(b.identifier('durationRestThreshold'), (0, update_nested_prop_1.parseValueExpression)(easing.durationRestThreshold)),
94
+ ]),
85
95
  b.objectProperty(b.identifier('overshootClamping'), b.booleanLiteral(easing.overshootClamping)),
86
96
  ]),
87
97
  ]);
@@ -340,6 +340,16 @@ const createEasingExpression = (easing) => {
340
340
  b.objectProperty(b.identifier('damping'), (0, update_nested_prop_1.parseValueExpression)(easing.damping)),
341
341
  b.objectProperty(b.identifier('mass'), (0, update_nested_prop_1.parseValueExpression)(easing.mass)),
342
342
  b.objectProperty(b.identifier('stiffness'), (0, update_nested_prop_1.parseValueExpression)(easing.stiffness)),
343
+ ...(easing.allowTail === null
344
+ ? []
345
+ : [
346
+ b.objectProperty(b.identifier('allowTail'), b.booleanLiteral(easing.allowTail)),
347
+ ]),
348
+ ...(easing.durationRestThreshold === null
349
+ ? []
350
+ : [
351
+ b.objectProperty(b.identifier('durationRestThreshold'), (0, update_nested_prop_1.parseValueExpression)(easing.durationRestThreshold)),
352
+ ]),
343
353
  b.objectProperty(b.identifier('overshootClamping'), b.booleanLiteral(easing.overshootClamping)),
344
354
  ]),
345
355
  ]);
@@ -371,7 +381,7 @@ const getInlineOptionsFromExtraArgs = (extraArgs) => {
371
381
  }
372
382
  return existingOptions;
373
383
  };
374
- const normalizeEasingAfterAddingKeyframe = ({ extraArgs, previousSegmentCount, nextSegmentCount, }) => {
384
+ const normalizeEasingAfterAddingKeyframe = ({ extraArgs, previousSegmentCount, nextSegmentCount, insertedKeyframeIndex, nextKeyframeCount, }) => {
375
385
  const options = getInlineOptionsFromExtraArgs(extraArgs);
376
386
  if (!options) {
377
387
  return { extraArgs, needsEasingImport: false };
@@ -383,6 +393,16 @@ const normalizeEasingAfterAddingKeyframe = ({ extraArgs, previousSegmentCount, n
383
393
  if (easing === null) {
384
394
  return { extraArgs, needsEasingImport: false };
385
395
  }
396
+ if (easing.length < nextSegmentCount) {
397
+ const isSplittingExistingSegment = insertedKeyframeIndex > 0 &&
398
+ insertedKeyframeIndex < nextKeyframeCount - 1;
399
+ const easingIndexToDuplicate = isSplittingExistingSegment && easing.length > 0
400
+ ? Math.min(insertedKeyframeIndex - 1, easing.length - 1)
401
+ : null;
402
+ easing.splice(insertedKeyframeIndex, 0, easingIndexToDuplicate === null
403
+ ? studio_shared_1.LINEAR_KEYFRAME_EASING
404
+ : easing[easingIndexToDuplicate]);
405
+ }
386
406
  while (easing.length < nextSegmentCount) {
387
407
  easing.push(studio_shared_1.LINEAR_KEYFRAME_EASING);
388
408
  }
@@ -391,6 +411,15 @@ const normalizeEasingAfterAddingKeyframe = ({ extraArgs, previousSegmentCount, n
391
411
  needsEasingImport: setEasingOption({ options, easing }),
392
412
  };
393
413
  };
414
+ const getEasingIndexToRemove = ({ removedKeyframeIndex, keyframeCountBeforeRemoval, }) => {
415
+ if (removedKeyframeIndex === 0) {
416
+ return 0;
417
+ }
418
+ if (removedKeyframeIndex === keyframeCountBeforeRemoval - 1) {
419
+ return removedKeyframeIndex - 1;
420
+ }
421
+ return removedKeyframeIndex;
422
+ };
394
423
  const normalizeEasingAfterRemovingKeyframe = ({ extraArgs, previousSegmentCount, nextSegmentCount, removedKeyframeIndex, }) => {
395
424
  const options = getInlineOptionsFromExtraArgs(extraArgs);
396
425
  if (!options) {
@@ -404,7 +433,10 @@ const normalizeEasingAfterRemovingKeyframe = ({ extraArgs, previousSegmentCount,
404
433
  return { extraArgs, needsEasingImport: false };
405
434
  }
406
435
  if (easing.length > 0) {
407
- const easingIndexToRemove = removedKeyframeIndex === 0 ? 0 : removedKeyframeIndex - 1;
436
+ const easingIndexToRemove = getEasingIndexToRemove({
437
+ removedKeyframeIndex,
438
+ keyframeCountBeforeRemoval: previousSegmentCount + 1,
439
+ });
408
440
  easing.splice(easingIndexToRemove, 1);
409
441
  }
410
442
  while (easing.length > nextSegmentCount) {
@@ -430,11 +462,21 @@ const normalizeEasingAfterRemovingKeyframes = ({ extraArgs, previousSegmentCount
430
462
  if (easing === null) {
431
463
  return { extraArgs, needsEasingImport: false };
432
464
  }
433
- for (const removedKeyframeIndex of [...removedKeyframeIndexes].sort((first, second) => second - first)) {
465
+ for (const { removedKeyframeIndex, keyframeCountBeforeRemoval } of [
466
+ ...removedKeyframeIndexes,
467
+ ]
468
+ .sort((first, second) => second - first)
469
+ .map((keyframeIndex, index) => ({
470
+ removedKeyframeIndex: keyframeIndex,
471
+ keyframeCountBeforeRemoval: previousSegmentCount + 1 - index,
472
+ }))) {
434
473
  if (easing.length === 0) {
435
474
  break;
436
475
  }
437
- const easingIndexToRemove = removedKeyframeIndex === 0 ? 0 : removedKeyframeIndex - 1;
476
+ const easingIndexToRemove = getEasingIndexToRemove({
477
+ removedKeyframeIndex,
478
+ keyframeCountBeforeRemoval,
479
+ });
438
480
  easing.splice(easingIndexToRemove, 1);
439
481
  }
440
482
  while (easing.length > nextSegmentCount) {
@@ -587,6 +629,10 @@ const addKeyframe = ({ expression, key, frame, value, schema, }) => {
587
629
  extraArgs: existing.extraArgs,
588
630
  previousSegmentCount: Math.max(existing.keyframes.length - 1, 0),
589
631
  nextSegmentCount: Math.max(nextKeyframes.length - 1, 0),
632
+ insertedKeyframeIndex: [...nextKeyframes]
633
+ .sort((first, second) => first.frame - second.frame)
634
+ .findIndex((keyframe) => keyframe.frame === frame),
635
+ nextKeyframeCount: nextKeyframes.length,
590
636
  })
591
637
  : { extraArgs: existing.extraArgs, needsEasingImport: false };
592
638
  return {
@@ -1,21 +1,38 @@
1
- import { type InsertableCompositionElement } from '@remotion/studio-shared';
1
+ import { type InsertableCompositionElement, type InsertableCompositionElementPosition } from '@remotion/studio-shared';
2
2
  export type ResolvedCompositionComponent = {
3
3
  source: string;
4
4
  line: number;
5
5
  column: number;
6
6
  canAddSequence: boolean;
7
7
  };
8
+ export type ResolvedCompositionComponentWithFile = ResolvedCompositionComponent & {
9
+ fileName: string;
10
+ exportName: string | 'default';
11
+ };
12
+ export declare const resolveCompositionComponentWithFile: ({ remotionRoot, compositionFile, compositionId, }: {
13
+ remotionRoot: string;
14
+ compositionFile: string;
15
+ compositionId: string;
16
+ }) => Promise<ResolvedCompositionComponentWithFile>;
8
17
  export declare const resolveCompositionComponent: ({ remotionRoot, compositionFile, compositionId, }: {
9
18
  remotionRoot: string;
10
19
  compositionFile: string;
11
20
  compositionId: string;
12
21
  }) => Promise<ResolvedCompositionComponent>;
13
- export declare const insertJsxElementIntoComposition: ({ remotionRoot, compositionFile, compositionId, element, prettierConfigOverride, }: {
22
+ export declare const insertJsxElementIntoComposition: ({ remotionRoot, compositionFile, compositionId, element, prettierConfigOverride, wrapInSequence, }: {
14
23
  remotionRoot: string;
15
24
  compositionFile: string;
16
25
  compositionId: string;
17
26
  element: InsertableCompositionElement;
18
27
  prettierConfigOverride: Record<string, unknown> | null;
28
+ wrapInSequence?: {
29
+ dimensions: {
30
+ width: number;
31
+ height: number;
32
+ };
33
+ name: string | null;
34
+ position: InsertableCompositionElementPosition | null;
35
+ } | null | undefined;
19
36
  }) => Promise<{
20
37
  fileName: string;
21
38
  source: string;
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.insertJsxElementIntoComposition = exports.resolveCompositionComponent = void 0;
39
+ exports.insertJsxElementIntoComposition = exports.resolveCompositionComponent = exports.resolveCompositionComponentWithFile = void 0;
40
40
  const node_fs_1 = __importDefault(require("node:fs"));
41
41
  const node_path_1 = __importDefault(require("node:path"));
42
42
  const studio_shared_1 = require("@remotion/studio-shared");
@@ -570,12 +570,22 @@ const createSolidElement = ({ localName, width, height, position, }) => {
570
570
  createPositionAbsoluteStyleAttribute(position),
571
571
  ], true), null, []);
572
572
  };
573
- const createComponentElement = ({ localName, props, position, }) => {
573
+ const createComponentElement = ({ addPositionStyle, localName, props, position, }) => {
574
574
  return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
575
575
  ...props.map(createComponentProp),
576
- createPositionAbsoluteStyleAttribute(position),
576
+ ...(addPositionStyle
577
+ ? [createPositionAbsoluteStyleAttribute(position)]
578
+ : []),
577
579
  ], true), null, []);
578
580
  };
581
+ const createSequenceWrappedElement = ({ child, dimensions, name, position, sequenceLocalName, }) => {
582
+ return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(sequenceLocalName), [
583
+ ...(name === null ? [] : [createStringAttribute('name', name)]),
584
+ createNumberAttribute('width', dimensions.width),
585
+ createNumberAttribute('height', dimensions.height),
586
+ createPositionAbsoluteStyleAttribute(position),
587
+ ], false), recast.types.builders.jsxClosingElement(recast.types.builders.jsxIdentifier(sequenceLocalName)), [child]);
588
+ };
579
589
  const createAssetElement = ({ addPositionStyle, localName, staticFileLocalName, src, dimensions, position, }) => {
580
590
  return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
581
591
  staticFileLocalName === null
@@ -691,6 +701,24 @@ const ensureSolidImport = (ast) => {
691
701
  localName: getAvailableSolidLocalName(ast),
692
702
  });
693
703
  };
704
+ const getAvailableSequenceLocalName = (ast) => {
705
+ const candidates = ['Sequence', 'RemotionSequence'];
706
+ const available = candidates.find((candidate) => {
707
+ return !hasTopLevelBinding({ ast, name: candidate });
708
+ });
709
+ if (!available) {
710
+ throw new Error('Cannot add <Sequence> because Sequence is already defined');
711
+ }
712
+ return available;
713
+ };
714
+ const ensureSequenceImport = (ast) => {
715
+ return (0, imports_1.ensureNamedImport)({
716
+ ast,
717
+ importedName: 'Sequence',
718
+ sourcePath: 'remotion',
719
+ localName: getAvailableSequenceLocalName(ast),
720
+ });
721
+ };
694
722
  const getImportDeclarations = ({ ast, sourcePath, }) => {
695
723
  return ast.program.body.filter((node) => node.type === 'ImportDeclaration' &&
696
724
  node.source.type === 'StringLiteral' &&
@@ -1018,8 +1046,9 @@ const resolveCompositionComponentWithFile = async ({ remotionRoot, compositionFi
1018
1046
  visited: new Set(),
1019
1047
  });
1020
1048
  };
1049
+ exports.resolveCompositionComponentWithFile = resolveCompositionComponentWithFile;
1021
1050
  const resolveCompositionComponent = async ({ remotionRoot, compositionFile, compositionId, }) => {
1022
- const { source, line, column, canAddSequence } = await resolveCompositionComponentWithFile({
1051
+ const { source, line, column, canAddSequence } = await (0, exports.resolveCompositionComponentWithFile)({
1023
1052
  remotionRoot,
1024
1053
  compositionFile,
1025
1054
  compositionId,
@@ -1032,7 +1061,7 @@ const resolveCompositionComponent = async ({ remotionRoot, compositionFile, comp
1032
1061
  };
1033
1062
  };
1034
1063
  exports.resolveCompositionComponent = resolveCompositionComponent;
1035
- const createInsertableJsxElement = ({ ast, element, }) => {
1064
+ const createInsertableJsxElement = ({ addPositionStyleToComponent, ast, element, }) => {
1036
1065
  if (element.type === 'solid') {
1037
1066
  const solidLocalName = ensureSolidImport(ast);
1038
1067
  return createSolidElement({
@@ -1050,6 +1079,7 @@ const createInsertableJsxElement = ({ ast, element, }) => {
1050
1079
  importPath: element.importPath,
1051
1080
  });
1052
1081
  return createComponentElement({
1082
+ addPositionStyle: addPositionStyleToComponent,
1053
1083
  localName: componentLocalName,
1054
1084
  props: element.props,
1055
1085
  position: element.position,
@@ -1090,8 +1120,8 @@ const createInsertableJsxElement = ({ ast, element, }) => {
1090
1120
  }
1091
1121
  throw new Error('Unsupported element type');
1092
1122
  };
1093
- const insertJsxElementIntoComposition = async ({ remotionRoot, compositionFile, compositionId, element, prettierConfigOverride, }) => {
1094
- const location = await resolveCompositionComponentWithFile({
1123
+ const insertJsxElementIntoComposition = async ({ remotionRoot, compositionFile, compositionId, element, prettierConfigOverride, wrapInSequence = null, }) => {
1124
+ const location = await (0, exports.resolveCompositionComponentWithFile)({
1095
1125
  remotionRoot,
1096
1126
  compositionFile,
1097
1127
  compositionId,
@@ -1104,11 +1134,24 @@ const insertJsxElementIntoComposition = async ({ remotionRoot, compositionFile,
1104
1134
  fileName: location.fileName,
1105
1135
  });
1106
1136
  const ast = (0, parse_ast_1.parseAst)(input);
1107
- const elementToInsert = createInsertableJsxElement({ ast, element });
1137
+ const elementToInsert = createInsertableJsxElement({
1138
+ addPositionStyleToComponent: wrapInSequence === null,
1139
+ ast,
1140
+ element,
1141
+ });
1142
+ const finalElementToInsert = wrapInSequence
1143
+ ? createSequenceWrappedElement({
1144
+ child: elementToInsert,
1145
+ dimensions: wrapInSequence.dimensions,
1146
+ name: wrapInSequence.name,
1147
+ position: wrapInSequence.position,
1148
+ sequenceLocalName: ensureSequenceImport(ast),
1149
+ })
1150
+ : elementToInsert;
1108
1151
  const logLine = addElementToComponentRoot({
1109
1152
  ast,
1110
1153
  exportName: location.exportName,
1111
- element: elementToInsert,
1154
+ element: finalElementToInsert,
1112
1155
  });
1113
1156
  const finalFile = (0, parse_ast_1.serializeAst)(ast);
1114
1157
  const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
@@ -17,6 +17,7 @@ const delete_static_file_1 = require("./routes/delete-static-file");
17
17
  const download_remote_asset_1 = require("./routes/download-remote-asset");
18
18
  const duplicate_effect_1 = require("./routes/duplicate-effect");
19
19
  const duplicate_jsx_node_1 = require("./routes/duplicate-jsx-node");
20
+ const insert_element_1 = require("./routes/insert-element");
20
21
  const insert_jsx_element_1 = require("./routes/insert-jsx-element");
21
22
  const install_dependency_1 = require("./routes/install-dependency");
22
23
  const log_studio_error_1 = require("./routes/log-studio-error");
@@ -88,6 +89,7 @@ exports.allApiRoutes = {
88
89
  '/api/restart-studio': restart_studio_1.handleRestartStudio,
89
90
  '/api/install-package': install_dependency_1.handleInstallPackage,
90
91
  '/api/insert-jsx-element': insert_jsx_element_1.insertJsxElementHandler,
92
+ '/api/insert-element': insert_element_1.insertElementHandler,
91
93
  '/api/download-remote-asset': download_remote_asset_1.downloadRemoteAssetHandler,
92
94
  '/api/undo': undo_1.undoHandler,
93
95
  '/api/redo': redo_1.redoHandler,
@@ -0,0 +1,3 @@
1
+ import { type InsertElementRequest, type InsertElementResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const insertElementHandler: ApiHandler<InsertElementRequest, InsertElementResponse>;
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.insertElementHandler = void 0;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const renderer_1 = require("@remotion/renderer");
10
+ const studio_shared_1 = require("@remotion/studio-shared");
11
+ const file_watcher_1 = require("../../file-watcher");
12
+ const resolve_composition_component_1 = require("../../helpers/resolve-composition-component");
13
+ const format_log_file_location_1 = require("../format-log-file-location");
14
+ const undo_stack_1 = require("../undo-stack");
15
+ const log_update_1 = require("./log-updates/log-update");
16
+ const save_props_mutex_1 = require("./save-props-mutex");
17
+ const validatePosition = (position) => {
18
+ if (position === null) {
19
+ return;
20
+ }
21
+ if (!Number.isFinite(position.x) || !Number.isFinite(position.y)) {
22
+ throw new Error('Position must be finite');
23
+ }
24
+ };
25
+ const isInside = ({ child, parent }) => {
26
+ const relative = node_path_1.default.relative(parent, child);
27
+ return (relative === '' ||
28
+ (!relative.startsWith('..') && !node_path_1.default.isAbsolute(relative)));
29
+ };
30
+ const withoutTsxExtension = (fileName) => {
31
+ return fileName.replace(/\.tsx$/, '');
32
+ };
33
+ const normalizeSourceForComparison = (source) => {
34
+ return source.replace(/\r\n/g, '\n').trim();
35
+ };
36
+ const makeRelativeImportPath = ({ fromFile, toFile, }) => {
37
+ const withoutExtension = withoutTsxExtension(toFile);
38
+ let relative = node_path_1.default
39
+ .relative(node_path_1.default.dirname(fromFile), withoutExtension)
40
+ .split(node_path_1.default.sep)
41
+ .join('/');
42
+ if (!relative.startsWith('.')) {
43
+ relative = `./${relative}`;
44
+ }
45
+ return relative;
46
+ };
47
+ const validateDimensions = (dimensions) => {
48
+ if (!Number.isFinite(dimensions.width) ||
49
+ !Number.isFinite(dimensions.height) ||
50
+ dimensions.width <= 0 ||
51
+ dimensions.height <= 0) {
52
+ throw new Error('Element dimensions must be positive finite numbers');
53
+ }
54
+ };
55
+ const validateElement = (element) => {
56
+ if ((0, studio_shared_1.makeElementFileNameFromSlug)(element.slug) === null) {
57
+ throw new Error('Element slug must produce a safe lowercase .tsx file name');
58
+ }
59
+ if (typeof element.sourceCode !== 'string' ||
60
+ element.sourceCode.trim().length === 0 ||
61
+ element.sourceCode.length > 200000) {
62
+ throw new Error('Unsupported Element source code');
63
+ }
64
+ if ((0, studio_shared_1.getElementComponentNameFromSourceCode)(element.sourceCode) === null) {
65
+ throw new Error('Element source must export exactly one named component');
66
+ }
67
+ validateDimensions(element.dimensions);
68
+ };
69
+ const insertElementHandler = ({ input: { compositionFile, compositionId, element, position }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
70
+ try {
71
+ validateElement(element);
72
+ validatePosition(position);
73
+ const componentName = (0, studio_shared_1.getElementComponentNameFromSourceCode)(element.sourceCode);
74
+ if (componentName === null) {
75
+ throw new Error('Element source must export exactly one named component');
76
+ }
77
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[insert-element] Received request for compositionFile="${compositionFile}" compositionId="${compositionId}" element="${element.slug}"`);
78
+ const location = await (0, resolve_composition_component_1.resolveCompositionComponentWithFile)({
79
+ remotionRoot,
80
+ compositionFile,
81
+ compositionId,
82
+ });
83
+ if (!location.canAddSequence) {
84
+ throw new Error('Cannot insert Element into this composition component');
85
+ }
86
+ const derivedElementFileName = (0, studio_shared_1.makeElementFileNameFromSlug)(element.slug);
87
+ if (derivedElementFileName === null) {
88
+ throw new Error('Element slug must produce a safe lowercase .tsx file name');
89
+ }
90
+ const elementFileName = node_path_1.default.resolve(node_path_1.default.dirname(location.fileName), derivedElementFileName);
91
+ if (!isInside({ child: elementFileName, parent: remotionRoot })) {
92
+ throw new Error('Element file must stay inside the Remotion project');
93
+ }
94
+ const elementFileExists = (0, node_fs_1.existsSync)(elementFileName);
95
+ if (elementFileExists) {
96
+ const existingSource = (0, node_fs_1.readFileSync)(elementFileName, 'utf-8');
97
+ if (normalizeSourceForComparison(existingSource) !==
98
+ normalizeSourceForComparison(element.sourceCode)) {
99
+ throw new Error(`Element file already exists with different contents: ${derivedElementFileName}`);
100
+ }
101
+ }
102
+ const importPath = makeRelativeImportPath({
103
+ fromFile: location.fileName,
104
+ toFile: elementFileName,
105
+ });
106
+ const inserted = await (0, resolve_composition_component_1.insertJsxElementIntoComposition)({
107
+ remotionRoot,
108
+ compositionFile,
109
+ compositionId,
110
+ element: {
111
+ type: 'component',
112
+ componentName,
113
+ importName: componentName,
114
+ importPath,
115
+ props: [],
116
+ position: null,
117
+ },
118
+ prettierConfigOverride: null,
119
+ wrapInSequence: {
120
+ dimensions: element.dimensions,
121
+ name: element.displayName,
122
+ position,
123
+ },
124
+ });
125
+ (0, undo_stack_1.pushTransactionToUndoStack)({
126
+ snapshots: [
127
+ ...(elementFileExists
128
+ ? []
129
+ : [
130
+ {
131
+ filePath: elementFileName,
132
+ oldContents: null,
133
+ newContents: element.sourceCode,
134
+ logLine: 1,
135
+ },
136
+ ]),
137
+ {
138
+ filePath: inserted.fileName,
139
+ oldContents: inserted.oldContents,
140
+ newContents: inserted.output,
141
+ logLine: inserted.logLine,
142
+ },
143
+ ],
144
+ logLevel,
145
+ remotionRoot,
146
+ description: {
147
+ undoMessage: `↩️ Added ${element.displayName}`,
148
+ redoMessage: `↪️ Added ${element.displayName}`,
149
+ },
150
+ entryType: 'insert-jsx-element',
151
+ suppressHmrOnFileRestore: false,
152
+ });
153
+ if (!elementFileExists) {
154
+ (0, undo_stack_1.suppressUndoStackInvalidation)(elementFileName);
155
+ }
156
+ (0, undo_stack_1.suppressUndoStackInvalidation)(inserted.fileName);
157
+ if (!elementFileExists) {
158
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(elementFileName, element.sourceCode, undefined);
159
+ }
160
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(inserted.fileName, inserted.output, undefined);
161
+ const compositionLocationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
162
+ remotionRoot,
163
+ absolutePath: inserted.fileName,
164
+ line: inserted.logLine,
165
+ });
166
+ const elementLocationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
167
+ remotionRoot,
168
+ absolutePath: elementFileName,
169
+ line: 1,
170
+ });
171
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(elementLocationLabel)} ${elementFileExists ? 'Reused existing Element source' : 'Created Element source'}`);
172
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(compositionLocationLabel)} Added <${componentName}>`);
173
+ if (!inserted.formatted) {
174
+ (0, log_update_1.warnAboutPrettierOnce)(logLevel);
175
+ }
176
+ (0, undo_stack_1.printUndoHint)(logLevel);
177
+ return {
178
+ success: true,
179
+ };
180
+ }
181
+ catch (err) {
182
+ return {
183
+ success: false,
184
+ reason: err.message,
185
+ stack: err.stack,
186
+ };
187
+ }
188
+ });
189
+ exports.insertElementHandler = insertElementHandler;
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.482",
6
+ "version": "4.0.484",
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.482",
30
+ "remotion": "4.0.484",
31
31
  "recast": "0.23.11",
32
- "@remotion/bundler": "4.0.482",
33
- "@remotion/renderer": "4.0.482",
34
- "@remotion/studio-shared": "4.0.482",
32
+ "@remotion/bundler": "4.0.484",
33
+ "@remotion/renderer": "4.0.484",
34
+ "@remotion/studio-shared": "4.0.484",
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.482",
42
+ "@remotion/eslint-config-internal": "4.0.484",
43
43
  "eslint": "9.19.0",
44
44
  "@types/node": "20.12.14",
45
45
  "@typescript/native-preview": "7.0.0-dev.20260217.1"