@remotion/studio 4.0.472 → 4.0.473

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 (133) hide show
  1. package/dist/api/rename-static-file.d.ts +6 -0
  2. package/dist/api/rename-static-file.js +18 -0
  3. package/dist/components/AssetSelector.js +45 -4
  4. package/dist/components/AssetSelectorItem.js +153 -27
  5. package/dist/components/Canvas.js +60 -11
  6. package/dist/components/ConfirmationDialog-types.d.ts +8 -0
  7. package/dist/components/ConfirmationDialog-types.js +2 -0
  8. package/dist/components/ConfirmationDialog.d.ts +7 -0
  9. package/dist/components/ConfirmationDialog.js +103 -0
  10. package/dist/components/ContextMenu.d.ts +9 -1
  11. package/dist/components/ContextMenu.js +49 -5
  12. package/dist/components/CurrentAsset.d.ts +1 -0
  13. package/dist/components/CurrentAsset.js +13 -2
  14. package/dist/components/EditorContent.js +15 -2
  15. package/dist/components/EditorContexts.js +2 -1
  16. package/dist/components/EditorRuler/Ruler.js +2 -0
  17. package/dist/components/ExplorerPanel.d.ts +0 -4
  18. package/dist/components/ExplorerPanel.js +8 -4
  19. package/dist/components/ExplorerPanelRef.d.ts +4 -0
  20. package/dist/components/ExplorerPanelRef.js +5 -0
  21. package/dist/components/FilePreview.d.ts +1 -1
  22. package/dist/components/InitialCompositionLoader.d.ts +0 -1
  23. package/dist/components/InitialCompositionLoader.js +5 -27
  24. package/dist/components/Menu/MenuItem.js +7 -1
  25. package/dist/components/Menu/SubMenu.js +5 -1
  26. package/dist/components/Menu/portals.js +17 -8
  27. package/dist/components/MenuToolbar.js +5 -1
  28. package/dist/components/ModalContainer.js +6 -1
  29. package/dist/components/Modals.js +6 -2
  30. package/dist/components/NewComposition/ComboBox.js +8 -2
  31. package/dist/components/NewComposition/DeleteStaticFile.d.ts +4 -0
  32. package/dist/components/NewComposition/DeleteStaticFile.js +44 -0
  33. package/dist/components/NewComposition/RenameStaticFile.d.ts +4 -0
  34. package/dist/components/NewComposition/RenameStaticFile.js +118 -0
  35. package/dist/components/OptionsPanel.js +5 -1
  36. package/dist/components/OutlineToggle.d.ts +2 -0
  37. package/dist/components/OutlineToggle.js +20 -0
  38. package/dist/components/Preview.d.ts +0 -2
  39. package/dist/components/Preview.js +23 -33
  40. package/dist/components/PreviewToolbar.js +19 -6
  41. package/dist/components/RenderButton.js +8 -2
  42. package/dist/components/RenderPreview.js +2 -2
  43. package/dist/components/SelectedOutlineOverlay.d.ts +24 -0
  44. package/dist/components/SelectedOutlineOverlay.js +190 -22
  45. package/dist/components/ShowOutlinesProvider.d.ts +4 -0
  46. package/dist/components/ShowOutlinesProvider.js +24 -0
  47. package/dist/components/SizeSelector.js +3 -3
  48. package/dist/components/Splitter/SplitterHandle.js +2 -0
  49. package/dist/components/StaticFilePreview.js +2 -2
  50. package/dist/components/Timeline/KeyframeSettingsModal.d.ts +15 -0
  51. package/dist/components/Timeline/KeyframeSettingsModal.js +150 -0
  52. package/dist/components/Timeline/Timeline.js +3 -13
  53. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +25 -2
  54. package/dist/components/Timeline/TimelineClipboardKeybindings.js +234 -20
  55. package/dist/components/Timeline/TimelineDeleteKeybindings.js +12 -2
  56. package/dist/components/Timeline/TimelineEffectItem.js +1 -0
  57. package/dist/components/Timeline/TimelineEffectPropItem.js +52 -2
  58. package/dist/components/Timeline/TimelineKeyframeControls.js +5 -15
  59. package/dist/components/Timeline/TimelineKeyframeDiamond.js +24 -21
  60. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.d.ts +6 -0
  61. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.js +14 -0
  62. package/dist/components/Timeline/TimelineKeyframeDragState.d.ts +17 -0
  63. package/dist/components/Timeline/TimelineKeyframeDragState.js +39 -0
  64. package/dist/components/Timeline/TimelineList.js +2 -2
  65. package/dist/components/Timeline/TimelineMediaInfo.d.ts +0 -13
  66. package/dist/components/Timeline/TimelineMediaInfo.js +8 -73
  67. package/dist/components/Timeline/TimelineScaleField.js +1 -1
  68. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -0
  69. package/dist/components/Timeline/TimelineSequenceItem.js +276 -22
  70. package/dist/components/Timeline/TimelineSequencePropItem.js +81 -16
  71. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +25 -28
  72. package/dist/components/Timeline/apply-effect-response-to-code-values.d.ts +5 -0
  73. package/dist/components/Timeline/apply-effect-response-to-code-values.js +19 -0
  74. package/dist/components/Timeline/call-add-keyframe.js +2 -0
  75. package/dist/components/Timeline/call-move-keyframe.d.ts +19 -0
  76. package/dist/components/Timeline/call-move-keyframe.js +71 -0
  77. package/dist/components/Timeline/call-update-keyframe-settings.d.ts +22 -0
  78. package/dist/components/Timeline/call-update-keyframe-settings.js +52 -0
  79. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +7 -4
  80. package/dist/components/Timeline/delete-selected-timeline-item.js +33 -21
  81. package/dist/components/Timeline/duplicate-selected-timeline-item.d.ts +4 -2
  82. package/dist/components/Timeline/duplicate-selected-timeline-item.js +39 -34
  83. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.d.ts +8 -0
  84. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.js +12 -0
  85. package/dist/components/Timeline/get-keyframe-navigation.d.ts +2 -2
  86. package/dist/components/Timeline/get-keyframe-navigation.js +14 -6
  87. package/dist/components/Timeline/reset-selected-timeline-props.js +3 -2
  88. package/dist/components/Timeline/save-effect-prop.d.ts +14 -3
  89. package/dist/components/Timeline/save-effect-prop.js +36 -18
  90. package/dist/components/Timeline/save-prop-queue.d.ts +2 -1
  91. package/dist/components/Timeline/save-prop-queue.js +5 -2
  92. package/dist/components/Timeline/save-sequence-prop.d.ts +2 -7
  93. package/dist/components/Timeline/save-sequence-prop.js +33 -30
  94. package/dist/components/Timeline/should-clear-selection-on-pointer-down.d.ts +3 -0
  95. package/dist/components/Timeline/should-clear-selection-on-pointer-down.js +7 -0
  96. package/dist/components/Timeline/timeline-asset-link.d.ts +13 -0
  97. package/dist/components/Timeline/timeline-asset-link.js +37 -0
  98. package/dist/components/Timeline/timeline-translate-utils.js +4 -1
  99. package/dist/components/Timeline/use-timeline-keyframe-drag.d.ts +10 -0
  100. package/dist/components/Timeline/use-timeline-keyframe-drag.js +378 -0
  101. package/dist/components/import-assets.d.ts +16 -0
  102. package/dist/components/import-assets.js +155 -18
  103. package/dist/components/load-canvas-content-from-url.d.ts +1 -0
  104. package/dist/components/load-canvas-content-from-url.js +9 -3
  105. package/dist/components/use-select-asset.d.ts +1 -0
  106. package/dist/components/use-select-asset.js +30 -0
  107. package/dist/error-overlay/error-origin.d.ts +3 -0
  108. package/dist/error-overlay/error-origin.js +42 -0
  109. package/dist/error-overlay/react-overlay/listen-to-runtime-errors.js +6 -2
  110. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +38 -0
  111. package/dist/error-overlay/remotion-overlay/ShortcutHint.js +1 -1
  112. package/dist/error-overlay/remotion-overlay/log-studio-error.d.ts +3 -0
  113. package/dist/error-overlay/remotion-overlay/log-studio-error.js +27 -0
  114. package/dist/esm/{chunk-48grt472.js → chunk-q0jkt0zq.js} +21961 -19299
  115. package/dist/esm/internals.mjs +21961 -19299
  116. package/dist/esm/previewEntry.mjs +20600 -17914
  117. package/dist/esm/renderEntry.mjs +1 -1
  118. package/dist/helpers/get-asset-metadata.js +2 -2
  119. package/dist/helpers/get-preview-file-type.d.ts +2 -0
  120. package/dist/helpers/get-preview-file-type.js +33 -0
  121. package/dist/helpers/install-required-package.d.ts +1 -0
  122. package/dist/helpers/install-required-package.js +39 -0
  123. package/dist/helpers/remote-asset-drag.d.ts +4 -0
  124. package/dist/helpers/remote-asset-drag.js +73 -0
  125. package/dist/helpers/use-asset-drag-events.d.ts +5 -2
  126. package/dist/helpers/use-asset-drag-events.js +13 -2
  127. package/dist/hot-middleware-client/client.js +6 -0
  128. package/dist/state/editor-outlines.d.ts +8 -0
  129. package/dist/state/editor-outlines.js +18 -0
  130. package/dist/state/modals.d.ts +19 -2
  131. package/package.json +10 -10
  132. package/dist/helpers/detect-file-type.d.ts +0 -69
  133. package/dist/helpers/detect-file-type.js +0 -278
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RenameStaticFileModal = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const remotion_1 = require("remotion");
7
+ const rename_static_file_1 = require("../../api/rename-static-file");
8
+ const url_state_1 = require("../../helpers/url-state");
9
+ const modals_1 = require("../../state/modals");
10
+ const Button_1 = require("../Button");
11
+ const layout_1 = require("../layout");
12
+ const ModalFooter_1 = require("../ModalFooter");
13
+ const ModalHeader_1 = require("../ModalHeader");
14
+ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
15
+ const layout_2 = require("../RenderModal/layout");
16
+ const use_static_files_1 = require("../use-static-files");
17
+ const DismissableModal_1 = require("./DismissableModal");
18
+ const RemInput_1 = require("./RemInput");
19
+ const ValidationMessage_1 = require("./ValidationMessage");
20
+ const content = {
21
+ padding: 12,
22
+ paddingRight: 12,
23
+ flex: 1,
24
+ fontSize: 13,
25
+ minWidth: 500,
26
+ };
27
+ const getParent = (relativePath) => {
28
+ const slashIndex = relativePath.lastIndexOf('/');
29
+ return slashIndex === -1 ? '' : relativePath.slice(0, slashIndex);
30
+ };
31
+ const getBaseName = (relativePath) => {
32
+ const slashIndex = relativePath.lastIndexOf('/');
33
+ return slashIndex === -1 ? relativePath : relativePath.slice(slashIndex + 1);
34
+ };
35
+ const RenameStaticFileModal = ({ relativePath }) => {
36
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
37
+ const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
38
+ const { setCanvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionSetters);
39
+ const staticFiles = (0, use_static_files_1.useStaticFiles)();
40
+ const [newName, setNewName] = (0, react_1.useState)(() => getBaseName(relativePath));
41
+ const [submitting, setSubmitting] = (0, react_1.useState)(false);
42
+ const parent = (0, react_1.useMemo)(() => getParent(relativePath), [relativePath]);
43
+ const newRelativePath = (0, react_1.useMemo)(() => {
44
+ return [parent, newName].filter(Boolean).join('/');
45
+ }, [newName, parent]);
46
+ const changed = newRelativePath !== relativePath;
47
+ const validationMessage = (0, react_1.useMemo)(() => {
48
+ const trimmedName = newName.trim();
49
+ if (trimmedName.length === 0) {
50
+ return 'Name cannot be empty';
51
+ }
52
+ if (trimmedName !== newName) {
53
+ return 'Name cannot start or end with whitespace';
54
+ }
55
+ if (newName.includes('/') || newName.includes('\\')) {
56
+ return 'Name cannot include slashes';
57
+ }
58
+ const existingFile = staticFiles.find((file) => {
59
+ return file.name === newRelativePath && file.name !== relativePath;
60
+ });
61
+ if (existingFile) {
62
+ return 'An asset with this name already exists';
63
+ }
64
+ return null;
65
+ }, [newName, newRelativePath, relativePath, staticFiles]);
66
+ const valid = changed && validationMessage === null;
67
+ const onNameChange = (0, react_1.useCallback)((e) => {
68
+ setNewName(e.target.value);
69
+ }, []);
70
+ const onRename = (0, react_1.useCallback)(() => {
71
+ if (!valid) {
72
+ return;
73
+ }
74
+ setSubmitting(true);
75
+ const notification = (0, NotificationCenter_1.showNotification)(`Renaming ${relativePath}...`, null);
76
+ (0, rename_static_file_1.renameStaticFile)({
77
+ oldRelativePath: relativePath,
78
+ newRelativePath,
79
+ })
80
+ .then(() => {
81
+ setSelectedModal(null);
82
+ if ((canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'asset' &&
83
+ canvasContent.asset === relativePath) {
84
+ setCanvasContent({ type: 'asset', asset: newRelativePath });
85
+ (0, url_state_1.pushUrl)(`/assets/${newRelativePath}`);
86
+ }
87
+ notification.replaceContent(`Renamed to ${newRelativePath}`, 2000);
88
+ })
89
+ .catch((err) => {
90
+ setSubmitting(false);
91
+ notification.replaceContent(`Could not rename ${relativePath}: ${err.message}`, 3000);
92
+ });
93
+ }, [
94
+ canvasContent,
95
+ newRelativePath,
96
+ relativePath,
97
+ setCanvasContent,
98
+ setSelectedModal,
99
+ valid,
100
+ ]);
101
+ const onSubmit = (0, react_1.useCallback)((e) => {
102
+ e.preventDefault();
103
+ onRename();
104
+ }, [onRename]);
105
+ return (jsx_runtime_1.jsxs(DismissableModal_1.DismissableModal, { children: [
106
+ jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: `Rename ${relativePath}` }), jsx_runtime_1.jsxs("form", { onSubmit: onSubmit, children: [
107
+ jsx_runtime_1.jsx("div", { style: content, children: jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
108
+ jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Name" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsxs("div", { children: [
109
+ jsx_runtime_1.jsx(RemInput_1.RemotionInput, { value: newName, onChange: onNameChange, type: "text", autoFocus: true, autoComplete: "off", "data-1p-ignore": true, placeholder: "Asset name", status: validationMessage ? 'error' : 'ok', rightAlign: true }), validationMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
110
+ jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: validationMessage, type: "error" })
111
+ ] })) : null] }) })
112
+ ] }) }), jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { children: jsx_runtime_1.jsxs(layout_1.Row, { align: "center", justify: "flex-end", children: [
113
+ jsx_runtime_1.jsx(Button_1.Button, { onClick: () => setSelectedModal(null), children: "Cancel" }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx(Button_1.Button, { onClick: onRename, disabled: !valid || submitting, children: "Rename" })
114
+ ] }) })
115
+ ] })
116
+ ] }));
117
+ };
118
+ exports.RenameStaticFileModal = RenameStaticFileModal;
@@ -181,7 +181,11 @@ const OptionsPanel = ({ readOnlyStudio }) => {
181
181
  saveToFile(updater);
182
182
  }
