@remotion/studio-shared 4.0.481 → 4.0.483

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.
@@ -4,6 +4,7 @@ import type { _InternalTypes, CannotUpdateSequenceReason, CanUpdateEffectPropsRe
4
4
  import type { RecastCodemod, VisualControlChange } from './codemods';
5
5
  import type { ComponentProp } from './component-drag-data';
6
6
  import type { EffectClipboardParam, EffectClipboardPasteType, EffectClipboardSnapshot } from './effect-clipboard-data';
7
+ import type { ElementDragData } from './element-drag-data';
7
8
  import type { PackageManager } from './package-manager';
8
9
  import type { ProjectInfo } from './project-info';
9
10
  import type { CompletedClientRender, RequiredChromiumOptions } from './render-job';
@@ -528,6 +529,19 @@ export type InsertJsxElementResponse = {
528
529
  reason: string;
529
530
  stack: string;
530
531
  };
532
+ export type InsertElementRequest = {
533
+ compositionFile: string;
534
+ compositionId: string;
535
+ element: ElementDragData['element'];
536
+ position: InsertableCompositionElementPosition | null;
537
+ };
538
+ export type InsertElementResponse = {
539
+ success: true;
540
+ } | {
541
+ success: false;
542
+ reason: string;
543
+ stack: string;
544
+ };
531
545
  export type DownloadRemoteAssetRequest = {
532
546
  url: string;
533
547
  };
@@ -613,6 +627,7 @@ export type ApiRoutes = {
613
627
  '/api/delete-jsx-node': ReqAndRes<DeleteJsxNodeRequest, DeleteJsxNodeResponse>;
614
628
  '/api/duplicate-jsx-node': ReqAndRes<DuplicateJsxNodeRequest, DuplicateJsxNodeResponse>;
615
629
  '/api/insert-jsx-element': ReqAndRes<InsertJsxElementRequest, InsertJsxElementResponse>;
630
+ '/api/insert-element': ReqAndRes<InsertElementRequest, InsertElementResponse>;
616
631
  '/api/download-remote-asset': ReqAndRes<DownloadRemoteAssetRequest, DownloadRemoteAssetResponse>;
617
632
  '/api/update-available': ReqAndRes<UpdateAvailableRequest, UpdateAvailableResponse>;
618
633
  '/api/apply-codemod': ReqAndRes<ApplyCodemodRequest, ApplyCodemodResponse>;
@@ -10,6 +10,15 @@ export type ApplyVisualControlCodemod = {
10
10
  changes: VisualControlChange[];
11
11
  };
12
12
  export type RecastCodemod = {
13
+ type: 'new-composition';
14
+ newId: string;
15
+ componentName: string;
16
+ componentImportPath: string;
17
+ newHeight: number;
18
+ newWidth: number;
19
+ newFps: number;
20
+ newDurationInFrames: number;
21
+ } | {
13
22
  type: 'duplicate-composition';
14
23
  idToDuplicate: string;
15
24
  newId: string;
@@ -19,8 +19,25 @@ const isEasing = (value) => {
19
19
  isFiniteNumber(value.damping) &&
20
20
  isFiniteNumber(value.mass) &&
21
21
  isFiniteNumber(value.stiffness) &&
22
+ (value.allowTail === undefined ||
23
+ value.allowTail === null ||
24
+ typeof value.allowTail === 'boolean') &&
25
+ (value.durationRestThreshold === undefined ||
26
+ value.durationRestThreshold === null ||
27
+ isFiniteNumber(value.durationRestThreshold)) &&
22
28
  typeof value.overshootClamping === 'boolean')));
23
29
  };
30
+ const normalizeEasing = (easing) => {
31
+ var _a, _b;
32
+ if (easing.type !== 'spring') {
33
+ return easing;
34
+ }
35
+ return {
36
+ ...easing,
37
+ allowTail: (_a = easing.allowTail) !== null && _a !== void 0 ? _a : null,
38
+ durationRestThreshold: (_b = easing.durationRestThreshold) !== null && _b !== void 0 ? _b : null,
39
+ };
40
+ };
24
41
  const parseEasingClipboardDataResult = (value) => {
25
42
  try {
26
43
  const parsed = JSON.parse(value);
@@ -45,7 +62,7 @@ const parseEasingClipboardDataResult = (value) => {
45
62
  type: 'easing',
46
63
  version: 1,
47
64
  remotionClipboard: 'easing',
48
- easing: parsed.easing,
65
+ easing: normalizeEasing(parsed.easing),
49
66
  },
50
67
  };
51
68
  }
@@ -195,6 +195,17 @@ exports.EFFECT_CATALOG = [
195
195
  config: {},
196
196
  },
197
197
  },
198
+ {
199
+ id: 'effects-radial-progressive-blur',
200
+ category: 'Blur & Shadow',
201
+ label: 'radialProgressiveBlur()',
202
+ description: 'Ellipse-controlled blur effect',
203
+ effect: {
204
+ name: 'radialProgressiveBlur',
205
+ importPath: '@remotion/effects/radial-progressive-blur',
206
+ config: {},
207
+ },
208
+ },
198
209
  {
199
210
  id: 'effects-zoom-blur',
200
211
  category: 'Blur & Shadow',
@@ -228,6 +239,17 @@ exports.EFFECT_CATALOG = [
228
239
  config: {},
229
240
  },
230
241
  },
242
+ {
243
+ id: 'effects-light-trail',
244
+ category: 'Blur & Shadow',
245
+ label: 'lightTrail()',
246
+ description: 'Directional light trail effect',
247
+ effect: {
248
+ name: 'lightTrail',
249
+ importPath: '@remotion/effects/light-trail',
250
+ config: {},
251
+ },
252
+ },
231
253
  {
232
254
  id: 'effects-evolve',
233
255
  category: 'Reveal',
@@ -318,6 +340,22 @@ exports.EFFECT_CATALOG = [
318
340
  config: {},
319
341
  },
320
342
  },
343
+ {
344
+ id: 'effects-corner-pin',
345
+ category: 'Distort',
346
+ label: 'cornerPin()',
347
+ description: 'Pin source corners to a quad',
348
+ effect: {
349
+ name: 'cornerPin',
350
+ importPath: '@remotion/effects/corner-pin',
351
+ config: {
352
+ topLeft: [0.08, 0.12],
353
+ topRight: [0.92, 0.04],
354
+ bottomRight: [0.86, 0.9],
355
+ bottomLeft: [0.14, 0.96],
356
+ },
357
+ },
358
+ },
321
359
  {
322
360
  id: 'effects-wave',
323
361
  category: 'Distort',
@@ -21,8 +21,43 @@ const isEasing = (value) => {
21
21
  isFiniteNumber(value.damping) &&
22
22
  isFiniteNumber(value.mass) &&
23
23
  isFiniteNumber(value.stiffness) &&
24
+ (value.allowTail === undefined ||
25
+ value.allowTail === null ||
26
+ typeof value.allowTail === 'boolean') &&
27
+ (value.durationRestThreshold === undefined ||
28
+ value.durationRestThreshold === null ||
29
+ isFiniteNumber(value.durationRestThreshold)) &&
24
30
  typeof value.overshootClamping === 'boolean')));
25
31
  };
32
+ const normalizeEasing = (easing) => {
33
+ var _a, _b;
34
+ if (easing.type !== 'spring') {
35
+ return easing;
36
+ }
37
+ return {
38
+ ...easing,
39
+ allowTail: (_a = easing.allowTail) !== null && _a !== void 0 ? _a : null,
40
+ durationRestThreshold: (_b = easing.durationRestThreshold) !== null && _b !== void 0 ? _b : null,
41
+ };
42
+ };
43
+ const normalizeParam = (param) => {
44
+ if (param.type === 'static') {
45
+ return param;
46
+ }
47
+ return {
48
+ ...param,
49
+ easing: param.easing.map(normalizeEasing),
50
+ };
51
+ };
52
+ const normalizeSnapshot = (snapshot) => {
53
+ return {
54
+ ...snapshot,
55
+ params: Object.fromEntries(Object.entries(snapshot.params).map(([key, param]) => [
56
+ key,
57
+ normalizeParam(param),
58
+ ])),
59
+ };
60
+ };
26
61
  const isKeyframe = (value) => {
27
62
  return isRecord(value) && isFiniteNumber(value.frame) && 'value' in value;
28
63
  };
