@remotion/studio-shared 4.0.477 → 4.0.478

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.
@@ -294,6 +294,19 @@ export type ReorderEffectResponse = {
294
294
  reason: string;
295
295
  stack: string;
296
296
  };
297
+ export type DuplicateEffectRequestItem = {
298
+ fileName: string;
299
+ sequenceNodePath: SequencePropsSubscriptionKey;
300
+ effectIndex: number;
301
+ };
302
+ export type DuplicateEffectRequest = DuplicateEffectRequestItem[];
303
+ export type DuplicateEffectResponse = {
304
+ success: true;
305
+ } | {
306
+ success: false;
307
+ reason: string;
308
+ stack: string;
309
+ };
297
310
  export type ReorderSequencePosition = 'before' | 'after';
298
311
  export type ReorderSequenceRequest = {
299
312
  fileName: string;
@@ -490,7 +503,7 @@ export type InsertableCompositionElement = {
490
503
  position: InsertableCompositionElementPosition | null;
491
504
  } | {
492
505
  type: 'asset';
493
- assetType: 'image' | 'video' | 'gif' | 'audio';
506
+ assetType: 'image' | 'video' | 'gif' | 'animated-image' | 'audio';
494
507
  src: string;
495
508
  srcType: 'static' | 'remote';
496
509
  dimensions: {
@@ -586,6 +599,7 @@ export type ApiRoutes = {
586
599
  '/api/save-effect-props': ReqAndRes<SaveEffectPropsRequest, SaveEffectPropsResponse>;
587
600
  '/api/add-effect': ReqAndRes<AddEffectRequest, AddEffectResponse>;
588
601
  '/api/reorder-effect': ReqAndRes<ReorderEffectRequest, ReorderEffectResponse>;
602
+ '/api/duplicate-effect': ReqAndRes<DuplicateEffectRequest, DuplicateEffectResponse>;
589
603
  '/api/reorder-sequence': ReqAndRes<ReorderSequenceRequest, ReorderSequenceResponse>;
590
604
  '/api/delete-keyframes': ReqAndRes<DeleteKeyframesRequest, DeleteKeyframesResponse>;
591
605
  '/api/move-keyframes': ReqAndRes<MoveKeyframesRequest, MoveKeyframesResponse>;
@@ -3,11 +3,16 @@ export type ComponentProp = {
3
3
  name: string;
4
4
  value: string | number | boolean;
5
5
  };
6
+ export type ComponentDimensions = {
7
+ height: number;
8
+ width: number;
9
+ };
6
10
  export type ComponentDragData = {
7
11
  type: 'remotion-component';
8
12
  version: 1;
9
13
  component: {
10
14
  componentName: string;
15
+ dimensions?: ComponentDimensions;
11
16
  importName: string;
12
17
  importPath: string;
13
18
  props: ComponentProp[];
@@ -18,8 +23,9 @@ export declare const isComponentImportPath: (value: unknown) => value is string;
18
23
  export declare const isComponentPropName: (value: unknown) => value is string;
19
24
  export declare const isComponentProp: (value: unknown) => value is ComponentProp;
20
25
  export declare const areComponentProps: (value: unknown) => value is ComponentProp[];
21
- export declare const makeComponentDragData: ({ componentName, importName, importPath, props, }: {
26
+ export declare const makeComponentDragData: ({ componentName, dimensions, importName, importPath, props, }: {
22
27
  componentName: string;
28
+ dimensions?: ComponentDimensions | null | undefined;
23
29
  importName: string;
24
30
  importPath: string;
25
31
  props: ComponentProp[];
@@ -51,12 +51,24 @@ const areComponentProps = (value) => {
51
51
  return true;
52
52
  };
53
53
  exports.areComponentProps = areComponentProps;
54
- const makeComponentDragData = ({ componentName, importName, importPath, props, }) => {
54
+ const isComponentDimensions = (value) => {
55
+ if (!isRecord(value)) {
56
+ return false;
57
+ }
58
+ return (typeof value.width === 'number' &&
59
+ Number.isFinite(value.width) &&
60
+ value.width >= 0 &&
61
+ typeof value.height === 'number' &&
62
+ Number.isFinite(value.height) &&
63
+ value.height >= 0);
64
+ };
65
+ const makeComponentDragData = ({ componentName, dimensions, importName, importPath, props, }) => {
55
66
  return {
56
67
  type: 'remotion-component',
57
68
  version: 1,
58
69
  component: {
59
70
  componentName,
71
+ ...(dimensions ? { dimensions } : {}),
60
72
  importName,
61
73
  importPath,
62
74
  props,
@@ -76,11 +88,12 @@ const parseComponentDragData = (value) => {
76
88
  if (!isRecord(parsed.component)) {
77
89
  return null;
78
90
  }
79
- const { componentName, importName, importPath, props } = parsed.component;
91
+ const { componentName, dimensions, importName, importPath, props } = parsed.component;
80
92
  if (!(0, exports.isComponentIdentifier)(componentName) ||
81
93
  !(0, exports.isComponentIdentifier)(importName) ||
82
94
  !(0, exports.isComponentImportPath)(importPath) ||
83
- !(0, exports.areComponentProps)(props)) {
95
+ !(0, exports.areComponentProps)(props) ||
96
+ (typeof dimensions !== 'undefined' && !isComponentDimensions(dimensions))) {
84
97
  return null;
85
98
  }
86
99
  return {
@@ -88,6 +101,7 @@ const parseComponentDragData = (value) => {
88
101
  version: 1,
89
102
  component: {
90
103
  componentName,
104
+ ...(dimensions ? { dimensions } : {}),
91
105
  importName,
92
106
  importPath,
93
107
  props,
@@ -47,6 +47,10 @@ export type PngType = {
47
47
  type: 'png';
48
48
  dimensions: FileDimensions | null;
49
49
  };
50
+ export type ApngType = {
51
+ type: 'apng';
52
+ dimensions: FileDimensions | null;
53
+ };
50
54
  export type JpegType = {
51
55
  type: 'jpeg';
52
56
  dimensions: FileDimensions | null;
@@ -65,7 +69,7 @@ export type PdfType = {
65
69
  export type UnknownType = {
66
70
  type: 'unknown';
67
71
  };
68
- export type FileType = JpegType | WebpType | RiffType | WebmType | WavType | PdfType | AacType | IsoBaseMediaType | TransportStreamType | Mp3Type | GifType | PngType | BmpType | AacType | FlacType | M3uType | UnknownType;
69
- export type ImageFileType = JpegType | WebpType | GifType | PngType | BmpType;
72
+ export type FileType = JpegType | WebpType | RiffType | WebmType | WavType | PdfType | AacType | IsoBaseMediaType | TransportStreamType | Mp3Type | GifType | PngType | ApngType | BmpType | AacType | FlacType | M3uType | UnknownType;
73
+ export type ImageFileType = JpegType | WebpType | GifType | PngType | ApngType | BmpType;
70
74
  export declare const isImageFileType: (fileType: FileType) => fileType is ImageFileType;
71
75
  export declare const detectFileType: (data: Uint8Array<ArrayBufferLike>) => FileType;
@@ -69,12 +69,15 @@ const isM3u = (data) => {
69
69
  return new TextDecoder('utf-8').decode(data.slice(0, 7)) === '#EXTM3U';
70
70
  };
71
71
  exports.isM3u = isM3u;
72
+ const pngSignature = [137, 80, 78, 71, 13, 10, 26, 10];
73
+ const acTLChunkType = new Uint8Array([0x61, 0x63, 0x54, 0x4c]);
74
+ const idatChunkType = new Uint8Array([0x49, 0x44, 0x41, 0x54]);
75
+ const iendChunkType = new Uint8Array([0x49, 0x45, 0x4e, 0x44]);
72
76
  const getPngDimensions = (pngData) => {
73
77
  if (pngData.length < 24) {
74
78
  return null;
75
79
  }
76
80
  const view = new DataView(pngData.buffer, pngData.byteOffset);
77
- const pngSignature = [137, 80, 78, 71, 13, 10, 26, 10];
78
81
  for (let i = 0; i < 8; i++) {
79
82
  if (pngData[i] !== pngSignature[i]) {
80
83
  return null;
@@ -85,11 +88,38 @@ const getPngDimensions = (pngData) => {
85
88
  height: view.getUint32(20, false),
86
89
  };
87
90
  };
91
+ const hasApngAnimationControlChunk = (pngData) => {
92
+ if (pngData.length < 16) {
93
+ return false;
94
+ }
95
+ const view = new DataView(pngData.buffer, pngData.byteOffset, pngData.byteLength);
96
+ let offset = 8;
97
+ while (offset + 8 <= pngData.length) {
98
+ const chunkLength = view.getUint32(offset, false);
99
+ const chunkType = pngData.subarray(offset + 4, offset + 8);
100
+ if ((0, exports.matchesPattern)(acTLChunkType)(chunkType)) {
101
+ return true;
102
+ }
103
+ if ((0, exports.matchesPattern)(idatChunkType)(chunkType) ||
104
+ (0, exports.matchesPattern)(iendChunkType)(chunkType)) {
105
+ return false;
106
+ }
107
+ const nextOffset = offset + 12 + chunkLength;
108
+ if (nextOffset <= offset) {
109
+ return false;
110
+ }
111
+ offset = nextOffset;
112
+ }
113
+ return false;
114
+ };
88
115
  const isPng = (data) => {
89
116
  const pngPattern = new Uint8Array([0x89, 0x50, 0x4e, 0x47]);
90
117
  if ((0, exports.matchesPattern)(pngPattern)(data.subarray(0, 4))) {
91
118
  const png = getPngDimensions(data);
92
- return { dimensions: png, type: 'png' };
119
+ return {
120
+ dimensions: png,
121
+ type: hasApngAnimationControlChunk(data) ? 'apng' : 'png',
122
+ };
93
123
  }
94
124
  return null;
95
125
  };
@@ -235,6 +265,7 @@ const isImageFileType = (fileType) => {
235
265
  fileType.type === 'webp' ||
236
266
  fileType.type === 'gif' ||
237
267
  fileType.type === 'png' ||
268
+ fileType.type === 'apng' ||
238
269
  fileType.type === 'bmp');
239
270
  };
240
271
  exports.isImageFileType = isImageFileType;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
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, 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, 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';
3
3
  export { ASSET_DRAG_MIME_TYPE, makeAssetDragData, parseAssetDragData, type AssetDragData, } from './asset-drag-data';
4
4
  export type { ApplyVisualControlCodemod, RecastCodemod } from './codemods';
5
- export { COMPONENT_DRAG_MIME_TYPE, areComponentProps, isComponentIdentifier, isComponentImportPath, makeComponentDragData, parseComponentDragData, type ComponentDragData, type ComponentProp, } from './component-drag-data';
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
7
  export { KEYFRAME_EASING_PRESETS, type KeyframeEasingPreset, } from './keyframe-easing-presets';
8
8
  export { detectFileType, isImageFileType, type FileDimensions, type FileType, type ImageFileType, } from './detect-file-type';
@@ -26,6 +26,9 @@ const getRequiredPackageForInsertableElement = (element) => {
26
26
  if (element.assetType === 'gif') {
27
27
  return '@remotion/gif';
28
28
  }
29
+ if (element.assetType === 'animated-image') {
30
+ return null;
31
+ }
29
32
  return null;
30
33
  };
31
34
  exports.getRequiredPackageForInsertableElement = getRequiredPackageForInsertableElement;
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.477",
6
+ "version": "4.0.478",
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.477"
23
+ "remotion": "4.0.478"
24
24
  },
25
25
  "devDependencies": {
26
- "@remotion/renderer": "4.0.477",
27
- "@remotion/eslint-config-internal": "4.0.477",
26
+ "@remotion/renderer": "4.0.478",
27
+ "@remotion/eslint-config-internal": "4.0.478",
28
28
  "eslint": "9.19.0",
29
29
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
30
30
  },
@@ -1,22 +0,0 @@
1
- export declare const SHAPE_DRAG_MIME_TYPE = "application/vnd.remotion.shape+json";
2
- export declare const shapeNames: readonly ["Arrow", "Circle", "Ellipse", "Heart", "Pie", "Polygon", "Rect", "Star", "Triangle"];
3
- export type ShapeName = (typeof shapeNames)[number];
4
- export type ShapeAttribute = {
5
- name: string;
6
- value: string | number | boolean;
7
- };
8
- export type ShapeDragData = {
9
- type: 'remotion-shape';
10
- version: 1;
11
- shape: ShapeName;
12
- attributes: ShapeAttribute[];
13
- };
14
- export declare const isShapeName: (value: unknown) => value is "Arrow" | "Circle" | "Ellipse" | "Heart" | "Pie" | "Polygon" | "Rect" | "Star" | "Triangle";
15
- export declare const isShapeAttributeName: (value: unknown) => value is string;
16
- export declare const isShapeAttribute: (value: unknown) => value is ShapeAttribute;
17
- export declare const areShapeAttributes: (value: unknown) => value is ShapeAttribute[];
18
- export declare const makeShapeDragData: ({ attributes, shape, }: {
19
- attributes: ShapeAttribute[];
20
- shape: "Arrow" | "Circle" | "Ellipse" | "Heart" | "Pie" | "Polygon" | "Rect" | "Star" | "Triangle";
21
- }) => ShapeDragData;
22
- export declare const parseShapeDragData: (value: string) => ShapeDragData | null;
@@ -1,90 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseShapeDragData = exports.makeShapeDragData = exports.areShapeAttributes = exports.isShapeAttribute = exports.isShapeAttributeName = exports.isShapeName = exports.shapeNames = exports.SHAPE_DRAG_MIME_TYPE = void 0;
4
- exports.SHAPE_DRAG_MIME_TYPE = 'application/vnd.remotion.shape+json';
5
- exports.shapeNames = [
6
- 'Arrow',
7
- 'Circle',
8
- 'Ellipse',
9
- 'Heart',
10
- 'Pie',
11
- 'Polygon',
12
- 'Rect',
13
- 'Star',
14
- 'Triangle',
15
- ];
16
- const isRecord = (value) => {
17
- return typeof value === 'object' && value !== null && !Array.isArray(value);
18
- };
19
- const isShapeName = (value) => {
20
- return typeof value === 'string' && exports.shapeNames.includes(value);
21
- };
22
- exports.isShapeName = isShapeName;
23
- const isShapeAttributeName = (value) => {
24
- return (typeof value === 'string' &&
25
- value !== 'style' &&
26
- /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value));
27
- };
28
- exports.isShapeAttributeName = isShapeAttributeName;
29
- const isShapeAttribute = (value) => {
30
- if (!isRecord(value)) {
31
- return false;
32
- }
33
- if (!(0, exports.isShapeAttributeName)(value.name)) {
34
- return false;
35
- }
36
- return (typeof value.value === 'string' ||
37
- typeof value.value === 'boolean' ||
38
- (typeof value.value === 'number' && Number.isFinite(value.value)));
39
- };
40
- exports.isShapeAttribute = isShapeAttribute;
41
- const areShapeAttributes = (value) => {
42
- if (!Array.isArray(value)) {
43
- return false;
44
- }
45
- const seen = new Set();
46
- for (const attribute of value) {
47
- if (!(0, exports.isShapeAttribute)(attribute) || seen.has(attribute.name)) {
48
- return false;
49
- }
50
- seen.add(attribute.name);
51
- }
52
- return true;
53
- };
54
- exports.areShapeAttributes = areShapeAttributes;
55
- const makeShapeDragData = ({ attributes, shape, }) => {
56
- return {
57
- type: 'remotion-shape',
58
- version: 1,
59
- shape,
60
- attributes,
61
- };
62
- };
63
- exports.makeShapeDragData = makeShapeDragData;
64
- const parseShapeDragData = (value) => {
65
- try {
66
- const parsed = JSON.parse(value);
67
- if (!isRecord(parsed)) {
68
- return null;
69
- }
70
- if (parsed.type !== 'remotion-shape' || parsed.version !== 1) {
71
- return null;
72
- }
73
- if (!(0, exports.isShapeName)(parsed.shape)) {
74
- return null;
75
- }
76
- if (!(0, exports.areShapeAttributes)(parsed.attributes)) {
77
- return null;
78
- }
79
- return {
80
- type: 'remotion-shape',
81
- version: 1,
82
- shape: parsed.shape,
83
- attributes: parsed.attributes,
84
- };
85
- }
86
- catch (_a) {
87
- return null;
88
- }
89
- };
90
- exports.parseShapeDragData = parseShapeDragData;