183
183
  }, [compositionId, compositionDefaultProps, saveToFile, updateProps]);
184
- return (jsx_runtime_1.jsxs("div", { style: container, className: "css-reset", children: [
184
+ const onPointerDown = (0, react_1.useCallback)((e) => {
185
+ // Prevent deselection of currently selected items
186
+ e.stopPropagation();
187
+ }, []);
188
+ return (jsx_runtime_1.jsxs("div", { style: container, className: "css-reset", onPointerDown: onPointerDown, children: [
185
189
  jsx_runtime_1.jsx("div", { style: tabsContainer, children: jsx_runtime_1.jsxs(Tabs_1.Tabs, { children: [visualControlsTabActivated ? (jsx_runtime_1.jsx(Tabs_1.Tab, { selected: panel === 'visual-controls', onClick: onVisualControlsSelected, children: "Controls" })) : null, jsx_runtime_1.jsxs(Tabs_1.Tab, { selected: panel === 'input-props', onClick: onPropsSelected, style: { justifyContent: 'space-between' }, children: ["Props", hasLocalModifications ? (jsx_runtime_1.jsx(SchemaResetButton_1.SchemaResetButton, { onClick: resetToOriginal })) : null] }), renderingAvailable ? (jsx_runtime_1.jsx(RendersTab_1.RendersTab, { onClick: onRendersSelected, selected: panel === 'renders' })) : null] }) }), panel === 'input-props' ? (composition ? (jsx_runtime_1.jsx(DefaultPropsEditor_1.DefaultPropsEditor, { unresolvedComposition: composition, defaultProps: currentDefaultProps, setDefaultProps: setDefaultProps, propsEditType: "default-props" }, composition.id)) : null) : panel === 'visual-controls' && visualControlsTabActivated ? (jsx_runtime_1.jsx(VisualControlsContent_1.VisualControlsContent, {})) : !renderingAvailable ? null : (jsx_runtime_1.jsx(RenderQueue_1.RenderQueue, {}))] }));
186
190
  };
187
191
  exports.OptionsPanel = OptionsPanel;
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const OutlineToggle: React.FC;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OutlineToggle = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const colors_1 = require("../helpers/colors");
7
+ const editor_outlines_1 = require("../state/editor-outlines");
8
+ const ControlButton_1 = require("./ControlButton");
9
+ const OutlineToggle = () => {
10
+ const { editorShowOutlines, setEditorShowOutlines } = (0, react_1.useContext)(editor_outlines_1.EditorShowOutlinesContext);
11
+ const onClick = (0, react_1.useCallback)(() => {
12
+ setEditorShowOutlines((current) => !current);
13
+ }, [setEditorShowOutlines]);
14
+ const color = editorShowOutlines ? colors_1.BLUE : 'white';
15
+ const accessibilityLabel = editorShowOutlines
16
+ ? 'Hide outlines'
17
+ : 'Show outlines';
18
+ return (jsx_runtime_1.jsx(ControlButton_1.ControlButton, { title: accessibilityLabel, "aria-label": accessibilityLabel, onClick: onClick, children: jsx_runtime_1.jsx("svg", { style: { width: 16, height: 16 }, viewBox: "0 0 512 512", fill: color, "aria-hidden": "true", focusable: "false", children: jsx_runtime_1.jsx("path", { d: "M32 119.4C12.9 108.4 0 87.7 0 64 0 28.7 28.7 0 64 0 87.7 0 108.4 12.9 119.4 32l273.1 0c11.1-19.1 31.7-32 55.4-32 35.3 0 64 28.7 64 64 0 23.7-12.9 44.4-32 55.4l0 273.1c19.1 11.1 32 31.7 32 55.4 0 35.3-28.7 64-64 64-23.7 0-44.4-12.9-55.4-32l-273.1 0c-11.1 19.1-31.7 32-55.4 32-35.3 0-64-28.7-64-64 0-23.7 12.9-44.4 32-55.4l0-273.1zm64 0l0 273.1c9.7 5.6 17.8 13.7 23.4 23.4l273.1 0c5.6-9.7 13.7-17.8 23.4-23.4l0-273.1c-9.7-5.6-17.8-13.7-23.4-23.4L119.4 96c-5.6 9.7-13.7 17.8-23.4 23.4z" }) }) }));
19
+ };
20
+ exports.OutlineToggle = OutlineToggle;
@@ -3,8 +3,6 @@ import React from 'react';
3
3
  import type { CanvasContent } from 'remotion';
4
4
  import type { AssetMetadata } from '../helpers/get-asset-metadata';
5
5
  import type { Dimensions } from '../helpers/is-current-selected-still';
6
- export type AssetFileType = 'audio' | 'video' | 'image' | 'json' | 'txt' | 'other';
7
- export declare const getPreviewFileType: (fileName: string | null) => AssetFileType;
8
6
  export declare const VideoPreview: React.FC<{
9
7
  readonly canvasSize: Size;
10
8
  readonly contentDimensions: Dimensions | 'none' | null;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.VideoPreview = exports.getPreviewFileType = void 0;
3
+ exports.VideoPreview = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const player_1 = require("@remotion/player");
6
6
  const react_1 = require("react");
@@ -8,12 +8,15 @@ const remotion_1 = require("remotion");
8
8
  const ErrorLoader_1 = require("../error-overlay/remotion-overlay/ErrorLoader");
9
9
  const checkerboard_background_1 = require("../helpers/checkerboard-background");
10
10
  const colors_1 = require("../helpers/colors");
11
+ const get_preview_file_type_1 = require("../helpers/get-preview-file-type");
11
12
  const checkerboard_1 = require("../state/checkerboard");
12
13
  const is_menu_item_1 = require("./Menu/is-menu-item");
13
14
  const RenderPreview_1 = require("./RenderPreview");
14
15
  const SelectedOutlineOverlay_1 = require("./SelectedOutlineOverlay");
15
16
  const Spinner_1 = require("./Spinner");
16
17
  const StaticFilePreview_1 = require("./StaticFilePreview");
18
+ const should_clear_selection_on_pointer_down_1 = require("./Timeline/should-clear-selection-on-pointer-down");
19
+ const TimelineSelection_1 = require("./Timeline/TimelineSelection");
17
20
  const centeredContainer = {
18
21
  display: 'flex',
19
22
  flex: 1,
@@ -33,36 +36,6 @@ const assetMetadataErrorContainer = {
33
36
  height: '100%',
34
37
  overflowY: 'auto',
35
38
  };
36
- const getPreviewFileType = (fileName) => {
37
- var _a;
38
- if (!fileName) {
39
- return 'other';
40
- }
41
- const audioExtensions = ['mp3', 'wav', 'ogg', 'aac'];
42
- const videoExtensions = ['mp4', 'avi', 'mkv', 'mov', 'webm'];
43
- const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp'];
44
- const fileExtension = (_a = fileName.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
45
- if (fileExtension === undefined) {
46
- throw new Error('File extension is undefined');
47
- }
48
- if (audioExtensions.includes(fileExtension)) {
49
- return 'audio';
50
- }
51
- if (videoExtensions.includes(fileExtension)) {
52
- return 'video';
53
- }
54
- if (imageExtensions.includes(fileExtension)) {
55
- return 'image';
56
- }
57
- if (fileExtension === 'json') {
58
- return 'json';
59
- }
60
- if (fileExtension === 'txt') {
61
- return 'txt';
62
- }
63
- return 'other';
64
- };
65
- exports.getPreviewFileType = getPreviewFileType;
66
39
  const checkerboardSize = 49;
67
40
  const containerStyle = (options) => {
68
41
  return {
@@ -126,7 +99,7 @@ const CompWhenItHasDimensions = ({ contentDimensions, canvasSize, canvasContent,
126
99
  overflow: canvasContent.type === 'composition' ? 'visible' : 'hidden',
127
100
  justifyContent: canvasContent.type === 'asset' ? 'center' : 'flex-start',
128
101
  alignItems: canvasContent.type === 'asset' &&
129
- (0, exports.getPreviewFileType)(canvasContent.asset) === 'audio'
102
+ (0, get_preview_file_type_1.getPreviewFileType)(canvasContent.asset) === 'audio'
130
103
  ? 'center'
131
104
  : 'normal',
132
105
  };
@@ -154,6 +127,8 @@ const CompWhenItHasDimensions = ({ contentDimensions, canvasSize, canvasContent,
154
127
  };
155
128
  const PortalContainer = ({ scale, xCorrection, yCorrection, contentDimensions }) => {
156
129
  const { checkerboard } = (0, react_1.useContext)(checkerboard_1.CheckerboardContext);
130
+ const { clearSelection } = (0, TimelineSelection_1.useTimelineSelection)();
131
+ const portalContainer = (0, react_1.useRef)(null);
157
132
  const style = (0, react_1.useMemo)(() => {
158
133
  return containerStyle({
159
134
  checkerboard,
@@ -178,6 +153,21 @@ const PortalContainer = ({ scale, xCorrection, yCorrection, contentDimensions })
178
153
  current === null || current === void 0 ? void 0 : current.removeChild(remotion_1.Internals.portalNode());
179
154
  };
180
155
  }, []);
181
- const portalContainer = (0, react_1.useRef)(null);
156
+ const onPointerDown = (0, react_1.useCallback)((event) => {
157
+ if (!(0, should_clear_selection_on_pointer_down_1.shouldClearSelectionOnPointerDown)(event)) {
158
+ return;
159
+ }
160
+ clearSelection();
161
+ }, [clearSelection]);
162
+ (0, react_1.useEffect)(() => {
163
+ const { current } = portalContainer;
164
+ if (!current) {
165
+ return;
166
+ }
167
+ current.addEventListener('pointerdown', onPointerDown);
168
+ return () => {
169
+ current.removeEventListener('pointerdown', onPointerDown);
170
+ };
171
+ }, [onPointerDown]);
182
172
  return jsx_runtime_1.jsx("div", { ref: portalContainer, style: style });
183
173
  };
@@ -16,12 +16,14 @@ const FullscreenToggle_1 = require("./FullscreenToggle");
16
16
  const layout_1 = require("./layout");
17
17
  const LoopToggle_1 = require("./LoopToggle");
18
18
  const MuteToggle_1 = require("./MuteToggle");
19
+ const OutlineToggle_1 = require("./OutlineToggle");
19
20
  const PlaybackKeyboardShortcutsManager_1 = require("./PlaybackKeyboardShortcutsManager");
20
21
  const PlaybackRatePersistor_1 = require("./PlaybackRatePersistor");
21
22
  const PlaybackRateSelector_1 = require("./PlaybackRateSelector");
22
23
  const PlayPause_1 = require("./PlayPause");
23
24
  const RenderButton_1 = require("./RenderButton");
24
25
  const SizeSelector_1 = require("./SizeSelector");
26
+ const TimelineSelection_1 = require("./Timeline/TimelineSelection");
25
27
  const TimelineZoomControls_1 = require("./Timeline/TimelineZoomControls");
26
28
  const TimelineInOutToggle_1 = require("./TimelineInOutToggle");
27
29
  const TOOLBAR_HEIGHT = 50;
@@ -70,6 +72,16 @@ const sideContainer = {
70
72
  const padding = {
71
73
  width: timeline_layout_1.TIMELINE_PADDING,
72
74
  };
75
+ const toolbarControl = {
76
+ display: 'contents',
77
+ };
78
+ const PreviewToolbarControl = ({ children }) => {
79
+ const onPointerDown = (0, react_1.useCallback)((e) => {
80
+ // Prevent deselection of currently selected items
81
+ e.stopPropagation();
82
+ }, []);
83
+ return (jsx_runtime_1.jsx("div", { style: toolbarControl, onPointerDown: onPointerDown, children: children }));
84
+ };
73
85
  const PreviewToolbar = ({ readOnlyStudio, bufferStateDelayInMilliseconds }) => {
74
86
  const { playbackRate, setPlaybackRate } = remotion_1.Internals.usePlaybackRate();
75
87
  const { mediaMuted } = (0, react_1.useContext)(remotion_1.Internals.MediaVolumeContext);
@@ -136,12 +148,13 @@ const PreviewToolbar = ({ readOnlyStudio, bufferStateDelayInMilliseconds }) => {
136
148
  return (jsx_runtime_1.jsxs("div", { ref: previewToolbarRef, style: isMobileLayout ? mobileContainer : container, className: "css-reset", children: [
137
149
  jsx_runtime_1.jsx("div", { ref: leftScrollIndicatorRef, style: scrollIndicatorLeft }), isMobileLayout ? null : (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
138
150
  jsx_runtime_1.jsxs("div", { style: sideContainer, children: [
139
- jsx_runtime_1.jsx("div", { style: padding }), jsx_runtime_1.jsx(TimelineZoomControls_1.TimelineZoomControls, {})
140
- ] }), jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsx(SizeSelector_1.SizeSelector, {}), isStill || isVideoComposition ? (jsx_runtime_1.jsx(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate })) : null] })), isVideoComposition ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
141
- jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PlayPause_1.PlayPause, { bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds, loop: loop, playbackRate: playbackRate, muted: mediaMuted }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(LoopToggle_1.LoopToggle, { loop: loop, setLoop: setLoop }), jsx_runtime_1.jsx(MuteToggle_1.MuteToggle, { muted: mediaMuted, setMuted: setMediaMuted }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(TimelineInOutToggle_1.TimelineInOutPointToggle, {}), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 })
142
- ] })) : null, (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition' ? jsx_runtime_1.jsx(CheckboardToggle_1.CheckboardToggle, {}) : null, jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), canvasContent && isFullscreenSupported ? jsx_runtime_1.jsx(FullscreenToggle_1.FullScreenToggle, {}) : null, jsx_runtime_1.jsx(layout_1.Flex, {}), isMobileLayout && (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
143
- jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsx(SizeSelector_1.SizeSelector, {}), isStill || isVideoComposition ? (jsx_runtime_1.jsx(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate })) : null] })), jsx_runtime_1.jsxs("div", { style: sideContainer, children: [
144
- jsx_runtime_1.jsx(layout_1.Flex, {}), !isMobileLayout && jsx_runtime_1.jsx(FpsCounter_1.FpsCounter, { playbackSpeed: playbackRate }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(RenderButton_1.RenderButton, { readOnlyStudio: readOnlyStudio }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1.5 })
151
+ jsx_runtime_1.jsx("div", { style: padding }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(TimelineZoomControls_1.TimelineZoomControls, {}) })
152
+ ] }), jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(SizeSelector_1.SizeSelector, {}) }), isStill || isVideoComposition ? (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate }) })) : null] })), isVideoComposition ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
153
+ jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(PlayPause_1.PlayPause, { bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds, loop: loop, playbackRate: playbackRate, muted: mediaMuted }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(LoopToggle_1.LoopToggle, { loop: loop, setLoop: setLoop }) }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(MuteToggle_1.MuteToggle, { muted: mediaMuted, setMuted: setMediaMuted }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(TimelineInOutToggle_1.TimelineInOutPointToggle, {}) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 })
154
+ ] })) : null, (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition' ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
155
+ jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(CheckboardToggle_1.CheckboardToggle, {}) }), TimelineSelection_1.ENABLE_OUTLINES ? (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(OutlineToggle_1.OutlineToggle, {}) })) : null] })) : null, jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), canvasContent && isFullscreenSupported ? (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(FullscreenToggle_1.FullScreenToggle, {}) })) : null, jsx_runtime_1.jsx(layout_1.Flex, {}), isMobileLayout && (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
156
+ jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(SizeSelector_1.SizeSelector, {}) }), isStill || isVideoComposition ? (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate }) })) : null] })), jsx_runtime_1.jsxs("div", { style: sideContainer, children: [
157
+ jsx_runtime_1.jsx(layout_1.Flex, {}), !isMobileLayout && jsx_runtime_1.jsx(FpsCounter_1.FpsCounter, { playbackSpeed: playbackRate }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(RenderButton_1.RenderButton, { readOnlyStudio: readOnlyStudio }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1.5 })
145
158
  ] }), jsx_runtime_1.jsx(PlaybackKeyboardShortcutsManager_1.PlaybackKeyboardShortcutsManager, { setPlaybackRate: setPlaybackRate }), jsx_runtime_1.jsx(PlaybackRatePersistor_1.PlaybackRatePersistor, {}), jsx_runtime_1.jsx("div", { ref: rightScrollIndicatorRef, style: scrollIndicatorRight })