@@ -94,7 +129,7 @@ const parseEffectClipboardDataResult = (value) => {
94
129
  if (!isEffectClipboardSnapshotV3(effect)) {
95
130
  return { status: 'invalid' };
96
131
  }
97
- effects.push(effect);
132
+ effects.push(normalizeSnapshot(effect));
98
133
  }
99
134
  return {
100
135
  status: 'valid',
@@ -161,7 +196,7 @@ const parseEffectPropClipboardDataResult = (value) => {
161
196
  importPath: parsed.effect.importPath,
162
197
  },
163
198
  key: parsed.key,
164
- param: parsed.param,
199
+ param: normalizeParam(parsed.param),
165
200
  },
166
201
  };
167
202
  }
@@ -0,0 +1,22 @@
1
+ import { type ComponentDimensions } from './component-drag-data';
2
+ export declare const ELEMENT_DRAG_MIME_TYPE = "application/vnd.remotion.element+json";
3
+ export type ElementDragData = {
4
+ type: 'remotion-element';
5
+ version: 1;
6
+ element: {
7
+ slug: string;
8
+ displayName: string;
9
+ sourceCode: string;
10
+ dimensions: ComponentDimensions;
11
+ };
12
+ };
13
+ export declare const isLowercaseElementFileName: (value: unknown) => value is string;
14
+ export declare const makeElementFileNameFromSlug: (slug: string) => string | null;
15
+ export declare const getElementComponentNameFromSourceCode: (sourceCode: string) => string | null;
16
+ export declare const makeElementDragData: ({ dimensions, displayName, slug, sourceCode, }: {
17
+ slug: string;
18
+ displayName: string;
19
+ sourceCode: string;
20
+ dimensions: ComponentDimensions;
21
+ }) => ElementDragData;
22
+ export declare const parseElementDragData: (value: string) => ElementDragData | null;
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseElementDragData = exports.makeElementDragData = exports.getElementComponentNameFromSourceCode = exports.makeElementFileNameFromSlug = exports.isLowercaseElementFileName = exports.ELEMENT_DRAG_MIME_TYPE = void 0;
4
+ const component_drag_data_1 = require("./component-drag-data");
5
+ exports.ELEMENT_DRAG_MIME_TYPE = 'application/vnd.remotion.element+json';
6
+ const isRecord = (value) => {
7
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
8
+ };
9
+ const isLowercaseElementFileName = (value) => {
10
+ return (typeof value === 'string' &&
11
+ value.length > 0 &&
12
+ value.length < 120 &&
13
+ value === value.toLowerCase() &&
14
+ value.endsWith('.tsx') &&
15
+ !value.includes('/') &&
16
+ !value.includes('\\') &&
17
+ !value.includes('\0') &&
18
+ !value.includes('..') &&
19
+ /^[a-z0-9][a-z0-9.-]*\.tsx$/.test(value));
20
+ };
21
+ exports.isLowercaseElementFileName = isLowercaseElementFileName;
22
+ const isSlug = (value) => {
23
+ return (typeof value === 'string' &&
24
+ value.length > 0 &&
25
+ value.length < 120 &&
26
+ /^[a-z0-9][a-z0-9/-]*$/.test(value) &&
27
+ !value.includes('..') &&
28
+ !value.includes('//'));
29
+ };
30
+ const makeElementFileNameFromSlug = (slug) => {
31
+ if (!isSlug(slug)) {
32
+ return null;
33
+ }
34
+ const lastSegment = slug.split('/').at(-1);
35
+ if (!lastSegment) {
36
+ return null;
37
+ }
38
+ const fileName = `${lastSegment}.element.tsx`;
39
+ return (0, exports.isLowercaseElementFileName)(fileName) ? fileName : null;
40
+ };
41
+ exports.makeElementFileNameFromSlug = makeElementFileNameFromSlug;
42
+ const isDisplayName = (value) => {
43
+ return typeof value === 'string' && value.length > 0 && value.length < 120;
44
+ };
45
+ const isSourceCode = (value) => {
46
+ return (typeof value === 'string' &&
47
+ value.trim().length > 0 &&
48
+ value.length < 200000);
49
+ };
50
+ const isDimensions = (value) => {
51
+ if (!isRecord(value)) {
52
+ return false;
53
+ }
54
+ return (typeof value.width === 'number' &&
55
+ Number.isFinite(value.width) &&
56
+ value.width > 0 &&
57
+ typeof value.height === 'number' &&
58
+ Number.isFinite(value.height) &&
59
+ value.height > 0);
60
+ };
61
+ const getElementComponentNameFromSourceCode = (sourceCode) => {
62
+ const componentNames = Array.from(sourceCode.matchAll(/export\s+(?:const|function)\s+([A-Z_$][A-Za-z0-9_$]*)\b/g)).map((match) => match[1]);
63
+ const uniqueComponentNames = Array.from(new Set(componentNames));
64
+ if (uniqueComponentNames.length !== 1) {
65
+ return null;
66
+ }
67
+ const [componentName] = uniqueComponentNames;
68
+ return (0, component_drag_data_1.isComponentIdentifier)(componentName) ? componentName : null;
69
+ };
70
+ exports.getElementComponentNameFromSourceCode = getElementComponentNameFromSourceCode;
71
+ const makeElementDragData = ({ dimensions, displayName, slug, sourceCode, }) => {
72
+ return {
73
+ type: 'remotion-element',
74
+ version: 1,
75
+ element: {
76
+ slug,
77
+ displayName,
78
+ sourceCode,
79
+ dimensions,
80
+ },
81
+ };
82
+ };
83
+ exports.makeElementDragData = makeElementDragData;
84
+ const parseElementDragData = (value) => {
85
+ try {
86
+ const parsed = JSON.parse(value);
87
+ if (!isRecord(parsed)) {
88
+ return null;
89
+ }
90
+ if (parsed.type !== 'remotion-element' || parsed.version !== 1) {
91
+ return null;
92
+ }
93
+ if (!isRecord(parsed.element)) {
94
+ return null;
95
+ }
96
+ const { dimensions, displayName, slug, sourceCode } = parsed.element;
97
+ if (!isSlug(slug) ||
98
+ !isDisplayName(displayName) ||
99
+ !isSourceCode(sourceCode) ||
100
+ (0, exports.getElementComponentNameFromSourceCode)(sourceCode) === null ||
101
+ (0, exports.makeElementFileNameFromSlug)(slug) === null ||
102
+ !isDimensions(dimensions)) {
103
+ return null;
104
+ }
105
+ return (0, exports.makeElementDragData)({
106
+ slug,
107
+ displayName,
108
+ sourceCode,
109
+ dimensions,
110
+ });
111
+ }
112
+ catch (_a) {
113
+ return null;
114
+ }
115
+ };
116
+ exports.parseElementDragData = parseElementDragData;
package/dist/index.d.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  export { splitAnsi, stripAnsi } from './ansi';
2
- export { AddEffectKeyframeRequest, AddEffectKeyframeResponse, AddKeyframesRequest, AddKeyframesResponse, AddEffectRequest, AddEffectResponse, AddRenderRequest, AddSequenceKeyframeRequest, AddSequenceKeyframeResponse, ApiRoutes, ApplyCodemodRequest, ApplyCodemodResponse, ApplyVisualControlRequest, ApplyVisualControlResponse, CanUpdateDefaultPropsResponse, CanUpdateSequencePropsRequest, CancelRenderRequest, CancelRenderResponse, CompositionComponentInfoRequest, CompositionComponentInfoResponse, CopyStillToClipboardRequest, DeleteEffectKeyframe, DeleteEffectRequest, DeleteEffectRequestItem, DeleteEffectResponse, DeleteJsxNodeRequest, DeleteJsxNodeRequestItem, DeleteJsxNodeResponse, DeleteKeyframesRequest, DeleteKeyframesResponse, DeleteSequenceKeyframe, DeleteStaticFileRequest, DeleteStaticFileResponse, DownloadRemoteAssetRequest, DownloadRemoteAssetResponse, DuplicateEffectRequest, DuplicateEffectRequestItem, DuplicateEffectResponse, DuplicateJsxNodeRequest, DuplicateJsxNodeResponse, InsertJsxElementRequest, InsertJsxElementResponse, InsertableCompositionElement, InsertableCompositionElementPosition, InstallPackageRequest, InstallPackageResponse, LogStudioErrorRequest, LogStudioErrorResponse, MoveEffectKeyframe, MoveKeyframesRequest, MoveKeyframesResponse, MoveSequenceKeyframe, OpenInEditorRequest, OpenInEditorResponse, OpenInFileExplorerRequest, PasteEffectsRequest, PasteEffectsResponse, ProjectInfoRequest, ProjectInfoResponse, RedoRequest, RedoResponse, RemoveRenderRequest, RenameStaticFileRequest, RenameStaticFileResponse, ReorderEffectRequest, ReorderEffectResponse, ReorderSequencePosition, ReorderSequenceRequest, ReorderSequenceResponse, RestartStudioRequest, RestartStudioResponse, SaveEffectPropsRequest, SaveEffectPropsResponse, SaveSequencePropEdit, SaveSequencePropsRequest, SaveSequencePropsResponse, SaveSequencePropsResult, SimpleDiff, SubscribeToDefaultPropsRequest, SubscribeToDefaultPropsResponse, SubscribeToFileExistenceRequest, SubscribeToFileExistenceResponse, SubscribeToSequencePropsRequest, SubscribeToSequencePropsResponse, UndoRequest, UndoResponse, UnsubscribeFromDefaultPropsRequest, UnsubscribeFromFileExistenceRequest, UnsubscribeFromSequencePropsRequest, UpdateAvailableRequest, UpdateAvailableResponse, UpdateDefaultPropsRequest, UpdateDefaultPropsResponse, UpdateEffectKeyframeSettingsRequest, UpdateEffectKeyframeSettingsResponse, UpdateSequenceKeyframeSettingsRequest, UpdateSequenceKeyframeSettingsResponse, type KeyframeSettings, type AddEffectKeyframe, type AddSequenceKeyframe, } from './api-requests';
2
+ export { AddEffectKeyframeRequest, AddEffectKeyframeResponse, AddEffectRequest, AddEffectResponse, AddKeyframesRequest, AddKeyframesResponse, AddRenderRequest, AddSequenceKeyframeRequest, AddSequenceKeyframeResponse, ApiRoutes, ApplyCodemodRequest, ApplyCodemodResponse, ApplyVisualControlRequest, ApplyVisualControlResponse, CanUpdateDefaultPropsResponse, CanUpdateSequencePropsRequest, CancelRenderRequest, CancelRenderResponse, CompositionComponentInfoRequest, CompositionComponentInfoResponse, CopyStillToClipboardRequest, DeleteEffectKeyframe, DeleteEffectRequest, DeleteEffectRequestItem, DeleteEffectResponse, DeleteJsxNodeRequest, DeleteJsxNodeRequestItem, DeleteJsxNodeResponse, DeleteKeyframesRequest, DeleteKeyframesResponse, DeleteSequenceKeyframe, DeleteStaticFileRequest, DeleteStaticFileResponse, DownloadRemoteAssetRequest, DownloadRemoteAssetResponse, DuplicateEffectRequest, DuplicateEffectRequestItem, DuplicateEffectResponse, DuplicateJsxNodeRequest, DuplicateJsxNodeResponse, InsertElementRequest, InsertElementResponse, InsertJsxElementRequest, InsertJsxElementResponse, InsertableCompositionElement, InsertableCompositionElementPosition, InstallPackageRequest, InstallPackageResponse, LogStudioErrorRequest, LogStudioErrorResponse, MoveEffectKeyframe, MoveKeyframesRequest, MoveKeyframesResponse, MoveSequenceKeyframe, OpenInEditorRequest, OpenInEditorResponse, OpenInFileExplorerRequest, PasteEffectsRequest, PasteEffectsResponse, ProjectInfoRequest, ProjectInfoResponse, RedoRequest, RedoResponse, RemoveRenderRequest, RenameStaticFileRequest, RenameStaticFileResponse, ReorderEffectRequest, ReorderEffectResponse, ReorderSequencePosition, ReorderSequenceRequest, ReorderSequenceResponse, RestartStudioRequest, RestartStudioResponse, SaveEffectPropsRequest, SaveEffectPropsResponse, SaveSequencePropEdit, SaveSequencePropsRequest, SaveSequencePropsResponse, SaveSequencePropsResult, SimpleDiff, SubscribeToDefaultPropsRequest, SubscribeToDefaultPropsResponse, SubscribeToFileExistenceRequest, SubscribeToFileExistenceResponse, SubscribeToSequencePropsRequest, SubscribeToSequencePropsResponse, UndoRequest, UndoResponse, UnsubscribeFromDefaultPropsRequest, UnsubscribeFromFileExistenceRequest, UnsubscribeFromSequencePropsRequest, UpdateAvailableRequest, UpdateAvailableResponse, UpdateDefaultPropsRequest, UpdateDefaultPropsResponse, UpdateEffectKeyframeSettingsRequest, UpdateEffectKeyframeSettingsResponse, UpdateSequenceKeyframeSettingsRequest, UpdateSequenceKeyframeSettingsResponse, type AddEffectKeyframe, type AddSequenceKeyframe, type KeyframeSettings, } from './api-requests';
3
3
  export { ASSET_DRAG_MIME_TYPE, makeAssetDragData, parseAssetDragData, type AssetDragData, } from './asset-drag-data';
