@remotion/studio-server 4.0.507 → 4.0.509

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 (76) hide show
  1. package/dist/canvas-capture/generate-canvas-capture-composition.d.ts +14 -0
  2. package/dist/canvas-capture/generate-canvas-capture-composition.js +174 -0
  3. package/dist/codemods/delete-jsx-node.d.ts +4 -0
  4. package/dist/codemods/delete-jsx-node.js +8 -0
  5. package/dist/codemods/duplicate-composition.js +8 -6
  6. package/dist/codemods/duplicate-jsx-node.d.ts +2 -0
  7. package/dist/codemods/duplicate-jsx-node.js +8 -0
  8. package/dist/codemods/get-node-path-remappings.d.ts +16 -0
  9. package/dist/codemods/get-node-path-remappings.js +88 -0
  10. package/dist/codemods/recast-mods.js +13 -0
  11. package/dist/codemods/reorder-sequence.d.ts +2 -1
  12. package/dist/codemods/reorder-sequence.js +8 -0
  13. package/dist/codemods/split-jsx-sequence.d.ts +2 -0
  14. package/dist/codemods/split-jsx-sequence.js +8 -0
  15. package/dist/codemods/update-keyframes/update-keyframes.js +17 -10
  16. package/dist/file-watcher.d.ts +11 -1
  17. package/dist/file-watcher.js +16 -5
  18. package/dist/helpers/coding-agent-registry.d.ts +0 -1
  19. package/dist/helpers/coding-agent-registry.js +1 -5
  20. package/dist/helpers/finder-artwork.d.ts +1 -0
  21. package/dist/helpers/finder-artwork.js +4 -0
  22. package/dist/helpers/resolve-composition-component.d.ts +4 -1
  23. package/dist/helpers/resolve-composition-component.js +63 -69
  24. package/dist/helpers/terminal-artwork.d.ts +6 -0
  25. package/dist/helpers/terminal-artwork.js +14 -0
  26. package/dist/helpers/terminal-registry.d.ts +36 -0
  27. package/dist/helpers/terminal-registry.js +401 -0
  28. package/dist/index.d.ts +8 -2
  29. package/dist/preview-server/api-routes.js +2 -0
  30. package/dist/preview-server/live-events.d.ts +1 -0
  31. package/dist/preview-server/live-events.js +3 -1
  32. package/dist/preview-server/routes/add-effect-keyframe.js +7 -1
  33. package/dist/preview-server/routes/add-effect.js +7 -1
  34. package/dist/preview-server/routes/add-keyframes.js +10 -2
  35. package/dist/preview-server/routes/add-sequence-keyframe.js +7 -1
  36. package/dist/preview-server/routes/app-icon.d.ts +6 -0
  37. package/dist/preview-server/routes/app-icon.js +66 -0
  38. package/dist/preview-server/routes/apply-codemod.js +34 -5
  39. package/dist/preview-server/routes/apply-visual-control-change.js +7 -1
  40. package/dist/preview-server/routes/batch-update-keyframe-settings.js +10 -2
  41. package/dist/preview-server/routes/can-update-sequence-props.d.ts +1 -0
  42. package/dist/preview-server/routes/can-update-sequence-props.js +5 -4
  43. package/dist/preview-server/routes/default-coding-agent.js +4 -2
  44. package/dist/preview-server/routes/delete-effect.js +7 -1
  45. package/dist/preview-server/routes/delete-jsx-node.js +16 -2
  46. package/dist/preview-server/routes/delete-keyframes.js +10 -2
  47. package/dist/preview-server/routes/duplicate-effect.js +7 -1
  48. package/dist/preview-server/routes/duplicate-jsx-node.js +17 -5
  49. package/dist/preview-server/routes/insert-element.js +23 -3
  50. package/dist/preview-server/routes/insert-jsx-element.js +23 -2
  51. package/dist/preview-server/routes/move-keyframes.js +10 -2
  52. package/dist/preview-server/routes/open-in-terminal.d.ts +3 -0
  53. package/dist/preview-server/routes/open-in-terminal.js +17 -0
  54. package/dist/preview-server/routes/paste-effects.js +7 -1
  55. package/dist/preview-server/routes/reorder-effect.js +7 -1
  56. package/dist/preview-server/routes/reorder-sequence.js +17 -2
  57. package/dist/preview-server/routes/save-effect-props.js +7 -1
  58. package/dist/preview-server/routes/save-multiple-effect-props.js +10 -2
  59. package/dist/preview-server/routes/save-sequence-props.js +29 -5
  60. package/dist/preview-server/routes/split-jsx-sequence.js +17 -6
  61. package/dist/preview-server/routes/update-config.js +6 -1
  62. package/dist/preview-server/routes/update-default-props.js +7 -1
  63. package/dist/preview-server/routes/update-effect-keyframe-settings.js +7 -1
  64. package/dist/preview-server/routes/update-sequence-keyframe-settings.js +7 -1
  65. package/dist/preview-server/sequence-node-path-mutation.d.ts +7 -0
  66. package/dist/preview-server/sequence-node-path-mutation.js +21 -0
  67. package/dist/preview-server/sequence-props-watchers.js +15 -6
  68. package/dist/preview-server/start-server.d.ts +1 -0
  69. package/dist/preview-server/start-server.js +1 -0
  70. package/dist/preview-server/undo-stack.d.ts +7 -13
  71. package/dist/preview-server/undo-stack.js +58 -5
  72. package/dist/routes.d.ts +2 -1
  73. package/dist/routes.js +12 -2
  74. package/dist/start-studio.d.ts +2 -1
  75. package/dist/start-studio.js +2 -1
  76. package/package.json +8 -8
