@remotion/studio 4.0.470 → 4.0.472

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 (112) hide show
  1. package/dist/components/AssetSelector.js +10 -1
  2. package/dist/components/Canvas.js +98 -0
  3. package/dist/components/CompositionSelectorItem.d.ts +1 -0
  4. package/dist/components/CompositionSelectorItem.js +12 -4
  5. package/dist/components/ContextMenu.d.ts +7 -2
  6. package/dist/components/ContextMenu.js +91 -43
  7. package/dist/components/Editor.js +14 -6
  8. package/dist/components/Modals.js +3 -1
  9. package/dist/components/NewComposition/CodemodFooter.js +2 -2
  10. package/dist/components/NewComposition/DeleteFolder.d.ts +6 -0
  11. package/dist/components/NewComposition/DeleteFolder.js +39 -0
  12. package/dist/components/NewComposition/RenameFolder.d.ts +6 -0
  13. package/dist/components/NewComposition/RenameFolder.js +60 -0
  14. package/dist/components/Preview.js +2 -1
  15. package/dist/components/SelectedOutlineOverlay.d.ts +109 -1
  16. package/dist/components/SelectedOutlineOverlay.js +489 -73
  17. package/dist/components/Splitter/SplitterContainer.js +9 -0
  18. package/dist/components/Splitter/SplitterHandle.js +63 -70
  19. package/dist/components/Timeline/Timeline.js +121 -1
  20. package/dist/components/Timeline/TimelineArrayField.d.ts +9 -0
  21. package/dist/components/Timeline/TimelineArrayField.js +210 -0
  22. package/dist/components/Timeline/TimelineBooleanField.d.ts +2 -2
  23. package/dist/components/Timeline/TimelineBooleanField.js +2 -2
  24. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +20 -0
  25. package/dist/components/Timeline/TimelineClipboardKeybindings.js +265 -0
  26. package/dist/components/Timeline/TimelineColorField.d.ts +2 -2
  27. package/dist/components/Timeline/TimelineColorField.js +2 -8
  28. package/dist/components/Timeline/TimelineDeleteKeybindings.js +15 -0
  29. package/dist/components/Timeline/TimelineDragHandler.js +1 -0
  30. package/dist/components/Timeline/TimelineEffectItem.js +159 -6
  31. package/dist/components/Timeline/TimelineEffectPropItem.js +95 -25
  32. package/dist/components/Timeline/TimelineEnumField.d.ts +2 -2
  33. package/dist/components/Timeline/TimelineEnumField.js +3 -3
  34. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +4 -3
  35. package/dist/components/Timeline/TimelineKeyframeControls.js +52 -33
  36. package/dist/components/Timeline/TimelineKeyframedValue.d.ts +7 -2
  37. package/dist/components/Timeline/TimelineKeyframedValue.js +22 -8
  38. package/dist/components/Timeline/TimelineLayerEye.d.ts +1 -0
  39. package/dist/components/Timeline/TimelineLayerEye.js +8 -3
  40. package/dist/components/Timeline/TimelineNumberField.d.ts +2 -2
  41. package/dist/components/Timeline/TimelineNumberField.js +7 -11
  42. package/dist/components/Timeline/TimelinePrimitiveFieldValue.d.ts +17 -0
  43. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +53 -0
  44. package/dist/components/Timeline/TimelineRotationField.d.ts +2 -2
  45. package/dist/components/Timeline/TimelineRotationField.js +41 -24
  46. package/dist/components/Timeline/TimelineRowChrome.d.ts +3 -0
  47. package/dist/components/Timeline/TimelineRowChrome.js +11 -10
  48. package/dist/components/Timeline/TimelineScaleField.d.ts +20 -0
  49. package/dist/components/Timeline/TimelineScaleField.js +314 -0
  50. package/dist/components/Timeline/TimelineSchemaField.d.ts +3 -2
  51. package/dist/components/Timeline/TimelineSchemaField.js +8 -42
  52. package/dist/components/Timeline/TimelineSelection.js +3 -2
  53. package/dist/components/Timeline/TimelineSequence.d.ts +1 -0
  54. package/dist/components/Timeline/TimelineSequence.js +51 -10
  55. package/dist/components/Timeline/TimelineSequenceFrame.js +1 -0
  56. package/dist/components/Timeline/TimelineSequenceItem.js +97 -7
  57. package/dist/components/Timeline/TimelineSequencePropItem.js +82 -21
  58. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +58 -0
  59. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +528 -0
  60. package/dist/components/Timeline/TimelineTrack.js +1 -1
  61. package/dist/components/Timeline/TimelineTranslateField.d.ts +2 -2
  62. package/dist/components/Timeline/TimelineTranslateField.js +21 -25
  63. package/dist/components/Timeline/TimelineUvCoordinateField.d.ts +2 -2
  64. package/dist/components/Timeline/TimelineUvCoordinateField.js +20 -26
  65. package/dist/components/Timeline/call-add-keyframe.js +2 -0
  66. package/dist/components/Timeline/call-delete-keyframe.d.ts +16 -0
  67. package/dist/components/Timeline/call-delete-keyframe.js +86 -14
  68. package/dist/components/Timeline/delete-selected-keyframe.d.ts +10 -0
  69. package/dist/components/Timeline/delete-selected-keyframe.js +48 -7
  70. package/dist/components/Timeline/delete-selected-timeline-item.js +6 -11
  71. package/dist/components/Timeline/get-node-keyframes.d.ts +5 -2
  72. package/dist/components/Timeline/get-node-keyframes.js +38 -5
  73. package/dist/components/Timeline/get-timeline-keyframes.js +4 -4
  74. package/dist/components/Timeline/reset-selected-timeline-props.d.ts +38 -0
  75. package/dist/components/Timeline/reset-selected-timeline-props.js +156 -0
  76. package/dist/components/Timeline/sequence-props-subscription-store.d.ts +3 -2
  77. package/dist/components/Timeline/sequence-props-subscription-store.js +2 -1
  78. package/dist/components/Timeline/timeline-field-utils.d.ts +1 -0
  79. package/dist/components/Timeline/timeline-field-utils.js +5 -1
  80. package/dist/components/Timeline/timeline-scroll-logic.js +3 -3
  81. package/dist/components/Timeline/timeline-translate-utils.js +6 -2
  82. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +7 -0
  83. package/dist/components/Timeline/use-sequence-props-subscription.js +2 -1
  84. package/dist/components/TopPanel.d.ts +1 -1
  85. package/dist/components/folder-menu-items.d.ts +12 -0
  86. package/dist/components/folder-menu-items.js +147 -0
  87. package/dist/components/import-assets.d.ts +6 -0
  88. package/dist/components/import-assets.js +157 -0
  89. package/dist/esm/{chunk-dny42qnq.js → chunk-48grt472.js} +9717 -5925
  90. package/dist/esm/internals.mjs +9717 -5925
  91. package/dist/esm/previewEntry.mjs +9531 -5737
  92. package/dist/esm/renderEntry.mjs +1 -1
  93. package/dist/helpers/calculate-timeline.js +7 -3
  94. package/dist/helpers/create-folder-tree.js +1 -0
  95. package/dist/helpers/detect-file-type.d.ts +69 -0
  96. package/dist/helpers/detect-file-type.js +278 -0
  97. package/dist/helpers/get-folder-id.d.ts +4 -0
  98. package/dist/helpers/get-folder-id.js +7 -0
  99. package/dist/helpers/get-left-of-timeline-slider.js +1 -1
  100. package/dist/helpers/get-timeline-sequence-layout.js +10 -11
  101. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +2 -0
  102. package/dist/helpers/open-in-editor.d.ts +19 -1
  103. package/dist/helpers/open-in-editor.js +42 -4
  104. package/dist/helpers/timeline-layout.js +5 -1
  105. package/dist/helpers/use-menu-structure.js +0 -1
  106. package/dist/helpers/validate-folder-rename.d.ts +6 -0
  107. package/dist/helpers/validate-folder-rename.js +19 -0
  108. package/dist/state/modals.d.ts +10 -0
  109. package/dist/state/scale-lock.d.ts +18 -0
  110. package/dist/state/scale-lock.js +59 -0
  111. package/dist/state/z-index.js +5 -2
  112. package/package.json +10 -10