4
4
  export type { ApplyVisualControlCodemod, RecastCodemod } from './codemods';
5
5
  export { COMPONENT_DRAG_MIME_TYPE, areComponentProps, isComponentIdentifier, isComponentImportPath, makeComponentDragData, parseComponentDragData, type ComponentDimensions, type ComponentDragData, type ComponentProp, } from './component-drag-data';
6
6
  export { DEFAULT_BUFFER_STATE_DELAY_IN_MILLISECONDS } from './default-buffer-state-delay-in-milliseconds';
7
- export { KEYFRAME_EASING_PRESETS, LINEAR_KEYFRAME_EASING, type KeyframeEasing, type KeyframeEasingPreset, } from './keyframe-easing-presets';
8
7
  export { detectFileType, isImageFileType, type FileDimensions, type FileType, type ImageFileType, } from './detect-file-type';
9
8
  export { parseEasingClipboardData, parseEasingClipboardDataResult, type EasingClipboardData, type EasingClipboardDataParseResult, } from './easing-clipboard-data';
9
+ export { EFFECT_CATALOG, getEffectCatalogCategories, getEffectDocumentationLink, getEffectDocumentationPath, getEffectPreviewAlt, getEffectPreviewSource, makeEffectDragDataFromCatalogItem, type EffectCatalogCategory, type EffectCatalogItem, } from './effect-catalog';
10
10
  export { parseEffectClipboardData, parseEffectClipboardDataResult, parseEffectPropClipboardData, parseEffectPropClipboardDataResult, type EffectClipboardClamping, type EffectClipboardData, type EffectClipboardDataParseResult, type EffectClipboardEasing, type EffectClipboardExtrapolateType, type EffectClipboardInterpolationFunction, type EffectClipboardKeyframe, type EffectClipboardKeyframedParam, type EffectClipboardParam, type EffectClipboardPasteType, type EffectClipboardSnapshot, type EffectClipboardStaticParam, type EffectPropClipboardData, type EffectPropClipboardDataParseResult, } from './effect-clipboard-data';
11
11
  export { EFFECT_DRAG_MIME_TYPE, parseEffectDragData, type EffectDragData, } from './effect-drag-data';
12
- export { EFFECT_CATALOG, getEffectCatalogCategories, getEffectDocumentationLink, getEffectDocumentationPath, getEffectPreviewAlt, getEffectPreviewSource, makeEffectDragDataFromCatalogItem, type EffectCatalogCategory, type EffectCatalogItem, } from './effect-catalog';
12
+ export { ELEMENT_DRAG_MIME_TYPE, getElementComponentNameFromSourceCode, isLowercaseElementFileName, makeElementDragData, makeElementFileNameFromSlug, parseElementDragData, type ElementDragData, } from './element-drag-data';
13
13
  export { EventSourceEvent } from './event-source-event';
14
14
  export { formatBytes } from './format-bytes';
15
15
  export { getAllSchemaKeys } from './get-all-keys';
@@ -18,18 +18,19 @@ export { ErrorLocation, getLocationFromBuildError, } from './get-location-from-b
18
18
  export { getProjectName } from './get-project-name';
19
19
  export type { GitSource } from './git-source';
20
20
  export { HotMiddlewareMessage, HotMiddlewareOptions, ModuleMap, hotMiddlewareOptions, } from './hot-middleware';