@@ -0,0 +1,14 @@
1
+ import type { CanvasCaptureData } from '@remotion/studio-shared';
2
+ export declare const generateCanvasCaptureComposition: ({ componentName, compositionId, data, durationInFrames, fps, height, keyframeFps, videoFileName, videoHeight, videoWidth, width, }: {
3
+ readonly componentName: string;
4
+ readonly compositionId: string;
5
+ readonly data: CanvasCaptureData;
6
+ readonly durationInFrames: number;
7
+ readonly fps: number;
8
+ readonly height: number;
9
+ readonly keyframeFps: number;
10
+ readonly videoFileName: string;
11
+ readonly videoHeight: number;
12
+ readonly videoWidth: number;
13
+ readonly width: number;
14
+ }) => Promise<string>;
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateCanvasCaptureComposition = void 0;
4
+ const duplicate_composition_1 = require("../codemods/duplicate-composition");
5
+ const customCursorRegex = /^\s*url\(/;
6
+ const collapseMouseMovementsByFrame = ({ data, keyframeFps, }) => {
7
+ const movements = [];
8
+ for (const movement of data.mouseMovements) {
9
+ if (movement.canvasX === null || movement.canvasY === null) {
10
+ continue;
11
+ }
12
+ const framedMovement = {
13
+ ...movement,
14
+ frame: Math.ceil(movement.timeInSeconds * keyframeFps),
15
+ };
16
+ const previous = movements.at(-1);
17
+ if ((previous === null || previous === void 0 ? void 0 : previous.frame) === framedMovement.frame) {
18
+ movements[movements.length - 1] = framedMovement;
19
+ }
20
+ else {
21
+ movements.push(framedMovement);
22
+ }
23
+ }
24
+ return movements;
25
+ };
26
+ const getCursorName = (cursor) => {
27
+ var _a;
28
+ if (customCursorRegex.test(cursor)) {
29
+ return 'custom';
30
+ }
31
+ return ((_a = cursor.split(',').at(-1)) === null || _a === void 0 ? void 0 : _a.trim().toLowerCase()) || 'default';
32
+ };
33
+ const serialize = (value) => JSON.stringify(value);
34
+ const generateCanvasCaptureComposition = ({ componentName, compositionId, data, durationInFrames, fps, height, keyframeFps, videoFileName, videoHeight, videoWidth, width, }) => {
35
+ var _a;
36
+ const movements = collapseMouseMovementsByFrame({ data, keyframeFps });
37
+ if (movements.length === 0) {
38
+ throw new Error('The Canvas Capture does not contain cursor movements');
39
+ }
40
+ const cursorKeyframes = movements.reduce((keyframes, movement) => {
41
+ var _a;
42
+ const value = getCursorName(movement.cursor);
43
+ if (((_a = keyframes.at(-1)) === null || _a === void 0 ? void 0 : _a.value) !== value) {
44
+ keyframes.push({ frame: movement.frame, value });
45
+ }
46
+ return keyframes;
47
+ }, []);
48
+ const positionKeyframes = [];
49
+ for (const movement of movements) {
50
+ const previous = positionKeyframes.at(-1);
51
+ if (previous !== undefined && movement.frame - previous.frame > 1) {
52
+ positionKeyframes.push({
53
+ frame: movement.frame - 1,
54
+ value: previous.value,
55
+ });
56
+ }
57
+ positionKeyframes.push({
58
+ frame: movement.frame,
59
+ value: `${movement.canvasX}px ${movement.canvasY}px`,
60
+ });
61
+ }
62
+ const scaleKeyframes = [
63
+ { frame: 0, value: data.captureMetadata.density },
64
+ ...data.pointerClicks.map((click) => ({
65
+ frame: Math.ceil(click.timeInSeconds * keyframeFps),
66
+ value: click.type === 'pointer-down'
67
+ ? data.captureMetadata.density * 0.9
68
+ : data.captureMetadata.density,
69
+ })),
70
+ ].reduce((keyframes, keyframe) => {
71
+ var _a, _b;
72
+ if (((_a = keyframes.at(-1)) === null || _a === void 0 ? void 0 : _a.frame) === keyframe.frame) {
73
+ keyframes[keyframes.length - 1] = keyframe;
74
+ }
75
+ else if (((_b = keyframes.at(-1)) === null || _b === void 0 ? void 0 : _b.value) !== keyframe.value) {
76
+ keyframes.push(keyframe);
77
+ }
78
+ return keyframes;
79
+ }, []);
80
+ const customCursor = (_a = movements.find((movement) => customCursorRegex.test(movement.cursor))) === null || _a === void 0 ? void 0 : _a.cursor;
81
+ const cursorProp = cursorKeyframes.length === 1
82
+ ? `cursor=${serialize(cursorKeyframes[0].value)}`
83
+ : `cursor={interpolate(
84
+ frame,
85
+ ${serialize(cursorKeyframes.map((keyframe) => keyframe.frame))},
86
+ ${serialize(cursorKeyframes.map((keyframe) => keyframe.value))},
87
+ {
88
+ easing: Easing.step1,
89
+ extrapolateLeft: 'clamp',
90
+ extrapolateRight: 'clamp',
91
+ },
92
+ )}`;
93
+ const scale = scaleKeyframes.length === 1
94
+ ? serialize(scaleKeyframes[0].value)
95
+ : `interpolate(
96
+ frame,
97
+ ${serialize(scaleKeyframes.map((keyframe) => keyframe.frame))},
98
+ ${serialize(scaleKeyframes.map((keyframe) => keyframe.value))},
99
+ {
100
+ easing: Easing.step1,
101
+ extrapolateLeft: 'clamp',
102
+ extrapolateRight: 'clamp',
103
+ },
104
+ )`;
105
+ const translate = positionKeyframes.length === 1
106
+ ? serialize(positionKeyframes[0].value)
107
+ : `interpolate(
108
+ frame,
109
+ ${serialize(positionKeyframes.map((keyframe) => keyframe.frame))},
110
+ ${serialize(positionKeyframes.map((keyframe) => keyframe.value))},
111
+ {
112
+ extrapolateLeft: 'clamp',
113
+ extrapolateRight: 'clamp',
114
+ },
115
+ )`;
116
+ const previewComponentName = componentName.endsWith('Composition')
117
+ ? `${componentName.slice(0, -'Composition'.length)}Preview`
118
+ : `${componentName}Preview`;
119
+ return (0, duplicate_composition_1.formatOutput)(`import {MacOSCursor} from '@remotion/mac-cursors';
120
+ import {Video} from '@remotion/media';
121
+ import {
122
+ AbsoluteFill,
123
+ Composition,
124
+ Easing,
125
+ interpolate,
126
+ staticFile,
127
+ useCurrentFrame,
128
+ } from 'remotion';
129
+
130
+ export const ${previewComponentName} = () => {
131
+ const frame = useCurrentFrame();
132
+
133
+ return (
134
+ <AbsoluteFill
135
+ style={{
136
+ width: ${videoWidth},
137
+ height: ${videoHeight},
138
+ }}
139
+ >
140
+ <Video
141
+ src={staticFile(${serialize(videoFileName)})}
142
+ style={{
143
+ position: 'absolute',
144
+ }}
145
+ />
146
+ <MacOSCursor
147
+ ${cursorProp}
148
+ ${customCursor === undefined ? '' : `\t\t\t\tcustomCursor=${serialize(customCursor)}\n`} style={{
149
+ position: 'absolute',
150
+ left: 0,
151
+ top: 0,
152
+ scale: ${scale},
153
+ translate: ${translate},
154
+ }}
155
+ />
156
+ </AbsoluteFill>
157
+ );
158
+ };
159
+
160
+ export const ${componentName} = () => {
161
+ return (
162
+ <Composition
163
+ id=${serialize(compositionId)}
164
+ component={${previewComponentName}}
165
+ width={${width}}
166
+ height={${height}}
167
+ fps={${fps}}
168
+ durationInFrames={${durationInFrames}}
169
+ />
170
+ );
171
+ };
172
+ `);
173
+ };
174
+ exports.generateCanvasCaptureComposition = generateCanvasCaptureComposition;
@@ -13,6 +13,10 @@ export declare const deleteJsxNodes: ({ input, nodePaths, prettierConfigOverride
13
13
  formatted: boolean;
14
14
  nodeLabels: string[];
15
15
  logLines: number[];
16
+ nodePathRemappings: {
17
+ oldNodePath: SequenceNodePath;
18
+ newNodePath: SequenceNodePath | null;
19
+ }[];
16
20
  }>;
17
21
  export declare const deleteJsxNode: ({ input, nodePath, prettierConfigOverride, }: {
18
22
  input: string;
@@ -37,6 +37,7 @@ exports.deleteJsxNode = exports.deleteJsxNodes = exports.deleteJsxElementAtPath
37
37
  const recast = __importStar(require("recast"));
38
38
  const get_ast_node_path_1 = require("../helpers/get-ast-node-path");
39
39
  const format_file_content_1 = require("./format-file-content");
40
+ const get_node_path_remappings_1 = require("./get-node-path-remappings");
40
41
  const parse_ast_1 = require("./parse-ast");
41
42
  const { builders: b, namedTypes } = recast.types;
42
43
  /** Recast `builders.nullLiteral()` is typed against ast-types; normalize to Babel `Expression`. */
@@ -292,6 +293,7 @@ const deleteJsxNodes = async ({ input, nodePaths, prettierConfigOverride, }) =>
292
293
  throw new Error('No JSX nodes were specified for deletion');
293
294
  }
294
295
  const ast = (0, parse_ast_1.parseAst)(input);
296
+ const capturedNodePaths = (0, get_node_path_remappings_1.captureJsxNodePaths)(ast);
295
297
  const pathsToDelete = nodePaths.map((nodePath) => {
296
298
  var _a, _b;
297
299
  var _c, _d;
@@ -314,11 +316,17 @@ const deleteJsxNodes = async ({ input, nodePaths, prettierConfigOverride, }) =>
314
316
  input: finalFile,
315
317
  prettierConfigOverride,
316
318
  });
319
+ const { nodePathRemappings } = (0, get_node_path_remappings_1.getNodePathRemappings)({
320
+ ast,
321
+ captured: capturedNodePaths,
322
+ output,
323
+ });
317
324
  return {
318
325
  output,
319
326
  formatted,
320
327
  nodeLabels: pathsToDelete.map(({ nodeLabel }) => nodeLabel),
321
328
  logLines: pathsToDelete.map(({ logLine }) => logLine),
329
+ nodePathRemappings,
322
330
  };
323
331
  };
324
332
  exports.deleteJsxNodes = deleteJsxNodes;
@@ -81,12 +81,14 @@ const parseAndApplyCodemod = ({ input, codeMod, }) => {
81
81
  });
82
82
  }