146
159
  ] }));
147
160
  };
@@ -102,7 +102,9 @@ const RenderButton = ({ readOnlyStudio, }) => {
102
102
  shouldApplyCssTransforms: true,
103
103
  });
104
104
  const refresh = size === null || size === void 0 ? void 0 : size.refresh;
105
- const onPointerDown = (0, react_1.useCallback)(() => {
105
+ const onPointerDown = (0, react_1.useCallback)((e) => {
106
+ // Prevent deselection of currently selected items
107
+ e.stopPropagation();
106
108
  setDropdownOpened((o) => {
107
109
  if (!o) {
108
110
  refresh === null || refresh === void 0 ? void 0 : refresh();
@@ -110,6 +112,10 @@ const RenderButton = ({ readOnlyStudio, }) => {
110
112
  return !o;
111
113
  });
112
114
  }, [refresh]);
115
+ const onMenuPointerDown = (0, react_1.useCallback)((e) => {
116
+ // Prevent deselection of currently selected items
117
+ e.stopPropagation();
118
+ }, []);
113
119
  const onClickDropdown = (0, react_1.useCallback)((e) => {
114
120
  e.stopPropagation();
115
121
  const isKeyboardInitiated = e.detail === 0;
@@ -420,7 +426,7 @@ const RenderButton = ({ readOnlyStudio, }) => {
420
426
  ] }) }), shouldShowDropdown ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
421
427
  jsx_runtime_1.jsx("div", { style: dividerStyle }), jsx_runtime_1.jsx("button", { ref: dropdownRef, type: "button", style: dropdownTriggerStyle, disabled: !readOnlyStudio && connectionStatus !== 'connected', className: is_menu_item_1.MENU_INITIATOR_CLASSNAME, onPointerDown: onPointerDown, onClick: onClickDropdown, children: jsx_runtime_1.jsx(caret_1.CaretDown, {}) })
422
428
  ] })) : null] }), portalStyle