21
- export { getKeyframeInterpolationFunction, getKeyframeInterpolationFunctionForSchemaField, isKeyframeInterpolationFunction, isSchemaFieldKeyframable, isInteractivitySchemaFieldKeyframable, keyframeInterpolationFunctions, type KeyframeInterpolationFunction, } from './keyframe-interpolation-function';
22
- export { DEFAULT_SPRING_EASING, parseSpringEasingConfig, type SpringKeyframeEasing, } from './parse-spring-easing-config';
21
+ export { KEYFRAME_EASING_PRESETS, LINEAR_KEYFRAME_EASING, type KeyframeEasing, type KeyframeEasingPreset, } from './keyframe-easing-presets';
22
+ export { getKeyframeInterpolationFunction, getKeyframeInterpolationFunctionForSchemaField, isInteractivitySchemaFieldKeyframable, isKeyframeInterpolationFunction, isSchemaFieldKeyframable, keyframeInterpolationFunctions, type KeyframeInterpolationFunction, } from './keyframe-interpolation-function';
23
23
  export { DEFAULT_TIMELINE_TRACKS } from './max-timeline-tracks';
24
24
  export { Pkgs, apiDocs, descriptions, extraPackages, installableMap, packages, type ExtraPackage, } from './package-info';
25
25
  export { PackageManager } from './package-manager';
26
+ export { DEFAULT_SPRING_EASING, parseSpringEasingConfig, type SpringKeyframeEasing, } from './parse-spring-easing-config';
26
27
  export { ProjectInfo } from './project-info';
27
28
  export type { RenderDefaults } from './render-defaults';
28
29
  export { AggregateRenderProgress, ArtifactProgress, BrowserDownloadState, BrowserProgressLog, BundlingState, CopyingState, DownloadProgress, JobProgressCallback, RenderJob, RenderJobWithCleanup, RenderingProgressInput, RequiredChromiumOptions, StitchingProgressInput, UiOpenGlOptions, } from './render-job';
29
30
  export type { CompletedClientRender } from './render-job';
30
31
  export { getRequiredPackageForEffectImportPath, getRequiredPackageForInsertableElement, } from './required-package';
31
- export { SCHEMA_FIELD_ROW_HEIGHT, getEffectFieldsToShow, getFieldsToShow, } from './schema-field-info';
32
- export type { AnySchemaFieldInfo, DragOverrides, EffectSchemaFieldInfo, PropStatuses, SchemaFieldInfo, SequenceControls, InteractivitySchemaFieldInfo, } from './schema-field-info';
32
+ export { SCHEMA_FIELD_GROUPS, SCHEMA_FIELD_ROW_HEIGHT, getEffectFieldsToShow, getFieldsToShow, getSchemaFieldGroup, } from './schema-field-info';
33
+ export type { AnySchemaFieldInfo, DragOverrides, EffectSchemaFieldInfo, InteractivitySchemaFieldInfo, PropStatuses, SchemaFieldGroup, SchemaFieldGroupInfo, SchemaFieldInfo, SequenceControls, } from './schema-field-info';
33
34
  export { SFX_DRAG_MIME_TYPE, parseSfxDragData, type SfxDragData, } from './sfx-drag-data';
34
35
  export { ScriptLine, SomeStackFrame, StackFrame, SymbolicatedStackFrame, } from './stack-types';
35
36
  export { EnumPath, stringifyDefaultProps } from './stringify-default-props';
package/dist/index.js CHANGED
@@ -14,8 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.installableMap = exports.extraPackages = exports.descriptions = exports.apiDocs = exports.DEFAULT_TIMELINE_TRACKS = exports.parseSpringEasingConfig = exports.DEFAULT_SPRING_EASING = exports.keyframeInterpolationFunctions = exports.isInteractivitySchemaFieldKeyframable = exports.isSchemaFieldKeyframable = exports.isKeyframeInterpolationFunction = exports.getKeyframeInterpolationFunctionForSchemaField = exports.getKeyframeInterpolationFunction = exports.hotMiddlewareOptions = exports.getProjectName = exports.getLocationFromBuildError = exports.getDefaultOutLocation = exports.getAllSchemaKeys = exports.formatBytes = exports.makeEffectDragDataFromCatalogItem = exports.getEffectPreviewSource = exports.getEffectPreviewAlt = exports.getEffectDocumentationPath = exports.getEffectDocumentationLink = exports.getEffectCatalogCategories = exports.EFFECT_CATALOG = exports.parseEffectDragData = exports.EFFECT_DRAG_MIME_TYPE = exports.parseEffectPropClipboardDataResult = exports.parseEffectPropClipboardData = exports.parseEffectClipboardDataResult = exports.parseEffectClipboardData = exports.parseEasingClipboardDataResult = exports.parseEasingClipboardData = exports.isImageFileType = exports.detectFileType = exports.LINEAR_KEYFRAME_EASING = exports.KEYFRAME_EASING_PRESETS = exports.DEFAULT_BUFFER_STATE_DELAY_IN_MILLISECONDS = exports.parseComponentDragData = exports.makeComponentDragData = exports.isComponentImportPath = exports.isComponentIdentifier = exports.areComponentProps = exports.COMPONENT_DRAG_MIME_TYPE = exports.parseAssetDragData = exports.makeAssetDragData = exports.ASSET_DRAG_MIME_TYPE = exports.stripAnsi = exports.splitAnsi = void 0;
18
- exports.isUrl = exports.stringifySequenceSubscriptionKey = exports.stringifySequenceExpandedRowKey = exports.optimisticUpdateSequenceKeyframeSettings = exports.optimisticUpdateEffectKeyframeSettings = exports.optimisticUpdateForPropStatuses = exports.optimisticUpdateForEffectPropStatuses = exports.optimisticMoveSequenceKeyframes = exports.optimisticMoveEffectKeyframes = exports.moveKeyframesInPropStatus = exports.canMoveKeyframesWithoutCollisions = exports.optimisticDeleteSequenceKeyframes = exports.optimisticDeleteSequenceKeyframe = exports.optimisticDeleteEffectKeyframes = exports.optimisticDeleteEffectKeyframe = exports.optimisticAddSequenceKeyframe = exports.optimisticAddEffectKeyframe = exports.stringifyDefaultProps = exports.parseSfxDragData = exports.SFX_DRAG_MIME_TYPE = exports.getFieldsToShow = exports.getEffectFieldsToShow = exports.SCHEMA_FIELD_ROW_HEIGHT = exports.getRequiredPackageForInsertableElement = exports.getRequiredPackageForEffectImportPath = exports.packages = void 0;
17
+ exports.DEFAULT_TIMELINE_TRACKS = exports.keyframeInterpolationFunctions = exports.isSchemaFieldKeyframable = exports.isKeyframeInterpolationFunction = exports.isInteractivitySchemaFieldKeyframable = exports.getKeyframeInterpolationFunctionForSchemaField = exports.getKeyframeInterpolationFunction = exports.LINEAR_KEYFRAME_EASING = exports.KEYFRAME_EASING_PRESETS = exports.hotMiddlewareOptions = exports.getProjectName = exports.getLocationFromBuildError = exports.getDefaultOutLocation = exports.getAllSchemaKeys = exports.formatBytes = exports.parseElementDragData = exports.makeElementFileNameFromSlug = exports.makeElementDragData = exports.isLowercaseElementFileName = exports.getElementComponentNameFromSourceCode = exports.ELEMENT_DRAG_MIME_TYPE = exports.parseEffectDragData = exports.EFFECT_DRAG_MIME_TYPE = exports.parseEffectPropClipboardDataResult = exports.parseEffectPropClipboardData = exports.parseEffectClipboardDataResult = exports.parseEffectClipboardData = exports.makeEffectDragDataFromCatalogItem = exports.getEffectPreviewSource = exports.getEffectPreviewAlt = exports.getEffectDocumentationPath = exports.getEffectDocumentationLink = exports.getEffectCatalogCategories = exports.EFFECT_CATALOG = exports.parseEasingClipboardDataResult = exports.parseEasingClipboardData = exports.isImageFileType = exports.detectFileType = exports.DEFAULT_BUFFER_STATE_DELAY_IN_MILLISECONDS = exports.parseComponentDragData = exports.makeComponentDragData = exports.isComponentImportPath = exports.isComponentIdentifier = exports.areComponentProps = exports.COMPONENT_DRAG_MIME_TYPE = exports.parseAssetDragData = exports.makeAssetDragData = exports.ASSET_DRAG_MIME_TYPE = exports.stripAnsi = exports.splitAnsi = void 0;
18
+ exports.isUrl = exports.stringifySequenceSubscriptionKey = exports.stringifySequenceExpandedRowKey = exports.optimisticUpdateSequenceKeyframeSettings = exports.optimisticUpdateEffectKeyframeSettings = exports.optimisticUpdateForPropStatuses = exports.optimisticUpdateForEffectPropStatuses = exports.optimisticMoveSequenceKeyframes = exports.optimisticMoveEffectKeyframes = exports.moveKeyframesInPropStatus = exports.canMoveKeyframesWithoutCollisions = exports.optimisticDeleteSequenceKeyframes = exports.optimisticDeleteSequenceKeyframe = exports.optimisticDeleteEffectKeyframes = exports.optimisticDeleteEffectKeyframe = exports.optimisticAddSequenceKeyframe = exports.optimisticAddEffectKeyframe = exports.stringifyDefaultProps = exports.parseSfxDragData = exports.SFX_DRAG_MIME_TYPE = exports.getSchemaFieldGroup = exports.getFieldsToShow = exports.getEffectFieldsToShow = exports.SCHEMA_FIELD_ROW_HEIGHT = exports.SCHEMA_FIELD_GROUPS = exports.getRequiredPackageForInsertableElement = exports.getRequiredPackageForEffectImportPath = exports.parseSpringEasingConfig = exports.DEFAULT_SPRING_EASING = exports.packages = exports.installableMap = exports.extraPackages = exports.descriptions = exports.apiDocs = void 0;
19
19
  const ansi_1 = require("./ansi");