83
83
  if (codeMod.type === 'new-composition') {
84
- (0, imports_1.ensureNamedImport)({
85
- ast: newAst,
86
- importedName: 'Composition',
87
- sourcePath: 'remotion',
88
- localName: 'Composition',
89
- });
84
+ if (codeMod.canvasCapture === null) {
85
+ (0, imports_1.ensureNamedImport)({
86
+ ast: newAst,
87
+ importedName: 'Composition',
88
+ sourcePath: 'remotion',
89
+ localName: 'Composition',
90
+ });
91
+ }
90
92
  (0, imports_1.ensureNamedImport)({
91
93
  ast: newAst,
92
94
  importedName: codeMod.componentName,
@@ -1,3 +1,4 @@
1
+ import type { SequenceNodePathRemapping } from '@remotion/studio-shared';
1
2
  import type { SequenceNodePath } from 'remotion';
2
3
  export declare const duplicateJsxElementAtPath: (jsxPath: import("ast-types/lib/node-path").NodePath<N, V>) => void;
3
4
  export declare const duplicateJsxNode: ({ input, nodePath, prettierConfigOverride, }: {
@@ -9,4 +10,5 @@ export declare const duplicateJsxNode: ({ input, nodePath, prettierConfigOverrid
9
10
  formatted: boolean;
10
11
  nodeLabel: string;
11
12
  logLine: number;
13
+ nodePathRemappings: SequenceNodePathRemapping[];
12
14
  }>;
@@ -38,6 +38,7 @@ const types_1 = require("@babel/types");
38
38
  const recast = __importStar(require("recast"));
39
39
  const delete_jsx_node_1 = require("./delete-jsx-node");
40
40
  const format_file_content_1 = require("./format-file-content");
41
+ const get_node_path_remappings_1 = require("./get-node-path-remappings");
41
42
  const parse_ast_1 = require("./parse-ast");
42
43
  const { namedTypes } = recast.types;
43
44
  const makeFragment = (first, second) => ({
@@ -288,6 +289,7 @@ const duplicateJsxNode = async ({ input, nodePath, prettierConfigOverride, }) =>
288
289
  var _a, _b;
289
290
  var _c, _d;
290
291
  const ast = (0, parse_ast_1.parseAst)(input);
292
+ const capturedNodePaths = (0, get_node_path_remappings_1.captureJsxNodePaths)(ast);
291
293
  const jsxPath = (0, delete_jsx_node_1.findJsxElementPathForDeletion)(ast, nodePath);
292
294
  if (!jsxPath) {
293
295
  throw new Error('Could not find a JSX element at the specified location to duplicate');
@@ -301,11 +303,17 @@ const duplicateJsxNode = async ({ input, nodePath, prettierConfigOverride, }) =>
301
303
  input: finalFile,
302
304
  prettierConfigOverride,
303
305
  });
306
+ const { nodePathRemappings } = (0, get_node_path_remappings_1.getNodePathRemappings)({
307
+ ast,
308
+ captured: capturedNodePaths,
309
+ output,
310
+ });
304
311
  return {
305
312
  output,
306
313
  formatted,
307
314
  nodeLabel,
308
315
  logLine,
316
+ nodePathRemappings,
309
317
  };
310
318
  };
311
319
  exports.duplicateJsxNode = duplicateJsxNode;
@@ -0,0 +1,16 @@
1
+ import type { File, JSXOpeningElement } from '@babel/types';
2
+ import type { SequenceNodePathRemapping } from '@remotion/studio-shared';
3
+ import type { SequenceNodePath } from 'remotion';
4
+ export type CapturedJsxNodePath = {
5
+ node: JSXOpeningElement;
6
+ nodePath: SequenceNodePath;
7
+ };
8
+ export declare const captureJsxNodePaths: (ast: File) => CapturedJsxNodePath[];
9
+ export declare const getNodePathRemappings: ({ ast, captured, output, }: {
10
+ ast: File;
11
+ captured: CapturedJsxNodePath[];
12
+ output: string;
13
+ }) => {
14
+ nodePathRemappings: SequenceNodePathRemapping[];
15
+ finalNodePathByNode: Map<JSXOpeningElement, SequenceNodePath>;
16
+ };
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getNodePathRemappings = exports.captureJsxNodePaths = void 0;
37
+ const recast = __importStar(require("recast"));
38
+ const can_update_sequence_props_1 = require("../preview-server/routes/can-update-sequence-props");
39
+ const parse_ast_1 = require("./parse-ast");
40
+ const captureJsxNodePaths = (ast) => {
41
+ const captured = [];
42
+ recast.visit(ast, {
43
+ visitJSXOpeningElement(path) {
44
+ captured.push({
45
+ node: path.node,
46
+ nodePath: (0, can_update_sequence_props_1.getNodePathForRecastPath)(path, ast),
47
+ });
48
+ return this.traverse(path);
49
+ },
50
+ });
51
+ return captured;
52
+ };
53
+ exports.captureJsxNodePaths = captureJsxNodePaths;
54
+ const getNodePathRemappings = ({ ast, captured, output, }) => {
55
+ const nodesAfterMutation = [];
56
+ recast.visit(ast, {
57
+ visitJSXOpeningElement(path) {
58
+ nodesAfterMutation.push(path.node);
59
+ return this.traverse(path);
60
+ },
61
+ });
62
+ const finalAst = (0, parse_ast_1.parseAst)(output);
63
+ const finalNodePaths = [];
64
+ recast.visit(finalAst, {
65
+ visitJSXOpeningElement(path) {
66
+ finalNodePaths.push((0, can_update_sequence_props_1.getNodePathForRecastPath)(path, finalAst));
67
+ return this.traverse(path);
68
+ },
69
+ });
70
+ if (nodesAfterMutation.length !== finalNodePaths.length) {
71
+ throw new Error('Could not map JSX node paths after modifying JSX nodes');
72
+ }
73
+ const finalNodePathByNode = new Map();
74
+ for (let i = 0; i < nodesAfterMutation.length; i++) {
75
+ finalNodePathByNode.set(nodesAfterMutation[i], finalNodePaths[i]);
76
+ }
77
+ const nodePathRemappings = captured.flatMap(({ node, nodePath }) => {
78
+ var _a;
79
+ const newNodePath = (_a = finalNodePathByNode.get(node)) !== null && _a !== void 0 ? _a : null;
80
+ if (newNodePath !== null &&
81
+ JSON.stringify(nodePath) === JSON.stringify(newNodePath)) {
82
+ return [];
83
+ }
84
+ return [{ oldNodePath: nodePath, newNodePath }];
85
+ });
86
+ return { finalNodePathByNode, nodePathRemappings };
87
+ };
88
+ exports.getNodePathRemappings = getNodePathRemappings;
@@ -164,6 +164,19 @@ const jsxAttributeWithExpression = (name, expression) => ({
164
164
  },
165
165
  });
166
166
  const newCompositionElement = (transformation) => {
167
+ if (transformation.canvasCapture !== null) {
168
+ return {
169
+ type: 'JSXElement',
170
+ openingElement: {
171
+ type: 'JSXOpeningElement',
172
+ name: jsxId(transformation.componentName),
173
+ attributes: [],
174
+ selfClosing: true,
175
+ },
176
+ closingElement: null,
177
+ children: [],
178
+ };
179
+ }
167
180
  return {
168
181
  type: 'JSXElement',
169
182
  openingElement: {
@@ -1,4 +1,4 @@
1
- import type { ReorderSequencePosition } from '@remotion/studio-shared';
1
+ import type { ReorderSequencePosition, SequenceNodePathRemapping } from '@remotion/studio-shared';
2
2
  import type { SequenceNodePath } from 'remotion';
3
3
  export declare const reorderSequence: ({ input, sourceNodePath, targetNodePath, position, prettierConfigOverride, }: {
4
4
  input: string;
@@ -11,4 +11,5 @@ export declare const reorderSequence: ({ input, sourceNodePath, targetNodePath,
11
11
  formatted: boolean;
12
12
  sequenceLabel: string;
13
13
  logLine: number;
14
+ nodePathRemappings: SequenceNodePathRemapping[];
14
15
  }>;
@@ -37,6 +37,7 @@ exports.reorderSequence = void 0;
37
37
  const recast = __importStar(require("recast"));
38
38
  const delete_jsx_node_1 = require("./delete-jsx-node");
39
39
  const format_file_content_1 = require("./format-file-content");
40
+ const get_node_path_remappings_1 = require("./get-node-path-remappings");
40
41
  const parse_ast_1 = require("./parse-ast");
41
42
  const { namedTypes } = recast.types;
42
43
  const getJsxChildrenParent = (path) => {
@@ -57,6 +58,7 @@ const reorderSequence = async ({ input, sourceNodePath, targetNodePath, position
57
58
  var _a, _b;
58
59
  var _c, _d;
59
60
  const ast = (0, parse_ast_1.parseAst)(input);
61
+ const capturedNodePaths = (0, get_node_path_remappings_1.captureJsxNodePaths)(ast);
60
62
  const sourcePath = (0, delete_jsx_node_1.findJsxElementPathForDeletion)(ast, sourceNodePath);
61
63
  if (!sourcePath) {
62
64
  throw new Error('Could not find a JSX element at the source location to reorder sequence');
@@ -99,11 +101,17 @@ const reorderSequence = async ({ input, sourceNodePath, targetNodePath, position
99
101
  input: finalFile,
100
102
  prettierConfigOverride,
101
103
  });
104
+ const { nodePathRemappings } = (0, get_node_path_remappings_1.getNodePathRemappings)({
105
+ ast,
106
+ captured: capturedNodePaths,
107
+ output,
108
+ });
102
109
  return {
103
110
  output,
104
111
  formatted,
105
112
  sequenceLabel,
106
113
  logLine,
114
+ nodePathRemappings,
107
115
  };
108
116
  };
109
117
  exports.reorderSequence = reorderSequence;
@@ -1,3 +1,4 @@
1
+ import type { SequenceNodePathRemapping } from '@remotion/studio-shared';
1
2
  import type { SequenceNodePath } from 'remotion';
2
3
  export declare const getSplitUnsupportedSequenceTagReason: (tagName: string) => string | null;
3
4
  export declare const getIsSplittableSequenceTag: (tagName: string) => boolean;
@@ -11,4 +12,5 @@ export declare const splitJsxSequence: ({ input, nodePath, splitFrame, prettierC
11
12
  formatted: boolean;
12
13
  nodeLabel: string;
13
14
  logLine: number;
15
+ nodePathRemappings: SequenceNodePathRemapping[];
14
16
  }>;
@@ -38,6 +38,7 @@ const types_1 = require("@babel/types");
38
38
  const recast = __importStar(require("recast"));
39
39
  const delete_jsx_node_1 = require("./delete-jsx-node");
40
40
  const format_file_content_1 = require("./format-file-content");
41
+ const get_node_path_remappings_1 = require("./get-node-path-remappings");
41
42
  const parse_ast_1 = require("./parse-ast");
42
43
  const { builders: b, namedTypes } = recast.types;
43
44
  const jsxId = (name) => ({ type: 'JSXIdentifier', name });
@@ -275,6 +276,7 @@ const splitJsxSequence = async ({ input, nodePath, splitFrame, prettierConfigOve
275
276
  throw new Error('Split frame must be an integer');
276
277
  }
277
278
  const ast = (0, parse_ast_1.parseAst)(input);
279
+ const capturedNodePaths = (0, get_node_path_remappings_1.captureJsxNodePaths)(ast);
278
280
  const jsxPath = (0, delete_jsx_node_1.findJsxElementPathForDeletion)(ast, nodePath);
279
281
  if (!jsxPath) {
280
282
  throw new Error('Could not find a JSX sequence at the specified location to split');
@@ -340,11 +342,17 @@ const splitJsxSequence = async ({ input, nodePath, splitFrame, prettierConfigOve
340
342
  input: finalFile,
341
343
  prettierConfigOverride,
342
344
  });
345
+ const { nodePathRemappings } = (0, get_node_path_remappings_1.getNodePathRemappings)({
346
+ ast,
347
+ captured: capturedNodePaths,
348
+ output,
349
+ });
343
350
  return {
344
351
  output,
345
352
  formatted,
346
353
  nodeLabel: (0, delete_jsx_node_1.getJsxElementTagLabel)(jsxElement),
347
354
  logLine: (_d = (_c = (_a = jsxElement.openingElement.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _c !== void 0 ? _c : (_b = jsxElement.loc) === null || _b === void 0 ? void 0 : _b.start.line) !== null && _d !== void 0 ? _d : 1,
355
+ nodePathRemappings,
348
356
  };
349
357
  };
350
358
  exports.splitJsxSequence = splitJsxSequence;
@@ -334,18 +334,16 @@ const getInlineOptionsFromExtraArgs = (extraArgs) => {
334
334
  }
335
335
  return existingOptions;
336
336
  };
337
- const normalizeEasingAfterAddingKeyframe = ({ extraArgs, previousSegmentCount, nextSegmentCount, insertedKeyframeIndex, nextKeyframeCount, }) => {
338
- const options = getInlineOptionsFromExtraArgs(extraArgs);
337
+ const normalizeEasingAfterAddingKeyframe = ({ extraArgs, previousSegmentCount, nextSegmentCount, insertedKeyframeIndex, nextKeyframeCount, defaultEasing, }) => {
338
+ var _a, _b;
339
+ const options = (_a = getInlineOptionsFromExtraArgs(extraArgs)) !== null && _a !== void 0 ? _a : (extraArgs.length === 0 ? createEmptyOptionsExpression() : null);
339
340
  if (!options) {
340
341
  return { extraArgs, needsEasingImport: false };
341
342
  }
342
- const easing = getExistingEasingArrayOrNull({
343
+ const easing = (_b = getExistingEasingArrayOrNull({
343
344
  options,
344
345
  segmentCount: previousSegmentCount,
345
- });
346
- if (easing === null) {
347
- return { extraArgs, needsEasingImport: false };
348
- }
346
+ })) !== null && _b !== void 0 ? _b : Array.from({ length: previousSegmentCount }, () => defaultEasing);
349
347
  if (easing.length < nextSegmentCount) {
350
348
  const isSplittingExistingSegment = insertedKeyframeIndex > 0 &&
351
349
  insertedKeyframeIndex < nextKeyframeCount - 1;
@@ -353,15 +351,16 @@ const normalizeEasingAfterAddingKeyframe = ({ extraArgs, previousSegmentCount, n
353
351
  ? Math.min(insertedKeyframeIndex - 1, easing.length - 1)
354
352
  : null;
355
353
  easing.splice(insertedKeyframeIndex, 0, easingIndexToDuplicate === null
356
- ? studio_shared_1.LINEAR_KEYFRAME_EASING
354
+ ? defaultEasing
357
355
  : easing[easingIndexToDuplicate]);
358
356
  }
359
357
  while (easing.length < nextSegmentCount) {
360
- easing.push(studio_shared_1.LINEAR_KEYFRAME_EASING);
358
+ easing.push(defaultEasing);
361
359
  }
360
+ const needsEasingImport = setEasingOption({ options, easing });
362
361
  return {
363
362
  extraArgs: getExtraArgsWithOptions({ extraArgs, options }),
364
- needsEasingImport: setEasingOption({ options, easing }),
363
+ needsEasingImport,
365
364
  };
366
365
  };
367
366
  const getEasingIndexToRemove = ({ removedKeyframeIndex, keyframeCountBeforeRemoval, }) => {
@@ -586,6 +585,9 @@ const addKeyframe = ({ expression, key, frame, value, schema, videoConfigValues,
586
585
  const existing = getInterpolationExpression(expression, videoConfigValues);
587
586
  const newOutput = (0, update_nested_prop_1.parseValueExpression)(value);
588
587
  if (existing) {
588
+ const defaultEasing = (0, studio_shared_1.isSchemaFieldHoldOnly)({ schema, key })
589
+ ? studio_shared_1.HOLD_KEYFRAME_EASING
590
+ : studio_shared_1.LINEAR_KEYFRAME_EASING;
589
591
  const existingCalleeName = existing.callee.type === 'Identifier'
590
592
  ? existing.callee.name
591
593
  : 'interpolate';
@@ -619,6 +621,7 @@ const addKeyframe = ({ expression, key, frame, value, schema, videoConfigValues,
619
621
  .sort((first, second) => first.frame - second.frame)
620
622
  .findIndex((keyframe) => keyframe.frame === frame),
621
623
  nextKeyframeCount: nextKeyframes.length,
624
+ defaultEasing,
622
625
  })
623
626
  : { extraArgs: existing.extraArgs, needsEasingImport: false };
624
627
  return {
@@ -804,6 +807,10 @@ const applyKeyframeOperation = ({ expression, key, operation, schema, videoConfi
804
807
  };
805
808
  }
806
809
  if (operation.type === 'easing') {
810
+ if ((0, studio_shared_1.isSchemaFieldHoldOnly)({ schema, key }) &&
811
+ operation.easing.type !== 'step1') {
812
+ throw new Error(`Cannot update easing: "${key}" only supports Easing.step1`);
813
+ }
807
814
  const updated = updateKeyframeEasing({
808
815
  expression,
809
816
  segmentIndex: operation.segmentIndex,
@@ -1,3 +1,12 @@
1
+ export type FileChangeMetadata = {
2
+ skipSequencePropsUpdate: boolean;
3
+ };
4
+ type WriteFileAndNotifyFileWatchersOptions = {
5
+ file: string;
6
+ content: string;
7
+ originatorClientId: string | undefined;
8
+ metadata: FileChangeMetadata | null;
9
+ };
1
10
  export type FileChangeEvent = {
2
11
  type: 'created';
3
12
  content: string;
@@ -8,6 +17,7 @@ export type FileChangeEvent = {
8
17
  type: 'changed';
9
18
  content: string;
10
19
  originatorClientId: string | undefined;
20
+ skipSequencePropsUpdate: boolean;
11
21
  };
12
22
  type OnChange = (event: FileChangeEvent) => void;
13
23
  export type FileWatcherRegistry = {
@@ -25,7 +35,7 @@ export type FileWatcherRegistry = {
25
35
  exists: boolean;
26
36
  unwatch: () => void;
27
37
  };
28
- writeFileAndNotifyFileWatchers: (file: string, content: string, originatorClientId: string | undefined) => void;
38
+ writeFileAndNotifyFileWatchers: (options: WriteFileAndNotifyFileWatchersOptions) => void;
29
39
  };
30
40
  export declare const createFileWatcherRegistry: () => FileWatcherRegistry;
31
41
  export declare const setFileWatcherRegistry: (registry: FileWatcherRegistry) => () => void;