423
- ? react_dom_1.default.createPortal(jsx_runtime_1.jsx("div", { style: styles_1.fullScreenOverlay, children: jsx_runtime_1.jsx("div", { style: styles_1.outerPortal, className: "css-reset", children: jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onOutsideClick: onHideDropdown, onEscape: onHideDropdown, children: jsx_runtime_1.jsx("div", { style: portalStyle, children: jsx_runtime_1.jsx(MenuContent_1.MenuContent, { onNextMenu: () => { }, onPreviousMenu: () => { }, values: dropdownValues, onHide: onHideDropdown, leaveLeftSpace: false, preselectIndex: dropdownValues.findIndex((v) => v.id === renderType), topItemCanBeUnselected: false, fixedHeight: derivedMaxHeight }) }) }) }) }), (0, portals_1.getPortal)(currentZIndex))
429
+ ? react_dom_1.default.createPortal(jsx_runtime_1.jsx("div", { style: styles_1.fullScreenOverlay, children: jsx_runtime_1.jsx("div", { style: styles_1.outerPortal, className: "css-reset", children: jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onOutsideClick: onHideDropdown, onEscape: onHideDropdown, children: jsx_runtime_1.jsx("div", { style: portalStyle, onPointerDown: onMenuPointerDown, children: jsx_runtime_1.jsx(MenuContent_1.MenuContent, { onNextMenu: () => { }, onPreviousMenu: () => { }, values: dropdownValues, onHide: onHideDropdown, leaveLeftSpace: false, preselectIndex: dropdownValues.findIndex((v) => v.id === renderType), topItemCanBeUnselected: false, fixedHeight: derivedMaxHeight }) }) }) }) }), (0, portals_1.getPortal)(currentZIndex))
424
430
  : null] }));