20
20
  Object.defineProperty(exports, "splitAnsi", { enumerable: true, get: function () { return ansi_1.splitAnsi; } });
21
21
  Object.defineProperty(exports, "stripAnsi", { enumerable: true, get: function () { return ansi_1.stripAnsi; } });
@@ -33,23 +33,12 @@ Object.defineProperty(exports, "makeComponentDragData", { enumerable: true, get:
33
33
  Object.defineProperty(exports, "parseComponentDragData", { enumerable: true, get: function () { return component_drag_data_1.parseComponentDragData; } });
34
34
  const default_buffer_state_delay_in_milliseconds_1 = require("./default-buffer-state-delay-in-milliseconds");
35
35
  Object.defineProperty(exports, "DEFAULT_BUFFER_STATE_DELAY_IN_MILLISECONDS", { enumerable: true, get: function () { return default_buffer_state_delay_in_milliseconds_1.DEFAULT_BUFFER_STATE_DELAY_IN_MILLISECONDS; } });
36
- const keyframe_easing_presets_1 = require("./keyframe-easing-presets");
37
- Object.defineProperty(exports, "KEYFRAME_EASING_PRESETS", { enumerable: true, get: function () { return keyframe_easing_presets_1.KEYFRAME_EASING_PRESETS; } });
38
- Object.defineProperty(exports, "LINEAR_KEYFRAME_EASING", { enumerable: true, get: function () { return keyframe_easing_presets_1.LINEAR_KEYFRAME_EASING; } });
39
36
  const detect_file_type_1 = require("./detect-file-type");
40
37
  Object.defineProperty(exports, "detectFileType", { enumerable: true, get: function () { return detect_file_type_1.detectFileType; } });
41
38
  Object.defineProperty(exports, "isImageFileType", { enumerable: true, get: function () { return detect_file_type_1.isImageFileType; } });
42
39
  const easing_clipboard_data_1 = require("./easing-clipboard-data");
43
40
  Object.defineProperty(exports, "parseEasingClipboardData", { enumerable: true, get: function () { return easing_clipboard_data_1.parseEasingClipboardData; } });
44
41
  Object.defineProperty(exports, "parseEasingClipboardDataResult", { enumerable: true, get: function () { return easing_clipboard_data_1.parseEasingClipboardDataResult; } });
45
- const effect_clipboard_data_1 = require("./effect-clipboard-data");
46
- Object.defineProperty(exports, "parseEffectClipboardData", { enumerable: true, get: function () { return effect_clipboard_data_1.parseEffectClipboardData; } });
47
- Object.defineProperty(exports, "parseEffectClipboardDataResult", { enumerable: true, get: function () { return effect_clipboard_data_1.parseEffectClipboardDataResult; } });
48
- Object.defineProperty(exports, "parseEffectPropClipboardData", { enumerable: true, get: function () { return effect_clipboard_data_1.parseEffectPropClipboardData; } });
49
- Object.defineProperty(exports, "parseEffectPropClipboardDataResult", { enumerable: true, get: function () { return effect_clipboard_data_1.parseEffectPropClipboardDataResult; } });
50
- const effect_drag_data_1 = require("./effect-drag-data");
51
- Object.defineProperty(exports, "EFFECT_DRAG_MIME_TYPE", { enumerable: true, get: function () { return effect_drag_data_1.EFFECT_DRAG_MIME_TYPE; } });
52
- Object.defineProperty(exports, "parseEffectDragData", { enumerable: true, get: function () { return effect_drag_data_1.parseEffectDragData; } });
53
42
  const effect_catalog_1 = require("./effect-catalog");
54
43
  Object.defineProperty(exports, "EFFECT_CATALOG", { enumerable: true, get: function () { return effect_catalog_1.EFFECT_CATALOG; } });
55
44
  Object.defineProperty(exports, "getEffectCatalogCategories", { enumerable: true, get: function () { return effect_catalog_1.getEffectCatalogCategories; } });
@@ -58,6 +47,21 @@ Object.defineProperty(exports, "getEffectDocumentationPath", { enumerable: true,
58
47
  Object.defineProperty(exports, "getEffectPreviewAlt", { enumerable: true, get: function () { return effect_catalog_1.getEffectPreviewAlt; } });
59
48
  Object.defineProperty(exports, "getEffectPreviewSource", { enumerable: true, get: function () { return effect_catalog_1.getEffectPreviewSource; } });
60
49
  Object.defineProperty(exports, "makeEffectDragDataFromCatalogItem", { enumerable: true, get: function () { return effect_catalog_1.makeEffectDragDataFromCatalogItem; } });
50
+ const effect_clipboard_data_1 = require("./effect-clipboard-data");
51
+ Object.defineProperty(exports, "parseEffectClipboardData", { enumerable: true, get: function () { return effect_clipboard_data_1.parseEffectClipboardData; } });
52
+ Object.defineProperty(exports, "parseEffectClipboardDataResult", { enumerable: true, get: function () { return effect_clipboard_data_1.parseEffectClipboardDataResult; } });
53
+ Object.defineProperty(exports, "parseEffectPropClipboardData", { enumerable: true, get: function () { return effect_clipboard_data_1.parseEffectPropClipboardData; } });
54
+ Object.defineProperty(exports, "parseEffectPropClipboardDataResult", { enumerable: true, get: function () { return effect_clipboard_data_1.parseEffectPropClipboardDataResult; } });
55
+ const effect_drag_data_1 = require("./effect-drag-data");
56
+ Object.defineProperty(exports, "EFFECT_DRAG_MIME_TYPE", { enumerable: true, get: function () { return effect_drag_data_1.EFFECT_DRAG_MIME_TYPE; } });
57
+ Object.defineProperty(exports, "parseEffectDragData", { enumerable: true, get: function () { return effect_drag_data_1.parseEffectDragData; } });
58
+ const element_drag_data_1 = require("./element-drag-data");
59
+ Object.defineProperty(exports, "ELEMENT_DRAG_MIME_TYPE", { enumerable: true, get: function () { return element_drag_data_1.ELEMENT_DRAG_MIME_TYPE; } });
60
+ Object.defineProperty(exports, "getElementComponentNameFromSourceCode", { enumerable: true, get: function () { return element_drag_data_1.getElementComponentNameFromSourceCode; } });
61
+ Object.defineProperty(exports, "isLowercaseElementFileName", { enumerable: true, get: function () { return element_drag_data_1.isLowercaseElementFileName; } });
62
+ Object.defineProperty(exports, "makeElementDragData", { enumerable: true, get: function () { return element_drag_data_1.makeElementDragData; } });
63
+ Object.defineProperty(exports, "makeElementFileNameFromSlug", { enumerable: true, get: function () { return element_drag_data_1.makeElementFileNameFromSlug; } });
64
+ Object.defineProperty(exports, "parseElementDragData", { enumerable: true, get: function () { return element_drag_data_1.parseElementDragData; } });
61
65
  const format_bytes_1 = require("./format-bytes");
62
66
  Object.defineProperty(exports, "formatBytes", { enumerable: true, get: function () { return format_bytes_1.formatBytes; } });
63
67
  const get_all_keys_1 = require("./get-all-keys");
@@ -70,16 +74,16 @@ const get_project_name_1 = require("./get-project-name");
70
74
  Object.defineProperty(exports, "getProjectName", { enumerable: true, get: function () { return get_project_name_1.getProjectName; } });
71
75
  const hot_middleware_1 = require("./hot-middleware");
72
76
  Object.defineProperty(exports, "hotMiddlewareOptions", { enumerable: true, get: function () { return hot_middleware_1.hotMiddlewareOptions; } });
77
+ const keyframe_easing_presets_1 = require("./keyframe-easing-presets");
78
+ Object.defineProperty(exports, "KEYFRAME_EASING_PRESETS", { enumerable: true, get: function () { return keyframe_easing_presets_1.KEYFRAME_EASING_PRESETS; } });
79
+ Object.defineProperty(exports, "LINEAR_KEYFRAME_EASING", { enumerable: true, get: function () { return keyframe_easing_presets_1.LINEAR_KEYFRAME_EASING; } });
73
80
  const keyframe_interpolation_function_1 = require("./keyframe-interpolation-function");
74
81
  Object.defineProperty(exports, "getKeyframeInterpolationFunction", { enumerable: true, get: function () { return keyframe_interpolation_function_1.getKeyframeInterpolationFunction; } });
75
82
  Object.defineProperty(exports, "getKeyframeInterpolationFunctionForSchemaField", { enumerable: true, get: function () { return keyframe_interpolation_function_1.getKeyframeInterpolationFunctionForSchemaField; } });
83
+ Object.defineProperty(exports, "isInteractivitySchemaFieldKeyframable", { enumerable: true, get: function () { return keyframe_interpolation_function_1.isInteractivitySchemaFieldKeyframable; } });
76
84
  Object.defineProperty(exports, "isKeyframeInterpolationFunction", { enumerable: true, get: function () { return keyframe_interpolation_function_1.isKeyframeInterpolationFunction; } });
77
85
  Object.defineProperty(exports, "isSchemaFieldKeyframable", { enumerable: true, get: function () { return keyframe_interpolation_function_1.isSchemaFieldKeyframable; } });
78
- Object.defineProperty(exports, "isInteractivitySchemaFieldKeyframable", { enumerable: true, get: function () { return keyframe_interpolation_function_1.isInteractivitySchemaFieldKeyframable; } });
79
86
  Object.defineProperty(exports, "keyframeInterpolationFunctions", { enumerable: true, get: function () { return keyframe_interpolation_function_1.keyframeInterpolationFunctions; } });
80
- const parse_spring_easing_config_1 = require("./parse-spring-easing-config");
81
- Object.defineProperty(exports, "DEFAULT_SPRING_EASING", { enumerable: true, get: function () { return parse_spring_easing_config_1.DEFAULT_SPRING_EASING; } });
82
- Object.defineProperty(exports, "parseSpringEasingConfig", { enumerable: true, get: function () { return parse_spring_easing_config_1.parseSpringEasingConfig; } });
83
87
  const max_timeline_tracks_1 = require("./max-timeline-tracks");
84
88
  Object.defineProperty(exports, "DEFAULT_TIMELINE_TRACKS", { enumerable: true, get: function () { return max_timeline_tracks_1.DEFAULT_TIMELINE_TRACKS; } });
85
89
  const package_info_1 = require("./package-info");
@@ -88,13 +92,18 @@ Object.defineProperty(exports, "descriptions", { enumerable: true, get: function
88
92
  Object.defineProperty(exports, "extraPackages", { enumerable: true, get: function () { return package_info_1.extraPackages; } });
89
93
  Object.defineProperty(exports, "installableMap", { enumerable: true, get: function () { return package_info_1.installableMap; } });
90
94
  Object.defineProperty(exports, "packages", { enumerable: true, get: function () { return package_info_1.packages; } });
95
+ const parse_spring_easing_config_1 = require("./parse-spring-easing-config");
96
+ Object.defineProperty(exports, "DEFAULT_SPRING_EASING", { enumerable: true, get: function () { return parse_spring_easing_config_1.DEFAULT_SPRING_EASING; } });
97
+ Object.defineProperty(exports, "parseSpringEasingConfig", { enumerable: true, get: function () { return parse_spring_easing_config_1.parseSpringEasingConfig; } });
91
98
  const required_package_1 = require("./required-package");
92
99
  Object.defineProperty(exports, "getRequiredPackageForEffectImportPath", { enumerable: true, get: function () { return required_package_1.getRequiredPackageForEffectImportPath; } });
93
100
  Object.defineProperty(exports, "getRequiredPackageForInsertableElement", { enumerable: true, get: function () { return required_package_1.getRequiredPackageForInsertableElement; } });
94
101
  const schema_field_info_1 = require("./schema-field-info");
102
+ Object.defineProperty(exports, "SCHEMA_FIELD_GROUPS", { enumerable: true, get: function () { return schema_field_info_1.SCHEMA_FIELD_GROUPS; } });
95
103
  Object.defineProperty(exports, "SCHEMA_FIELD_ROW_HEIGHT", { enumerable: true, get: function () { return schema_field_info_1.SCHEMA_FIELD_ROW_HEIGHT; } });
96
104
  Object.defineProperty(exports, "getEffectFieldsToShow", { enumerable: true, get: function () { return schema_field_info_1.getEffectFieldsToShow; } });
97
105
  Object.defineProperty(exports, "getFieldsToShow", { enumerable: true, get: function () { return schema_field_info_1.getFieldsToShow; } });
106
+ Object.defineProperty(exports, "getSchemaFieldGroup", { enumerable: true, get: function () { return schema_field_info_1.getSchemaFieldGroup; } });
98
107
  const sfx_drag_data_1 = require("./sfx-drag-data");
99
108
  Object.defineProperty(exports, "SFX_DRAG_MIME_TYPE", { enumerable: true, get: function () { return sfx_drag_data_1.SFX_DRAG_MIME_TYPE; } });
100
109
  Object.defineProperty(exports, "parseSfxDragData", { enumerable: true, get: function () { return sfx_drag_data_1.parseSfxDragData; } });
@@ -1,7 +1,7 @@
1
1
  import type { CanUpdateSequencePropStatusEasing } from 'remotion';
2
2
  export type KeyframeEasing = CanUpdateSequencePropStatusEasing;
3
3
  export type KeyframeEasingPreset = {
4
- readonly id: 'ease-in' | 'ease-out' | 'ease-in-out' | 'spring' | 'bouncy-spring';
4
+ readonly id: 'ease-in' | 'ease-out' | 'ease-in-out' | 'spring' | 'bouncy-spring' | 'tail-spring';
5
5
  readonly label: string;
6
6
  readonly easing: KeyframeEasing;
7
7
  };
@@ -18,12 +18,27 @@ exports.KEYFRAME_EASING_PRESETS = [
18
18
  label: 'Ease in-out',
19
19
  easing: { type: 'bezier', x1: 0.42, y1: 0, x2: 0.58, y2: 1 },
20
20
  },
21
+ {
22
+ id: 'tail-spring',
23
+ label: 'Tail spring',
24
+ easing: {
25
+ type: 'spring',
26
+ allowTail: true,
27
+ damping: 200,
28
+ durationRestThreshold: 0.02,
29
+ mass: 1,
30
+ overshootClamping: false,
31
+ stiffness: 100,
32
+ },
33
+ },
21
34
  {
22
35
  id: 'spring',
23
36
  label: 'Spring',
24
37
  easing: {
25
38
  type: 'spring',
39
+ allowTail: true,
26
40
  damping: 10,
41
+ durationRestThreshold: 0.02,
27
42
  mass: 1,
28
43
  overshootClamping: false,
29
44
  stiffness: 100,
@@ -34,7 +49,9 @@ exports.KEYFRAME_EASING_PRESETS = [
34
49
  label: 'Bouncy spring',
35
50
  easing: {
36
51
  type: 'spring',
52
+ allowTail: true,
37
53
  damping: 5,
54
+ durationRestThreshold: 0.02,
38
55
  mass: 1,
39
56
  overshootClamping: false,
40
57
  stiffness: 120,
@@ -13,7 +13,9 @@ const isInteractivitySchemaFieldKeyframable = (field) => {
13
13
  if (!field) {
14
14
  return true;
15
15
  }
16
- if (field.type === 'array' || field.type === 'enum') {
16
+ if (field.type === 'array' ||
17
+ field.type === 'boolean' ||
18
+ field.type === 'enum') {
17
19
  return false;
18
20
  }
19
21
  return field.keyframable !== false;
@@ -3,6 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.optimisticAddEffectKeyframe = exports.optimisticAddSequenceKeyframe = void 0;
4
4
  const keyframe_easing_presets_1 = require("./keyframe-easing-presets");
5
5
  const keyframe_interpolation_function_1 = require("./keyframe-interpolation-function");
6
+ const getEasingIndexToDuplicate = ({ insertedKeyframeIndex, easingLength, keyframeCount, }) => {
7
+ const isSplittingExistingSegment = insertedKeyframeIndex > 0 && insertedKeyframeIndex < keyframeCount - 1;
8
+ if (!isSplittingExistingSegment || easingLength === 0) {
9
+ return null;
10
+ }
11
+ return Math.min(insertedKeyframeIndex - 1, easingLength - 1);
12
+ };
6
13
  const addKeyframeToPropStatus = ({ status, fieldKey, frame, value, schema, }) => {
7
14
  var _a;
8
15
  if (status.status === 'keyframed') {
@@ -16,6 +23,16 @@ const addKeyframeToPropStatus = ({ status, fieldKey, frame, value, schema, }) =>
16
23
  }
17
24
  const keyframes = [...status.keyframes, { frame, value }].sort((first, second) => first.frame - second.frame);
18
25
  const easing = [...status.easing];
26
+ const insertedKeyframeIndex = keyframes.findIndex((keyframe) => keyframe.frame === frame);
27
+ const easingIndexToDuplicate = getEasingIndexToDuplicate({
28
+ insertedKeyframeIndex,
29
+ easingLength: easing.length,
30
+ keyframeCount: keyframes.length,
31
+ });
32
+ const easingToDuplicate = easingIndexToDuplicate === null
33
+ ? keyframe_easing_presets_1.LINEAR_KEYFRAME_EASING
34
+ : easing[easingIndexToDuplicate];
35
+ easing.splice(insertedKeyframeIndex, 0, easingToDuplicate);
19
36
  while (easing.length < keyframes.length - 1) {
20
37
  easing.push(keyframe_easing_presets_1.LINEAR_KEYFRAME_EASING);
21
38
  }
@@ -43,17 +60,45 @@ const addKeyframeToPropStatus = ({ status, fieldKey, frame, value, schema, }) =>
43
60
  }
44
61
  return status;
45
62
  };
63
+ const findFieldInSchema = (schema, key) => {
64
+ if (key in schema) {
65
+ return schema[key];
66
+ }
67
+ for (const field of Object.values(schema)) {
68
+ if (field.type !== 'enum') {
69
+ continue;
70
+ }
71
+ for (const variant of Object.values(field.variants)) {
72
+ const found = findFieldInSchema(variant, key);
73
+ if (found) {
74
+ return found;
75
+ }
76
+ }
77
+ }
78
+ return undefined;
79
+ };
80
+ const getMissingPropStatus = ({ schema, fieldKey, }) => {
81
+ const field = schema ? findFieldInSchema(schema, fieldKey) : undefined;
82
+ if (field && field.type !== 'hidden' && field.default !== undefined) {
83
+ return {
84
+ status: 'static',
85
+ codeValue: field.default,
86
+ };
87
+ }
88
+ return {
89
+ status: 'static',
90
+ codeValue: undefined,
91
+ };
92
+ };
46
93
  const optimisticAddSequenceKeyframe = ({ previous, fieldKey, frame, value, schema, }) => {
94
+ var _a;
47
95
  if (!previous.canUpdate) {
48
96
  return previous;
49
97
  }
50
98
  if (!(0, keyframe_interpolation_function_1.isSchemaFieldKeyframable)({ schema: schema !== null && schema !== void 0 ? schema : null, key: fieldKey })) {
51
99
  return previous;
52
100
  }
53
- const status = previous.props[fieldKey];
54
- if (!status) {
55
- return previous;
56
- }
101
+ const status = (_a = previous.props[fieldKey]) !== null && _a !== void 0 ? _a : getMissingPropStatus({ schema: schema !== null && schema !== void 0 ? schema : null, fieldKey });
57
102
  return {
58
103
  ...previous,
59
104
  props: {
@@ -70,6 +115,7 @@ const optimisticAddSequenceKeyframe = ({ previous, fieldKey, frame, value, schem
70
115
  };
71
116
  exports.optimisticAddSequenceKeyframe = optimisticAddSequenceKeyframe;
72
117
  const optimisticAddEffectKeyframe = ({ previous, effectIndex, fieldKey, frame, value, schema, }) => {
118
+ var _a;
73
119
  if (!previous.canUpdate) {
74
120
  return previous;
75
121
  }
@@ -84,10 +130,7 @@ const optimisticAddEffectKeyframe = ({ previous, effectIndex, fieldKey, frame, v
84
130
  if (!target.canUpdate) {
85
131
  return previous;
86
132
  }
87
- const status = target.props[fieldKey];
88
- if (!status) {
89
- return previous;
90
- }
133
+ const status = (_a = target.props[fieldKey]) !== null && _a !== void 0 ? _a : getMissingPropStatus({ schema: schema !== null && schema !== void 0 ? schema : null, fieldKey });
91
134
  const updatedEffect = {
92
135
  ...target,
93
136
  props: {
@@ -1,6 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.optimisticDeleteEffectKeyframes = exports.optimisticDeleteEffectKeyframe = exports.optimisticDeleteSequenceKeyframes = exports.optimisticDeleteSequenceKeyframe = void 0;
4
+ const getEasingIndexToRemove = ({ removedKeyframeIndex, keyframeCountBeforeRemoval, }) => {
5
+ if (removedKeyframeIndex === 0) {
6
+ return 0;
7
+ }
8
+ if (removedKeyframeIndex === keyframeCountBeforeRemoval - 1) {
9
+ return removedKeyframeIndex - 1;
10
+ }
11
+ return removedKeyframeIndex;
12
+ };
4
13
  const removeKeyframeFromPropStatus = ({ status, frame, }) => {
5
14
  if (status.status !== 'keyframed') {
6
15
  return status;
@@ -21,7 +30,10 @@ const removeKeyframeFromPropStatus = ({ status, frame, }) => {
21
30
  // keyframe so the invariant keeps holding until the server responds.
22
31
  const easing = [...status.easing];
23
32
  if (easing.length > 0) {
24
- const easingIndexToRemove = index === 0 ? 0 : index - 1;
33
+ const easingIndexToRemove = getEasingIndexToRemove({
34
+ removedKeyframeIndex: index,
35
+ keyframeCountBeforeRemoval: status.keyframes.length,
36
+ });
25
37
  easing.splice(easingIndexToRemove, 1);
26
38
  }
27
39
  return {
@@ -1,6 +1,8 @@
1
1
  export type SpringKeyframeEasing = {
2
2
  readonly type: 'spring';
3
+ allowTail: boolean | null;
3
4
  damping: number;
5
+ durationRestThreshold: number | null;
4
6
  mass: number;
5
7
  overshootClamping: boolean;
6
8
  stiffness: number;
@@ -3,7 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseSpringEasingConfig = exports.DEFAULT_SPRING_EASING = void 0;
4
4
  exports.DEFAULT_SPRING_EASING = {
5
5
  type: 'spring',
6
+ allowTail: null,
6
7
  damping: 10,
8
+ durationRestThreshold: null,
7
9
  mass: 1,
8
10
  overshootClamping: false,
9
11
  stiffness: 100,
@@ -72,7 +74,10 @@ const parseSpringEasingConfig = (node) => {
72
74
  if (!key || !isAstNode(prop.value)) {
73
75
  return null;
74
76
  }
75
- if (key === 'damping' || key === 'mass' || key === 'stiffness') {
77
+ if (key === 'damping' ||
78
+ key === 'mass' ||
79
+ key === 'stiffness' ||
80
+ key === 'durationRestThreshold') {
76
81
  const numericValue = getNumericValue(prop.value);
77
82
  if (numericValue === null ||
78
83
  !Number.isFinite(numericValue) ||
@@ -82,12 +87,12 @@ const parseSpringEasingConfig = (node) => {
82
87
  spring[key] = numericValue;
83
88
  continue;
84
89
  }
85
- if (key === 'overshootClamping') {
90
+ if (key === 'overshootClamping' || key === 'allowTail') {
86
91
  const booleanValue = getBooleanValue(prop.value);
87
92
  if (booleanValue === null) {
88
93
  return null;
89
94
  }
90
- spring.overshootClamping = booleanValue;
95
+ spring[key] = booleanValue;
91
96
  continue;
92
97
  }
93
98
  return null;
@@ -6,6 +6,7 @@ export type SchemaFieldInfo = {
6
6
  typeName: SupportedSchemaType;
7
7
  rowHeight: number;
8
8
  fieldSchema: VisibleFieldSchema;
9
+ group: SchemaFieldGroup;
9
10
  };
10
11
  export type InteractivitySchemaFieldInfo = SchemaFieldInfo & {
11
12
  readonly kind: 'sequence-field';
@@ -17,6 +18,22 @@ export type EffectSchemaFieldInfo = SchemaFieldInfo & {
17
18
  };
18
19
  export type AnySchemaFieldInfo = InteractivitySchemaFieldInfo | EffectSchemaFieldInfo;
19
20
  export declare const SCHEMA_FIELD_ROW_HEIGHT = 22;
21
+ export type SchemaFieldGroup = 'controls' | 'transforms' | 'text';
22
+ export type SchemaFieldGroupInfo = {
23
+ readonly id: SchemaFieldGroup;
24
+ readonly label: string;
25
+ };
26
+ export declare const SCHEMA_FIELD_GROUPS: readonly [{
27
+ readonly id: "controls";
28
+ readonly label: "Controls";
29
+ }, {
30
+ readonly id: "transforms";
31
+ readonly label: "Transform";
32
+ }, {
33
+ readonly id: "text";
34
+ readonly label: "Text";
35
+ }];
36
+ export declare const getSchemaFieldGroup: (key: string) => SchemaFieldGroup;
20
37
  declare const SUPPORTED_SCHEMA_TYPES: readonly ["number", "boolean", "rotation-css", "rotation-degrees", "translate", "transform-origin", "scale", "uv-coordinate", "color", "array", "enum", "hidden"];
21
38
  type SupportedSchemaType = (typeof SUPPORTED_SCHEMA_TYPES)[number];
22
39
  export declare const getFieldsToShow: ({ getDragOverrides, propStatuses, nodePath, schema, currentRuntimeValueDotNotation, }: {
@@ -1,9 +1,54 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getEffectFieldsToShow = exports.getFieldsToShow = exports.SCHEMA_FIELD_ROW_HEIGHT = void 0;
3
+ exports.getEffectFieldsToShow = exports.getFieldsToShow = exports.getSchemaFieldGroup = exports.SCHEMA_FIELD_GROUPS = exports.SCHEMA_FIELD_ROW_HEIGHT = void 0;
4
4
  const remotion_1 = require("remotion");
5
5
  const no_react_1 = require("remotion/no-react");
6
6
  exports.SCHEMA_FIELD_ROW_HEIGHT = 22;
7
+ exports.SCHEMA_FIELD_GROUPS = [
8
+ { id: 'controls', label: 'Controls' },
9
+ { id: 'transforms', label: 'Transform' },
10
+ { id: 'text', label: 'Text' },
11
+ ];
12
+ const schemaFieldGroupOrder = exports.SCHEMA_FIELD_GROUPS.reduce((acc, group, index) => {
13
+ acc[group.id] = index;
14
+ return acc;
15
+ }, {});
16
+ const TRANSFORM_FIELD_KEYS = new Set([
17
+ 'style.transformOrigin',
18
+ 'style.translate',
19
+ 'style.scale',
20
+ 'style.rotate',
21
+ 'style.opacity',
22
+ ]);
23
+ const TEXT_FIELD_KEYS = new Set([
24
+ 'style.color',
25
+ 'style.fontSize',
26
+ 'style.lineHeight',
27
+ 'style.fontWeight',
28
+ 'style.fontStyle',
29
+ 'style.letterSpacing',
30
+ 'style.textAlign',
31
+ ]);
32
+ const getSchemaFieldGroup = (key) => {
33
+ if (TRANSFORM_FIELD_KEYS.has(key)) {
34
+ return 'transforms';
35
+ }
36
+ if (TEXT_FIELD_KEYS.has(key)) {
37
+ return 'text';
38
+ }
39
+ return 'controls';
40
+ };
41
+ exports.getSchemaFieldGroup = getSchemaFieldGroup;
42
+ const sortSchemaFields = (fields) => {
43
+ return fields
44
+ .map((field, index) => ({ field, index }))
45
+ .sort((a, b) => {
46
+ const groupDiff = schemaFieldGroupOrder[a.field.group] -
47
+ schemaFieldGroupOrder[b.field.group];
48
+ return groupDiff === 0 ? a.index - b.index : groupDiff;
49
+ })
50
+ .map(({ field }) => field);
51
+ };
7
52
  const SUPPORTED_SCHEMA_TYPES = [
8
53
  'number',
9
54
  'boolean',
@@ -60,7 +105,7 @@ const getFieldsToShow = ({ getDragOverrides, propStatuses, nodePath, schema, cur
60
105
  frame: null,
61
106
  });
62
107
  const activeSchema = remotion_1.Internals.flattenActiveSchema(schema, (key) => valuesDotNotation[key]);
63
- return Object.entries(activeSchema)
108
+ const fields = Object.entries(activeSchema)
64
109
  .map(([key, fieldSchema]) => {
65
110
  const typeName = fieldSchema.type;
66
111
  if (SUPPORTED_SCHEMA_TYPES.indexOf(typeName) === -1) {
@@ -87,9 +132,11 @@ const getFieldsToShow = ({ getDragOverrides, propStatuses, nodePath, schema, cur
87
132
  value: valuesDotNotation[key],
88
133
  }),
89
134
  fieldSchema,
135
+ group: (0, exports.getSchemaFieldGroup)(key),
90
136
  };
91
137
  })
92
138
  .filter(no_react_1.NoReactInternals.truthy);
139
+ return sortSchemaFields(fields);
93
140
  };
94
141
  exports.getFieldsToShow = getFieldsToShow;
95
142
  const getEffectFieldsToShow = ({ effect, effectIndex, nodePath, propStatuses, getEffectDragOverrides, }) => {
@@ -104,7 +151,7 @@ const getEffectFieldsToShow = ({ effect, effectIndex, nodePath, propStatuses, ge
104
151
  const activeSchema = remotion_1.Internals.flattenActiveSchema(effect.schema, (key) => {
105
152
  return getEffectFieldValue({ key, dragOverrides, effectStatus });
106
153
  });
107
- return Object.entries(activeSchema)
154
+ const fields = Object.entries(activeSchema)
108
155
  .map(([key, fieldSchema]) => {
109
156
  const typeName = fieldSchema.type;
110
157
  if (typeName === 'hidden') {
@@ -133,8 +180,10 @@ const getEffectFieldsToShow = ({ effect, effectIndex, nodePath, propStatuses, ge
133
180
  fieldSchema,
134
181
  effectSchema: effect.schema,
135
182
  effectIndex,
183
+ group: (0, exports.getSchemaFieldGroup)(key),
136
184
  };
137
185
  })
138
186
  .filter(no_react_1.NoReactInternals.truthy);
187
+ return sortSchemaFields(fields);
139
188
  };
140
189
  exports.getEffectFieldsToShow = getEffectFieldsToShow;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio-shared"
4
4
  },
5
5
  "name": "@remotion/studio-shared",
6
- "version": "4.0.481",
6
+ "version": "4.0.483",
7
7
  "description": "Internal package for shared objects between the Studio backend and frontend",
8
8
  "main": "dist",
9
9
  "scripts": {
@@ -20,11 +20,11 @@
20
20
  "url": "https://github.com/remotion-dev/remotion/issues"
21
21
  },
22
22
  "dependencies": {
23
- "remotion": "4.0.481"
23
+ "remotion": "4.0.483"
24
24
  },
25
25
  "devDependencies": {
26
- "@remotion/renderer": "4.0.481",
27
- "@remotion/eslint-config-internal": "4.0.481",
26
+ "@remotion/renderer": "4.0.483",
27
+ "@remotion/eslint-config-internal": "4.0.483",
28
28
  "eslint": "9.19.0",
29
29
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
30
30
  },