@@ -1,13 +1,14 @@
1
- import type { SequenceSchema } from 'remotion';
1
+ import type { SequenceNodePath, SequenceSchema } from 'remotion';
2
2
  import { callApi } from '../call-api';
3
3
  type SubscribeResult = Awaited<ReturnType<typeof callApi<'/api/subscribe-to-sequence-props'>>>;
4
4
  type ApplyResult = (result: SubscribeResult) => void;
5
- export declare const acquireSequencePropsSubscription: ({ fileName, line, column, schema, effects, clientId, applyOnce, applyEach, }: {
5
+ export declare const acquireSequencePropsSubscription: ({ fileName, line, column, schema, effects, nodePath, clientId, applyOnce, applyEach, }: {
6
6
  fileName: string;
7
7
  line: number;
8
8
  column: number;
9
9
  schema: SequenceSchema;
10
10
  effects: SequenceSchema[];
11
+ nodePath: SequenceNodePath | null;
11
12
  clientId: string;
12
13
  applyOnce: ApplyResult;
13
14
  applyEach: ApplyResult;
@@ -6,7 +6,7 @@ const remotion_1 = require("remotion");
6
6
  const call_api_1 = require("../call-api");
7
7
  const makeKey = (fileName, line, column, sequenceKeys, effectKeys) => `${fileName}\0${line}\0${column}\0${sequenceKeys.join('\0')}\0${effectKeys.map((keys) => keys.join('\0')).join('\0\0')}`;
8
8
  const entries = new Map();
9
- const acquireSequencePropsSubscription = ({ fileName, line, column, schema, effects, clientId, applyOnce, applyEach, }) => {
9
+ const acquireSequencePropsSubscription = ({ fileName, line, column, schema, effects, nodePath, clientId, applyOnce, applyEach, }) => {
10
10
  const sequenceKeys = (0, studio_shared_1.getAllSchemaKeys)(schema);
11
11
  const effectKeys = effects.map((effect) => (0, studio_shared_1.getAllSchemaKeys)(effect));
12
12
  const key = makeKey(fileName, line, column, sequenceKeys, effectKeys);
@@ -16,6 +16,7 @@ const acquireSequencePropsSubscription = ({ fileName, line, column, schema, effe
16
16
  fileName,
17
17
  line,
18
18
  column,
19
+ nodePath,
19
20
  keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
20
21
  effects: effectKeys,
21
22
  clientId,
@@ -1,2 +1,3 @@
1
1
  export declare const getDecimalPlaces: (num: number) => number;
2
+ export declare const normalizeTimelineNumber: (value: number) => number;
2
3
  export declare const draggerStyle: React.CSSProperties;
@@ -1,12 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.draggerStyle = exports.getDecimalPlaces = void 0;
3
+ exports.draggerStyle = exports.normalizeTimelineNumber = exports.getDecimalPlaces = void 0;
4
4
  const getDecimalPlaces = (num) => {
5
5
  const str = String(num);
6
6
  const decimalIndex = str.indexOf('.');
7
7
  return decimalIndex === -1 ? 0 : str.length - decimalIndex - 1;
8
8
  };
9
9
  exports.getDecimalPlaces = getDecimalPlaces;
10
+ const normalizeTimelineNumber = (value) => {
11
+ return Math.round(value * 1000000) / 1000000;
12
+ };
13
+ exports.normalizeTimelineNumber = normalizeTimelineNumber;
10
14
  exports.draggerStyle = {
11
15
  width: 80,
12
16
  };
@@ -172,7 +172,7 @@ const getFrameIncrement = (durationInFrames) => {
172
172
  return (0, exports.getFrameIncrementFromWidth)(durationInFrames, width);
173
173
  };
174
174
  const getFrameIncrementFromWidth = (durationInFrames, width) => {
175
- return (width - timeline_layout_1.TIMELINE_PADDING * 2) / (durationInFrames - 1);
175
+ return (width - timeline_layout_1.TIMELINE_PADDING * 2) / durationInFrames;
176
176
  };
177
177
  exports.getFrameIncrementFromWidth = getFrameIncrementFromWidth;
178
178
  const getFrameWhileScrollingRight = ({ durationInFrames, width, }) => {
@@ -193,10 +193,10 @@ const getFrameWhileScrollingRight = ({ durationInFrames, width, }) => {
193
193
  exports.getFrameWhileScrollingRight = getFrameWhileScrollingRight;
194
194
  const getFrameFromX = ({ clientX, durationInFrames, width, extrapolate, }) => {
195
195
  const pos = clientX - timeline_layout_1.TIMELINE_PADDING;
196
- const frame = Math.round((0, remotion_1.interpolate)(pos, [0, width - timeline_layout_1.TIMELINE_PADDING * 2], [0, durationInFrames - 1], {
196
+ const frame = Math.min(durationInFrames - 1, Math.round((0, remotion_1.interpolate)(pos, [0, width - timeline_layout_1.TIMELINE_PADDING * 2], [0, durationInFrames], {
197
197
  extrapolateLeft: extrapolate,
198
198
  extrapolateRight: extrapolate,
199
- }));
199
+ })));
200
200
  return frame;
201
201
  };
202
202
  exports.getFrameFromX = getFrameFromX;
@@ -1,17 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.serializeTranslate = exports.parseTranslate = void 0;
4
+ const timeline_field_utils_1 = require("./timeline-field-utils");
4
5
  const PIXEL_PATTERN = /^(-?\d+(?:\.\d+)?)px(?:\s+(-?\d+(?:\.\d+)?)px)?$/;
5
6
  const parseTranslate = (value) => {
6
7
  const m = value.match(PIXEL_PATTERN);
7
8
  if (!m) {
8
9
  return [0, 0];
9
10
  }
10
- return [Number(m[1]), m[2] !== undefined ? Number(m[2]) : 0];
11
+ return [
12
+ (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(m[1])),
13
+ m[2] !== undefined ? (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(m[2])) : 0,
14
+ ];
11
15
  };
12
16
  exports.parseTranslate = parseTranslate;
13
17
  const formatTranslateCoordinate = (value) => {
14
- const rounded = Math.round(value * 1000) / 1000;
18
+ const rounded = (0, timeline_field_utils_1.normalizeTimelineNumber)(value);
15
19
  return String(Object.is(rounded, -0) ? 0 : rounded);
16
20
  };
17
21
  const serializeTranslate = (x, y) => {
@@ -11,6 +11,7 @@ const useExpandedTrackKeyframeRows = ({ sequence, nodePathInfo, keyframeDisplayO
11
11
  const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
12
12
  const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
13
13
  const { getDragOverrides, getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
14
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
14
15
  const tree = (0, react_1.useMemo)(() => (0, timeline_layout_1.buildTimelineTree)({
15
16
  sequence,
16
17
  nodePathInfo,
@@ -38,14 +39,20 @@ const useExpandedTrackKeyframeRows = ({ sequence, nodePathInfo, keyframeDisplayO
38
39
  nodePath: nodePathInfo.sequenceSubscriptionKey,
39
40
  codeValues,
40
41
  keyframeDisplayOffset,
42
+ getDragOverrides,
43
+ getEffectDragOverrides,
44
+ timelinePosition,
41
45
  }),
42
46
  rowKey: (0, timeline_node_path_key_1.timelineNodePathInfoToKey)(node.nodePathInfo),
43
47
  nodePathInfo: node.nodePathInfo,
44
48
  })), [
45
49
  codeValues,
46
50
  flat,
51
+ getDragOverrides,
52
+ getEffectDragOverrides,
47
53
  keyframeDisplayOffset,
48
54
  nodePathInfo.sequenceSubscriptionKey,
55
+ timelinePosition,
49
56
  ]);
50
57
  return { rows, expandedHeight };
51
58
  };
@@ -36,7 +36,7 @@ const useSequencePropsSubscription = ({ originalLocation, overrideId, schema, ef
36
36
  const locationLine = (_b = validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.line) !== null && _b !== void 0 ? _b : null;
37
37
  const locationColumn = (_c = validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.column) !== null && _c !== void 0 ? _c : null;
38
38
  (0, react_1.useEffect)(() => {
39
- var _a;
39
+ var _a, _b;
40
40
  if (!clientId ||
41
41
  !locationSource ||
42
42
  !locationLine ||
@@ -51,6 +51,7 @@ const useSequencePropsSubscription = ({ originalLocation, overrideId, schema, ef
51
51
  column: locationColumn,
52
52
  schema,
53
53
  effects,
54
+ nodePath: (_b = nodePathAtResubscribe === null || nodePathAtResubscribe === void 0 ? void 0 : nodePathAtResubscribe.nodePath) !== null && _b !== void 0 ? _b : null,
54
55
  clientId,
55
56
  applyOnce: (result) => {
56
57
  if (!result.success) {
@@ -3,6 +3,6 @@ export declare const useResponsiveSidebarStatus: () => "collapsed" | "expanded";
3
3
  export declare const TopPanel: React.NamedExoticComponent<{
4
4
  readonly readOnlyStudio: boolean;
5
5
  readonly onMounted: () => void;
6
- readonly drawRef: React.RefObject<HTMLDivElement | null>;
6
+ readonly drawRef: React.Ref<HTMLDivElement>;
7
7
  readonly bufferStateDelayInMilliseconds: number;
8
8
  }>;
@@ -0,0 +1,12 @@
1
+ import type { SetStateAction } from 'react';
2
+ import type { ResolvedStackLocation } from 'remotion';
3
+ import type { ModalState } from '../state/modals';
4
+ import type { ComboboxValue } from './NewComposition/ComboBox';
5
+ export declare const getFolderMenuItems: ({ closeMenu, connectionStatus, folder, readOnlyStudio, resolvedLocation, setSelectedModal, }: {
6
+ closeMenu: () => void;
7
+ connectionStatus: "connected" | "disconnected" | "init";
8
+ folder: import("remotion").TFolder;
9
+ readOnlyStudio: boolean;
10
+ resolvedLocation: ResolvedStackLocation | null;
11
+ setSelectedModal: (value: SetStateAction<ModalState | null>) => void;
12
+ }) => ComboboxValue[];
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getFolderMenuItems = void 0;
4
+ const no_react_1 = require("remotion/no-react");
5
+ const format_file_location_1 = require("../helpers/format-file-location");
6
+ const get_folder_id_1 = require("../helpers/get-folder-id");
7
+ const open_in_editor_1 = require("../helpers/open-in-editor");
8
+ const NotificationCenter_1 = require("./Notifications/NotificationCenter");
9
+ const getFolderMenuItems = ({ closeMenu, connectionStatus, folder, readOnlyStudio, resolvedLocation, setSelectedModal, }) => {
10
+ const editorName = window.remotion_editorName;
11
+ const folderId = (0, get_folder_id_1.getFolderId)({
12
+ folderName: folder.name,
13
+ parentName: folder.parent,
14
+ });
15
+ const fileLocation = (0, format_file_location_1.formatFileLocation)({
16
+ location: resolvedLocation,
17
+ root: window.remotion_cwd,
18
+ });
19
+ const showInEditorDisabled = connectionStatus !== 'connected' || !resolvedLocation;
20
+ const copyFileLocationDisabled = !fileLocation;
21
+ const codemodDisabled = readOnlyStudio || !folder.stack;
22
+ return [
23
+ editorName
24
+ ? {
25
+ id: 'show-folder-in-editor',
26
+ keyHint: null,
27
+ label: `Show folder in ${editorName}`,
28
+ leftItem: null,
29
+ onClick: async () => {
30
+ closeMenu();
31
+ if (!resolvedLocation) {
32
+ return;
33
+ }
34
+ try {
35
+ await (0, open_in_editor_1.openOriginalPositionInEditor)(resolvedLocation);
36
+ }
37
+ catch (err) {
38
+ (0, NotificationCenter_1.showNotification)(err.message, 2000);
39
+ }
40
+ },
41
+ quickSwitcherLabel: `Show folder in ${editorName}`,
42
+ subMenu: null,
43
+ type: 'item',
44
+ value: 'show-folder-in-editor',
45
+ disabled: showInEditorDisabled,
46
+ }
47
+ : null,
48
+ {
49
+ id: 'copy-folder-file-location',
50
+ keyHint: null,
51
+ label: `Copy file location`,
52
+ leftItem: null,
53
+ onClick: () => {
54
+ closeMenu();
55
+ if (!fileLocation) {
56
+ return;
57
+ }
58
+ navigator.clipboard
59
+ .writeText(fileLocation)
60
+ .then(() => {
61
+ (0, NotificationCenter_1.showNotification)('Copied file location to clipboard', 1000);
62
+ })
63
+ .catch((err) => {
64
+ (0, NotificationCenter_1.showNotification)(`Could not copy to clipboard: ${err.message}`, 1000);
65
+ });
66
+ },
67
+ quickSwitcherLabel: 'Copy folder file location',
68
+ subMenu: null,
69
+ type: 'item',
70
+ value: 'copy-folder-file-location',
71
+ disabled: copyFileLocationDisabled,
72
+ },
73
+ editorName || fileLocation
74
+ ? {
75
+ type: 'divider',
76
+ id: 'show-folder-in-editor-divider',
77
+ }
78
+ : null,
79
+ {
80
+ id: 'rename-folder',
81
+ keyHint: null,
82
+ label: `Rename...`,
83
+ leftItem: null,
84
+ onClick: () => {
85
+ closeMenu();
86
+ setSelectedModal({
87
+ type: 'rename-folder',
88
+ folderName: folder.name,
89
+ parentName: folder.parent,
90
+ stack: folder.stack,
91
+ });
92
+ },
93
+ quickSwitcherLabel: 'Rename folder...',
94
+ subMenu: null,
95
+ type: 'item',
96
+ value: 'rename-folder',
97
+ disabled: codemodDisabled,
98
+ },
99
+ {
100
+ id: 'delete-folder',
101
+ keyHint: null,
102
+ label: `Delete...`,
103
+ leftItem: null,
104
+ onClick: () => {
105
+ closeMenu();
106
+ setSelectedModal({
107
+ type: 'delete-folder',
108
+ folderName: folder.name,
109
+ parentName: folder.parent,
110
+ stack: folder.stack,
111
+ });
112
+ },
113
+ quickSwitcherLabel: 'Delete folder...',
114
+ subMenu: null,
115
+ type: 'item',
116
+ value: 'delete-folder',
117
+ disabled: codemodDisabled,
118
+ },
119
+ {
120
+ type: 'divider',
121
+ id: 'copy-folder-id-divider',
122
+ },
123
+ {
124
+ id: 'copy-folder-id',
125
+ keyHint: null,
126
+ label: `Copy ID`,
127
+ leftItem: null,
128
+ onClick: () => {
129
+ closeMenu();
130
+ navigator.clipboard
131
+ .writeText(folderId)
132
+ .then(() => {
133
+ (0, NotificationCenter_1.showNotification)('Copied to clipboard', 1000);
134
+ })
135
+ .catch((err) => {
136
+ (0, NotificationCenter_1.showNotification)(`Could not copy to clipboard: ${err.message}`, 1000);
137
+ });
138
+ },
139
+ quickSwitcherLabel: 'Copy folder ID',
140
+ subMenu: null,
141
+ type: 'item',
142
+ value: 'copy-folder-id',
143
+ disabled: false,
144
+ },
145
+ ].filter(no_react_1.NoReactInternals.truthy);
146
+ };
147
+ exports.getFolderMenuItems = getFolderMenuItems;
@@ -0,0 +1,6 @@
1
+ export declare const pickFilesToImport: () => Promise<File[]>;
2
+ export declare const importAssets: ({ compositionFile, compositionId, files, }: {
3
+ compositionFile: string;
4
+ compositionId: string;
5
+ files: File[];
6
+ }) => Promise<void>;
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.importAssets = exports.pickFilesToImport = void 0;
4
+ const get_static_files_1 = require("../api/get-static-files");
5
+ const write_static_file_1 = require("../api/write-static-file");
6
+ const detect_file_type_1 = require("../helpers/detect-file-type");
7
+ const call_api_1 = require("./call-api");
8
+ const NotificationCenter_1 = require("./Notifications/NotificationCenter");
9
+ const getAssetElement = ({ fileType, src, }) => {
10
+ if (fileType.type === 'png' ||
11
+ fileType.type === 'jpeg' ||
12
+ fileType.type === 'webp' ||
13
+ fileType.type === 'bmp') {
14
+ return {
15
+ type: 'asset',
16
+ assetType: 'image',
17
+ src,
18
+ dimensions: fileType.dimensions,
19
+ };
20
+ }
21
+ if (fileType.type === 'gif') {
22
+ return {
23
+ type: 'asset',
24
+ assetType: 'gif',
25
+ src,
26
+ dimensions: fileType.dimensions,
27
+ };
28
+ }
29
+ if (fileType.type === 'riff' ||
30
+ fileType.type === 'webm' ||
31
+ fileType.type === 'iso-base-media' ||
32
+ fileType.type === 'transport-stream') {
33
+ return {
34
+ type: 'asset',
35
+ assetType: 'video',
36
+ src,
37
+ dimensions: null,
38
+ };
39
+ }
40
+ return null;
41
+ };
42
+ const getAssetLabel = (element) => {
43
+ if (element.type !== 'asset') {
44
+ throw new Error('Expected asset element');
45
+ }
46
+ if (element.assetType === 'image') {
47
+ return '<Img>';
48
+ }
49
+ if (element.assetType === 'video') {
50
+ return '<Video>';
51
+ }
52
+ return '<Gif>';
53
+ };
54
+ const pickFilesToImport = () => {
55
+ return new Promise((resolve) => {
56
+ const input = document.createElement('input');
57
+ input.type = 'file';
58
+ input.multiple = true;
59
+ input.style.display = 'none';
60
+ let didResolve = false;
61
+ const resolveOnce = (files) => {
62
+ if (didResolve) {
63
+ return;
64
+ }
65
+ didResolve = true;
66
+ input.removeEventListener('change', onChange);
67
+ input.removeEventListener('cancel', onCancel);
68
+ input.remove();
69
+ resolve(files);
70
+ };
71
+ const onChange = () => {
72
+ var _a;
73
+ return resolveOnce(Array.from((_a = input.files) !== null && _a !== void 0 ? _a : []));
74
+ };
75
+ const onCancel = () => resolveOnce([]);
76
+ input.addEventListener('change', onChange);
77
+ input.addEventListener('cancel', onCancel);
78
+ document.body.appendChild(input);
79
+ input.click();
80
+ });
81
+ };
82
+ exports.pickFilesToImport = pickFilesToImport;
83
+ const importAssets = async ({ compositionFile, compositionId, files, }) => {
84
+ if (files.length === 0) {
85
+ return;
86
+ }
87
+ const staticFiles = (0, get_static_files_1.getStaticFiles)();
88
+ const differentExistingFile = files.find((file) => {
89
+ return staticFiles.some((staticFile) => staticFile.name === file.name && staticFile.sizeInBytes !== file.size);
90
+ });
91
+ if (differentExistingFile) {
92
+ (0, NotificationCenter_1.showNotification)(`File with name ${differentExistingFile.name} already exists and is different`, 4000);
93
+ return;
94
+ }
95
+ const insertedLabels = [];
96
+ const addedStaticFiles = [];
97
+ const unsupportedFiles = [];
98
+ const notifyAddedStaticFiles = () => {
99
+ if (addedStaticFiles.length === 1) {
100
+ (0, NotificationCenter_1.showNotification)(`Created ${addedStaticFiles[0]} in public folder`, 3000);
101
+ }
102
+ else if (addedStaticFiles.length > 1) {
103
+ (0, NotificationCenter_1.showNotification)(`Added ${addedStaticFiles.length} files to public folder`, 3000);
104
+ }
105
+ addedStaticFiles.length = 0;
106
+ };
107
+ try {
108
+ for (const file of files) {
109
+ const contents = await file.arrayBuffer();
110
+ const fileType = (0, detect_file_type_1.detectFileType)(new Uint8Array(contents));
111
+ const element = getAssetElement({
112
+ fileType,
113
+ src: file.name,
114
+ });
115
+ if (element === null) {
116
+ unsupportedFiles.push(file.name);
117
+ continue;
118
+ }
119
+ const alreadyExists = staticFiles.some((staticFile) => staticFile.name === file.name && staticFile.sizeInBytes === file.size);
120
+ if (!alreadyExists) {
121
+ await (0, write_static_file_1.writeStaticFile)({
122
+ contents,
123
+ filePath: file.name,
124
+ });
125
+ addedStaticFiles.push(file.name);
126
+ }
127
+ const result = await (0, call_api_1.callApi)('/api/insert-jsx-element', {
128
+ compositionFile,
129
+ compositionId,
130
+ element,
131
+ });
132
+ if (!result.success) {
133
+ notifyAddedStaticFiles();
134
+ (0, NotificationCenter_1.showNotification)(result.reason, 4000);
135
+ return;
136
+ }
137
+ insertedLabels.push(getAssetLabel(element));
138
+ }
139
+ notifyAddedStaticFiles();
140
+ if (insertedLabels.length === 1) {
141
+ (0, NotificationCenter_1.showNotification)(`Added ${insertedLabels[0]} to source file`, 2000);
142
+ }
143
+ else if (insertedLabels.length > 1) {
144
+ (0, NotificationCenter_1.showNotification)(`Added ${insertedLabels.length} assets to source file`, 2000);
145
+ }
146
+ if (unsupportedFiles.length === 1) {
147
+ (0, NotificationCenter_1.showNotification)(`Cannot add ${unsupportedFiles[0]}: Unsupported file type`, 3000);
148
+ }
149
+ else if (unsupportedFiles.length > 1) {
150
+ (0, NotificationCenter_1.showNotification)(`Skipped ${unsupportedFiles.length} unsupported files`, 3000);
151
+ }
152
+ }
153
+ catch (error) {
154
+ (0, NotificationCenter_1.showNotification)(`Could not add asset: ${error instanceof Error ? error.message : String(error)}`, 4000);
155
+ }
156
+ };
157
+ exports.importAssets = importAssets;