425
431
  };
426
432
  exports.RenderButton = RenderButton;
@@ -6,8 +6,8 @@ const react_1 = require("react");
6
6
  const client_id_1 = require("../helpers/client-id");
7
7
  const colors_1 = require("../helpers/colors");
8
8
  const get_asset_metadata_1 = require("../helpers/get-asset-metadata");
9
+ const get_preview_file_type_1 = require("../helpers/get-preview-file-type");
9
10
  const FilePreview_1 = require("./FilePreview");
10
- const Preview_1 = require("./Preview");
11
11
  const msgStyle = {
12
12
  fontSize: 13,
13
13
  color: 'white',
@@ -20,7 +20,7 @@ const errMsgStyle = {
20
20
  color: colors_1.LIGHT_TEXT,
21
21
  };
22
22
  const RenderPreview = ({ path, assetMetadata, getBlob }) => {
23
- const fileType = (0, Preview_1.getPreviewFileType)(path);
23
+ const fileType = (0, get_preview_file_type_1.getPreviewFileType)(path);
24
24
  const connectionStatus = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx)
25
25
  .previewServerState.type;
26
26
  const [blobUrl, setBlobUrl] = (0, react_1.useState)(null);
@@ -8,6 +8,26 @@ type OutlinePoint = {
8
8
  readonly y: number;
9
9
  };
10
10
  type UvCoordinate = readonly [number, number];
11
+ type UvCoordinateFieldSchema = Extract<SequenceFieldSchema, {
12
+ type: 'uv-coordinate';
13
+ }>;
14
+ type SelectedOutlineUvHandle = {
15
+ readonly clientId: string;
16
+ readonly codeValue: CanUpdateSequencePropStatusStatic;
17
+ readonly effectIndex: number;
18
+ readonly fieldDefault: UvCoordinate | undefined;
19
+ readonly fieldKey: string;
20
+ readonly fieldSchema: UvCoordinateFieldSchema;
21
+ readonly nodePath: SequencePropsSubscriptionKey;
22
+ readonly schema: SequenceSchema;
23
+ readonly value: UvCoordinate;
24
+ };
25
+ type UvConnectionHandle = Pick<SelectedOutlineUvHandle, 'effectIndex' | 'fieldKey' | 'fieldSchema' | 'value'>;
26
+ type UvHandleConnectionLine = {
27
+ readonly key: string;
28
+ readonly from: OutlinePoint;
29
+ readonly to: OutlinePoint;
30
+ };
11
31
  type SelectedOutlineDragTarget = {
12
32
  readonly codeValue: CanUpdateSequencePropStatusStatic | CanUpdateSequencePropStatusKeyframed;
13
33
  readonly clientId: string;
@@ -52,6 +72,10 @@ type SequenceWithSelectedOutline = {
52
72
  readonly sequence: TSequence;
53
73
  };
54
74
  export declare const getUvHandlePosition: (points: readonly [OutlinePoint, OutlinePoint, OutlinePoint, OutlinePoint], uv: UvCoordinate) => OutlinePoint;
75
+ export declare const getUvHandleConnectionLines: ({ handles, points, }: {
76
+ readonly handles: readonly UvConnectionHandle[];
77
+ readonly points: readonly [OutlinePoint, OutlinePoint, OutlinePoint, OutlinePoint];
78
+ }) => UvHandleConnectionLine[];
55
79
  export declare const getUvCoordinateForPoint: (points: readonly [OutlinePoint, OutlinePoint, OutlinePoint, OutlinePoint], point: OutlinePoint) => UvCoordinate;
56
80
  export declare const getOutlineSelectionInteraction: ({ shiftKey, metaKey, ctrlKey, }: {
57
81
  readonly shiftKey: boolean;