@remotion/cli 4.0.43 → 4.0.44

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 (61) hide show
  1. package/dist/config/index.d.ts +1 -1
  2. package/dist/config/log.d.ts +1 -1
  3. package/dist/editor/components/AssetSelector.js +19 -3
  4. package/dist/editor/components/AssetSelectorItem.d.ts +6 -4
  5. package/dist/editor/components/AssetSelectorItem.js +48 -23
  6. package/dist/editor/components/Canvas.d.ts +4 -1
  7. package/dist/editor/components/Canvas.js +72 -30
  8. package/dist/editor/components/CanvasOrLoading.js +9 -1
  9. package/dist/editor/components/CheckboardToggle.js +5 -0
  10. package/dist/editor/components/CompositionSelector.js +8 -6
  11. package/dist/editor/components/CompositionSelectorItem.d.ts +1 -1
  12. package/dist/editor/components/CurrentCompositionSideEffects.js +11 -4
  13. package/dist/editor/components/EditorContent.js +4 -1
  14. package/dist/editor/components/ExplorerPanel.js +0 -13
  15. package/dist/editor/components/FilePreview.d.ts +8 -0
  16. package/dist/editor/components/FilePreview.js +33 -0
  17. package/dist/editor/components/FramePersistor.d.ts +0 -1
  18. package/dist/editor/components/FramePersistor.js +1 -5
  19. package/dist/editor/components/InitialCompositionLoader.js +61 -18
  20. package/dist/editor/components/LoopToggle.js +3 -1
  21. package/dist/editor/components/MuteToggle.js +3 -1
  22. package/dist/editor/components/NewComposition/RemInput.d.ts +2 -2
  23. package/dist/editor/components/NewComposition/RemInputTypeColor.d.ts +1 -1
  24. package/dist/editor/components/NewComposition/RemTextarea.d.ts +1 -1
  25. package/dist/editor/components/OptionsPanel.js +7 -7
  26. package/dist/editor/components/PlayPause.js +2 -1
  27. package/dist/editor/components/PlaybackRateSelector.js +3 -1
  28. package/dist/editor/components/Preview.d.ts +7 -0
  29. package/dist/editor/components/Preview.js +156 -30
  30. package/dist/editor/components/RenderPreview.d.ts +4 -0
  31. package/dist/editor/components/RenderPreview.js +30 -0
  32. package/dist/editor/components/RendersTab.js +9 -1
  33. package/dist/editor/components/SizeSelector.js +15 -0
  34. package/dist/editor/components/StaticFilePreview.d.ts +4 -0
  35. package/dist/editor/components/StaticFilePreview.js +47 -0
  36. package/dist/editor/components/TextViewer.d.ts +4 -0
  37. package/dist/editor/components/TextViewer.js +26 -0
  38. package/dist/editor/components/Timeline/TimelineZoomControls.js +3 -1
  39. package/dist/editor/components/TimelineInOutToggle.js +2 -1
  40. package/dist/editor/components/ZoomPersistor.d.ts +2 -0
  41. package/dist/editor/components/ZoomPersistor.js +29 -7
  42. package/dist/editor/helpers/checkerboard-background.d.ts +1 -1
  43. package/dist/editor/helpers/colors.d.ts +1 -1
  44. package/dist/editor/helpers/create-folder-tree.d.ts +4 -3
  45. package/dist/editor/helpers/create-folder-tree.js +6 -3
  46. package/dist/editor/helpers/document-title.d.ts +1 -1
  47. package/dist/editor/helpers/document-title.js +14 -8
  48. package/dist/editor/helpers/is-current-selected-still.d.ts +3 -3
  49. package/dist/editor/helpers/is-current-selected-still.js +1 -15
  50. package/dist/editor/helpers/persist-open-folders.d.ts +4 -2
  51. package/dist/editor/helpers/persist-open-folders.js +7 -5
  52. package/dist/editor/state/folders.d.ts +4 -2
  53. package/dist/editor/state/folders.js +13 -6
  54. package/dist/get-cli-options.d.ts +2 -2
  55. package/dist/index.d.ts +10 -10
  56. package/dist/log.d.ts +4 -4
  57. package/package.json +8 -8
  58. package/dist/config/presets-profile.d.ts +0 -3
  59. package/dist/config/presets-profile.js +0 -12
  60. package/dist/handle-common-errors.d.ts +0 -2
  61. package/dist/handle-common-errors.js +0 -60
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ExplorerPanel = exports.optionsSidebarTabs = exports.persistSelectedOptionsSidebarPanel = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
- const remotion_1 = require("remotion");
7
6
  const colors_1 = require("../helpers/colors");
8
7
  const AssetSelector_1 = require("./AssetSelector");
9
8
  const CompositionSelector_1 = require("./CompositionSelector");
@@ -50,18 +49,6 @@ const ExplorerPanel = () => {
50
49
  },
51
50
  };
52
51
  }, []);
53
- const { compositions, currentComposition } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
54
- const composition = (0, react_1.useMemo)(() => {
55
- for (const comp of compositions) {
56
- if (comp.id === currentComposition) {
57
- return comp;
58
- }
59
- }
60
- return null;
61
- }, [compositions, currentComposition]);
62
- if (composition === null) {
63
- return null;
64
- }
65
52
  return ((0, jsx_runtime_1.jsxs)("div", { style: container, className: "css-reset", children: [(0, jsx_runtime_1.jsx)("div", { style: tabsContainer, children: (0, jsx_runtime_1.jsxs)(Tabs_1.Tabs, { children: [(0, jsx_runtime_1.jsx)(Tabs_1.Tab, { selected: panel === 'compositions', onClick: onCompositionsSelected, children: "Compositions" }), (0, jsx_runtime_1.jsx)(Tabs_1.Tab, { selected: panel === 'assets', onClick: onAssetsSelected, children: "Assets" })] }) }), panel === 'compositions' ? (0, jsx_runtime_1.jsx)(CompositionSelector_1.CompositionSelector, {}) : (0, jsx_runtime_1.jsx)(AssetSelector_1.AssetSelector, {})] }));
66
53
  };
67
54
  exports.ExplorerPanel = ExplorerPanel;
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import type { AssetFileType } from './Preview';
3
+ export declare const FilePreview: React.FC<{
4
+ src: string;
5
+ fileType: AssetFileType;
6
+ currentAsset: string;
7
+ fileSize: string | null;
8
+ }>;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FilePreview = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const JSONViewer_1 = require("./JSONViewer");
6
+ const layout_1 = require("./layout");
7
+ const TextViewer_1 = require("./TextViewer");
8
+ const msgStyle = {
9
+ fontSize: 13,
10
+ color: 'white',
11
+ fontFamily: 'sans-serif',
12
+ display: 'flex',
13
+ justifyContent: 'center',
14
+ };
15
+ const FilePreview = ({ fileType, src, currentAsset, fileSize }) => {
16
+ if (fileType === 'audio') {
17
+ return ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("audio", { src: src, controls: true }) }));
18
+ }
19
+ if (fileType === 'video') {
20
+ return (0, jsx_runtime_1.jsx)("video", { src: src, controls: true });
21
+ }
22
+ if (fileType === 'image') {
23
+ return (0, jsx_runtime_1.jsx)("img", { src: src });
24
+ }
25
+ if (fileType === 'json') {
26
+ return (0, jsx_runtime_1.jsx)(JSONViewer_1.JSONViewer, { src: src });
27
+ }
28
+ if (fileType === 'txt') {
29
+ return (0, jsx_runtime_1.jsx)(TextViewer_1.TextViewer, { src: src });
30
+ }
31
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: msgStyle, children: currentAsset }), fileSize ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1 }), (0, jsx_runtime_1.jsxs)("div", { style: msgStyle, children: ["Size: ", fileSize, " "] })] })) : null] }));
32
+ };
33
+ exports.FilePreview = FilePreview;
@@ -1,3 +1,2 @@
1
1
  import type React from 'react';
2
- export declare const getCurrentCompositionFromUrl: () => string;
3
2
  export declare const FramePersistor: React.FC;
@@ -1,12 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FramePersistor = exports.getCurrentCompositionFromUrl = void 0;
3
+ exports.FramePersistor = void 0;
4
4
  const react_1 = require("react");
5
5
  const remotion_1 = require("remotion");
6
- const getCurrentCompositionFromUrl = () => {
7
- return window.location.pathname.substr(1);
8
- };
9
- exports.getCurrentCompositionFromUrl = getCurrentCompositionFromUrl;
10
6
  const FramePersistor = () => {
11
7
  const [playing] = remotion_1.Internals.Timeline.usePlayingState();
12
8
  const config = (0, remotion_1.useVideoConfig)();
@@ -5,18 +5,38 @@ const react_1 = require("react");
5
5
  const remotion_1 = require("remotion");
6
6
  const folders_1 = require("../state/folders");
7
7
  const CompositionSelector_1 = require("./CompositionSelector");
8
- const FramePersistor_1 = require("./FramePersistor");
8
+ const ZoomPersistor_1 = require("./ZoomPersistor");
9
+ const useSelectAsset = () => {
10
+ const { setCanvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
11
+ const { setAssetFoldersExpanded } = (0, react_1.useContext)(folders_1.FolderContext);
12
+ return (asset) => {
13
+ setCanvasContent({ type: 'asset', asset });
14
+ setAssetFoldersExpanded((ex) => {
15
+ const split = asset.split('/');
16
+ const keysToExpand = split.map((_, i) => {
17
+ return split.slice(0, i).join('/');
18
+ });
19
+ const newState = {
20
+ ...ex,
21
+ };
22
+ for (const key of keysToExpand) {
23
+ newState[key] = true;
24
+ }
25
+ return newState;
26
+ });
27
+ };
28
+ };
9
29
  const useSelectComposition = () => {
10
- const { setFoldersExpanded } = (0, react_1.useContext)(folders_1.FolderContext);
11
- const { setCurrentComposition } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
30
+ const { setCompositionFoldersExpanded } = (0, react_1.useContext)(folders_1.FolderContext);
31
+ const { setCanvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
12
32
  return (c, push) => {
13
33
  if (push) {
14
34
  window.history.pushState({}, 'Studio', `/${c.id}`);
15
35
  }
16
- setCurrentComposition(c.id);
36
+ setCanvasContent({ type: 'composition', compositionId: c.id });
17
37
  const { folderName, parentFolderName } = c;
18
38
  if (folderName !== null) {
19
- setFoldersExpanded((ex) => {
39
+ setCompositionFoldersExpanded((ex) => {
20
40
  const keysToExpand = (0, CompositionSelector_1.getKeysToExpand)(folderName, parentFolderName);
21
41
  const newState = {
22
42
  ...ex,
@@ -31,35 +51,58 @@ const useSelectComposition = () => {
31
51
  };
32
52
  exports.useSelectComposition = useSelectComposition;
33
53
  const InitialCompositionLoader = () => {
34
- const { compositions, currentComposition } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
54
+ const { compositions, canvasContent, setCanvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
35
55
  const selectComposition = (0, exports.useSelectComposition)();
56
+ const selectAsset = useSelectAsset();
36
57
  (0, react_1.useEffect)(() => {
37
- if (currentComposition) {
58
+ if (canvasContent) {
38
59
  return;
39
60
  }
40
- const compositionFromUrl = (0, FramePersistor_1.getCurrentCompositionFromUrl)();
41
- if (compositionFromUrl) {
42
- const exists = compositions.find((c) => c.id === compositionFromUrl);
61
+ const canvasContentFromUrl = (0, ZoomPersistor_1.deriveCanvasContentFromUrl)();
62
+ if (canvasContentFromUrl && canvasContentFromUrl.type === 'composition') {
63
+ const exists = compositions.find((c) => c.id === canvasContentFromUrl.compositionId);
43
64
  if (exists) {
44
- selectComposition(exists, true);
45
- return;
65
+ selectComposition(exists, false);
46
66
  }
67
+ return;
68
+ }
69
+ if (canvasContentFromUrl && canvasContentFromUrl.type === 'asset') {
70
+ selectAsset(canvasContentFromUrl.asset);
71
+ return;
47
72
  }
48
73
  if (compositions.length > 0) {
49
74
  selectComposition(compositions[0], true);
50
75
  }
51
- }, [compositions, currentComposition, selectComposition]);
76
+ }, [
77
+ compositions,
78
+ canvasContent,
79
+ selectComposition,
80
+ setCanvasContent,
81
+ selectAsset,
82
+ ]);
52
83
  (0, react_1.useEffect)(() => {
53
84
  const onchange = () => {
54
- const newComp = window.location.pathname.substring(1);
55
- const exists = compositions.find((c) => c.id === newComp);
56
- if (exists) {
57
- selectComposition(exists, false);
85
+ const newCanvas = (0, ZoomPersistor_1.deriveCanvasContentFromUrl)();
86
+ if (newCanvas && (newCanvas === null || newCanvas === void 0 ? void 0 : newCanvas.type) === 'composition') {
87
+ const newComp = window.location.pathname.substring(1);
88
+ const exists = compositions.find((c) => c.id === newComp);
89
+ if (exists) {
90
+ selectComposition(exists, false);
91
+ }
92
+ }
93
+ else if (newCanvas && newCanvas.type === 'asset') {
94
+ const staticFiles = (0, remotion_1.getStaticFiles)();
95
+ const exists = staticFiles.find((file) => {
96
+ return file.name === newCanvas.asset;
97
+ });
98
+ if (exists) {
99
+ setCanvasContent(newCanvas);
100
+ }
58
101
  }
59
102
  };
60
103
  window.addEventListener('popstate', onchange);
61
104
  return () => window.removeEventListener('popstate', onchange);
62
- }, [compositions, selectComposition]);
105
+ }, [compositions, selectComposition, setCanvasContent]);
63
106
  return null;
64
107
  };
65
108
  exports.InitialCompositionLoader = InitialCompositionLoader;
@@ -3,12 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LoopToggle = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
+ const remotion_1 = require("remotion");
6
7
  const colors_1 = require("../helpers/colors");
7
8
  const is_current_selected_still_1 = require("../helpers/is-current-selected-still");
8
9
  const loop_1 = require("../state/loop");
9
10
  const ControlButton_1 = require("./ControlButton");
10
11
  const accessibilityLabel = 'Loop video';
11
12
  const LoopToggle = ({ loop, setLoop }) => {
13
+ const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
12
14
  const onClick = (0, react_1.useCallback)(() => {
13
15
  setLoop((c) => {
14
16
  (0, loop_1.persistLoopOption)(!c);
@@ -16,7 +18,7 @@ const LoopToggle = ({ loop, setLoop }) => {
16
18
  });
17
19
  }, [setLoop]);
18
20
  const isStill = (0, is_current_selected_still_1.useIsStill)();
19
- if (isStill) {
21
+ if (isStill || canvasContent === null || canvasContent.type === 'asset') {
20
22
  return null;
21
23
  }
22
24
  return ((0, jsx_runtime_1.jsx)(ControlButton_1.ControlButton, { title: accessibilityLabel, "aria-label": accessibilityLabel, onClick: onClick, children: (0, jsx_runtime_1.jsx)("svg", { viewBox: "0 0 512 512", style: { width: 18, height: 18 }, children: (0, jsx_runtime_1.jsx)("path", { fill: loop ? colors_1.BLUE : 'white', d: "M493.544 181.463c11.956 22.605 18.655 48.4 18.452 75.75C511.339 345.365 438.56 416 350.404 416H192v47.495c0 22.475-26.177 32.268-40.971 17.475l-80-80c-9.372-9.373-9.372-24.569 0-33.941l80-80C166.138 271.92 192 282.686 192 304v48h158.875c52.812 0 96.575-42.182 97.12-94.992.155-15.045-3.17-29.312-9.218-42.046-4.362-9.185-2.421-20.124 4.8-27.284 4.745-4.706 8.641-8.555 11.876-11.786 11.368-11.352 30.579-8.631 38.091 5.571zM64.005 254.992c.545-52.81 44.308-94.992 97.12-94.992H320v47.505c0 22.374 26.121 32.312 40.971 17.465l80-80c9.372-9.373 9.372-24.569 0-33.941l-80-80C346.014 16.077 320 26.256 320 48.545V96H161.596C73.44 96 .661 166.635.005 254.788c-.204 27.35 6.495 53.145 18.452 75.75 7.512 14.202 26.723 16.923 38.091 5.57 3.235-3.231 7.13-7.08 11.876-11.786 7.22-7.16 9.162-18.098 4.8-27.284-6.049-12.735-9.374-27.001-9.219-42.046z" }) }) }));
@@ -3,11 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MuteToggle = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
+ const remotion_1 = require("remotion");
6
7
  const is_current_selected_still_1 = require("../helpers/is-current-selected-still");
7
8
  const media_volume_1 = require("../icons/media-volume");
8
9
  const mute_1 = require("../state/mute");
9
10
  const ControlButton_1 = require("./ControlButton");
10
11
  const MuteToggle = ({ muted, setMuted }) => {
12
+ const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
11
13
  const onClick = (0, react_1.useCallback)(() => {
12
14
  setMuted((m) => {
13
15
  (0, mute_1.persistMuteOption)(!m);
@@ -16,7 +18,7 @@ const MuteToggle = ({ muted, setMuted }) => {
16
18
  }, [setMuted]);
17
19
  const accessibilityLabel = muted ? 'Unmute video' : 'Mute video';
18
20
  const isStill = (0, is_current_selected_still_1.useIsStill)();
19
- if (isStill) {
21
+ if (isStill || canvasContent === null || canvasContent.type === 'asset') {
20
22
  return null;
21
23
  }
22
24
  return ((0, jsx_runtime_1.jsx)(ControlButton_1.ControlButton, { title: accessibilityLabel, "aria-label": accessibilityLabel, onClick: onClick, children: muted ? (0, jsx_runtime_1.jsx)(media_volume_1.VolumeOffIcon, {}) : (0, jsx_runtime_1.jsx)(media_volume_1.VolumeOnIcon, {}) }));
@@ -12,6 +12,6 @@ export declare const getInputBorderColor: ({ status, isFocused, isHovered, }: {
12
12
  status: 'error' | 'warning' | 'ok';
13
13
  isFocused: boolean;
14
14
  isHovered: boolean;
15
- }) => "hsla(0, 0%, 100%, 0.15)" | "#ff3232" | "#f1c40f" | "rgba(255, 255, 255, 0.05)" | "rgba(0, 0, 0, 0.6)";
16
- export declare const RemotionInput: React.ForwardRefExoticComponent<Pick<Props, "status" | "key" | "rightAlign" | keyof React.InputHTMLAttributes<HTMLInputElement>> & React.RefAttributes<HTMLInputElement>>;
15
+ }) => "hsla(0, 0%, 100%, 0.15)" | "rgba(0, 0, 0, 0.6)" | "rgba(255, 255, 255, 0.05)" | "#ff3232" | "#f1c40f";
16
+ export declare const RemotionInput: React.ForwardRefExoticComponent<Pick<Props, "key" | keyof React.InputHTMLAttributes<HTMLInputElement> | "status" | "rightAlign"> & React.RefAttributes<HTMLInputElement>>;
17
17
  export {};
@@ -4,5 +4,5 @@ type Props = React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>
4
4
  status: RemInputStatus;
5
5
  name: string;
6
6
  };
7
- export declare const RemInputTypeColor: React.ForwardRefExoticComponent<Pick<Props, "status" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>> & React.RefAttributes<HTMLInputElement>>;
7
+ export declare const RemInputTypeColor: React.ForwardRefExoticComponent<Pick<Props, "key" | keyof React.InputHTMLAttributes<HTMLInputElement> | "status"> & React.RefAttributes<HTMLInputElement>>;
8
8
  export {};
@@ -3,5 +3,5 @@ type Props = React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLTextAreaEleme
3
3
  status: 'error' | 'warning' | 'ok';
4
4
  };
5
5
  export declare const inputBaseStyle: React.CSSProperties;
6
- export declare const RemTextarea: React.ForwardRefExoticComponent<Pick<Props, "status" | "key" | keyof React.InputHTMLAttributes<HTMLTextAreaElement>> & React.RefAttributes<HTMLTextAreaElement>>;
6
+ export declare const RemTextarea: React.ForwardRefExoticComponent<Pick<Props, "key" | "status" | keyof React.InputHTMLAttributes<HTMLTextAreaElement>> & React.RefAttributes<HTMLTextAreaElement>>;
7
7
  export {};
@@ -59,7 +59,7 @@ const OptionsPanel = () => {
59
59
  },
60
60
  };
61
61
  }, []);
62
- const { compositions, currentComposition } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
62
+ const { compositions, canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
63
63
  const circleStyle = (0, react_1.useMemo)(() => {
64
64
  const onTabColor = saving ? colors_1.LIGHT_TEXT : 'white';
65
65
  return {
@@ -69,13 +69,16 @@ const OptionsPanel = () => {
69
69
  };
70
70
  }, [panel, saving]);
71
71
  const composition = (0, react_1.useMemo)(() => {
72
+ if (canvasContent === null || canvasContent.type !== 'composition') {
73
+ return null;
74
+ }
72
75
  for (const comp of compositions) {
73
- if (comp.id === currentComposition) {
76
+ if (comp.id === canvasContent.compositionId) {
74
77
  return comp;
75
78
  }
76
79
  }
77
80
  return null;
78
- }, [compositions, currentComposition]);
81
+ }, [canvasContent, compositions]);
79
82
  const saveToolTip = (0, react_1.useMemo)(() => {
80
83
  return process.env.KEYBOARD_SHORTCUTS_ENABLED
81
84
  ? `Save using ${ShortcutHint_1.cmdOrCtrlCharacter}+S`
@@ -104,9 +107,6 @@ const OptionsPanel = () => {
104
107
  }
105
108
  return !(0, deep_equal_1.deepEqual)(composition.defaultProps, actualProps);
106
109
  }, [actualProps, composition]);
107
- if (composition === null) {
108
- return null;
109
- }
110
- return ((0, jsx_runtime_1.jsxs)("div", { style: container, className: "css-reset", children: [(0, jsx_runtime_1.jsx)("div", { style: tabsContainer, children: (0, jsx_runtime_1.jsxs)(Tabs_1.Tabs, { children: [(0, jsx_runtime_1.jsxs)(Tabs_1.Tab, { selected: panel === 'input-props', onClick: onPropsSelected, style: { justifyContent: 'space-between' }, children: ["Props", unsavedChangesExist ? ((0, jsx_runtime_1.jsx)("div", { title: saveToolTip, style: circleStyle })) : null] }), (0, jsx_runtime_1.jsx)(RendersTab_1.RendersTab, { onClick: onRendersSelected, selected: panel === 'renders' })] }) }), panel === 'renders' ? ((0, jsx_runtime_1.jsx)(RenderQueue_1.RenderQueue, {})) : ((0, jsx_runtime_1.jsx)(DataEditor_1.DataEditor, { unresolvedComposition: composition, inputProps: actualProps, setInputProps: setInputProps, mayShowSaveButton: true, propsEditType: "default-props", saving: saving, setSaving: setSaving }, composition.id))] }));
110
+ return ((0, jsx_runtime_1.jsxs)("div", { style: container, className: "css-reset", children: [(0, jsx_runtime_1.jsx)("div", { style: tabsContainer, children: (0, jsx_runtime_1.jsxs)(Tabs_1.Tabs, { children: [composition ? ((0, jsx_runtime_1.jsxs)(Tabs_1.Tab, { selected: panel === 'input-props', onClick: onPropsSelected, style: { justifyContent: 'space-between' }, children: ["Props", unsavedChangesExist ? ((0, jsx_runtime_1.jsx)("div", { title: saveToolTip, style: circleStyle })) : null] })) : null, (0, jsx_runtime_1.jsx)(RendersTab_1.RendersTab, { onClick: onRendersSelected, selected: panel === 'renders' })] }) }), panel === `input-props` && composition ? ((0, jsx_runtime_1.jsx)(DataEditor_1.DataEditor, { unresolvedComposition: composition, inputProps: actualProps, setInputProps: setInputProps, mayShowSaveButton: true, propsEditType: "default-props", saving: saving, setSaving: setSaving }, composition.id)) : ((0, jsx_runtime_1.jsx)(RenderQueue_1.RenderQueue, {}))] }));
111
111
  };
112
112
  exports.OptionsPanel = OptionsPanel;
@@ -23,6 +23,7 @@ const forwardBackStyle = {
23
23
  const PlayPause = ({ playbackRate, loop }) => {
24
24
  const { inFrame, outFrame } = (0, in_out_1.useTimelineInOutFramePosition)();
25
25
  const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
26
+ const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
26
27
  player_1.PlayerInternals.usePlayback({
27
28
  loop,
28
29
  playbackRate,
@@ -186,7 +187,7 @@ const PlayPause = ({ playbackRate, loop }) => {
186
187
  onEnter,
187
188
  onSpace,
188
189
  ]);
189
- if (isStill) {
190
+ if (isStill || canvasContent === null || canvasContent.type === 'asset') {
190
191
  return null;
191
192
  }
192
193
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ControlButton_1.ControlButton, { "aria-label": "Jump to beginning", title: "Jump to beginning", disabled: !videoConfig || isFirstFrame, onClick: jumpToStart, children: (0, jsx_runtime_1.jsx)(jump_to_start_1.JumpToStart, { style: forwardBackStyle }) }), (0, jsx_runtime_1.jsx)(ControlButton_1.ControlButton, { "aria-label": "Step back one frame", title: "Step back one frame", disabled: !videoConfig || isFirstFrame, onClick: oneFrameBack, children: (0, jsx_runtime_1.jsx)(step_back_1.StepBack, { style: forwardBackStyle }) }), (0, jsx_runtime_1.jsx)(ControlButton_1.ControlButton, { "aria-label": playing ? 'Pause' : 'Play', title: playing ? 'Pause' : 'Play', onClick: playing ? pause : play, disabled: !videoConfig, children: playing ? ((0, jsx_runtime_1.jsx)(pause_1.Pause, { style: {
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PlaybackRateSelector = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
+ const remotion_1 = require("remotion");
6
7
  const is_current_selected_still_1 = require("../helpers/is-current-selected-still");
7
8
  const Checkmark_1 = require("../icons/Checkmark");
8
9
  const playbackrate_1 = require("../state/playbackrate");
@@ -17,6 +18,7 @@ const getPlaybackRateLabel = (playbackRate) => {
17
18
  const accessibilityLabel = 'Change the playback rate';
18
19
  const comboStyle = { width: 80 };
19
20
  const PlaybackRateSelector = ({ playbackRate, setPlaybackRate }) => {
21
+ const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
20
22
  const isStill = (0, is_current_selected_still_1.useIsStill)();
21
23
  const style = (0, react_1.useMemo)(() => {
22
24
  return {
@@ -49,7 +51,7 @@ const PlaybackRateSelector = ({ playbackRate, setPlaybackRate }) => {
49
51
  const middle = Math.floor(commonPlaybackRates.length / 2);
50
52
  return [...values.slice(0, middle), divider, ...values.slice(middle)];
51
53
  }, [playbackRate, setPlaybackRate]);
52
- if (isStill) {
54
+ if (isStill || canvasContent === null || canvasContent.type === 'asset') {
53
55
  return null;
54
56
  }
55
57
  return ((0, jsx_runtime_1.jsx)("div", { style: style, "aria-label": accessibilityLabel, children: (0, jsx_runtime_1.jsx)(ComboBox_1.Combobox, { title: accessibilityLabel, style: comboStyle, selectedId: String(playbackRate), values: items }) }));
@@ -1,5 +1,12 @@
1
1
  import type { Size } from '@remotion/player';
2
2
  import React from 'react';
3
+ import type { CanvasContent } from 'remotion';
4
+ import type { Dimensions } from '../helpers/is-current-selected-still';
5
+ type AssetFileType = 'audio' | 'video' | 'image' | 'json' | 'txt' | 'other';
6
+ export declare const getPreviewFileType: (fileName: string | null) => AssetFileType;
3
7
  export declare const VideoPreview: React.FC<{
4
8
  canvasSize: Size;
9
+ contentDimensions: Dimensions | 'none' | null;
10
+ canvasContent: CanvasContent;
5
11
  }>;
12
+ export {};
@@ -1,13 +1,67 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.VideoPreview = void 0;
3
+ exports.VideoPreview = exports.getPreviewFileType = 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");
7
7
  const remotion_1 = require("remotion");
8
+ const format_bytes_1 = require("../../format-bytes");
8
9
  const checkerboard_background_1 = require("../helpers/checkerboard-background");
10
+ const client_id_1 = require("../helpers/client-id");
11
+ const colors_1 = require("../helpers/colors");
9
12
  const checkerboard_1 = require("../state/checkerboard");
10
13
  const preview_size_1 = require("../state/preview-size");
14
+ const JSONViewer_1 = require("./JSONViewer");
15
+ const layout_1 = require("./layout");
16
+ const Spinner_1 = require("./Spinner");
17
+ const TextViewer_1 = require("./TextViewer");
18
+ const spinnerContainer = {
19
+ display: 'flex',
20
+ flex: 1,
21
+ justifyContent: 'center',
22
+ alignItems: 'center',
23
+ };
24
+ const msgStyle = {
25
+ fontSize: 13,
26
+ color: 'white',
27
+ fontFamily: 'sans-serif',
28
+ display: 'flex',
29
+ justifyContent: 'center',
30
+ };
31
+ const errMsgStyle = {
32
+ ...msgStyle,
33
+ color: colors_1.LIGHT_TEXT,
34
+ };
35
+ const getPreviewFileType = (fileName) => {
36
+ var _a;
37
+ if (!fileName) {
38
+ return 'other';
39
+ }
40
+ const audioExtensions = ['mp3', 'wav', 'ogg', 'aac'];
41
+ const videoExtensions = ['mp4', 'avi', 'mkv', 'mov', 'webm'];
42
+ const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp'];
43
+ const fileExtension = (_a = fileName.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
44
+ if (fileExtension === undefined) {
45
+ throw new Error('File extension is undefined');
46
+ }
47
+ if (audioExtensions.includes(fileExtension)) {
48
+ return 'audio';
49
+ }
50
+ if (videoExtensions.includes(fileExtension)) {
51
+ return 'video';
52
+ }
53
+ if (imageExtensions.includes(fileExtension)) {
54
+ return 'image';
55
+ }
56
+ if (fileExtension === 'json') {
57
+ return 'json';
58
+ }
59
+ if (fileExtension === 'txt') {
60
+ return 'txt';
61
+ }
62
+ return 'other';
63
+ };
64
+ exports.getPreviewFileType = getPreviewFileType;
11
65
  const checkerboardSize = 49;
12
66
  const containerStyle = (options) => {
13
67
  return {
@@ -24,50 +78,129 @@ const containerStyle = (options) => {
24
78
  backgroundPosition: (0, checkerboard_background_1.getCheckerboardBackgroundPos)(checkerboardSize) /* Must be half of one side of the square */,
25
79
  };
26
80
  };
27
- const Inner = ({ canvasSize }) => {
81
+ const AssetComponent = ({ currentAsset }) => {
82
+ const fileType = (0, exports.getPreviewFileType)(currentAsset);
83
+ const staticFileSrc = (0, remotion_1.staticFile)(currentAsset);
84
+ const staticFiles = (0, remotion_1.getStaticFiles)();
85
+ const connectionStatus = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx).type;
86
+ const exists = staticFiles.find((file) => file.name === currentAsset);
87
+ if (connectionStatus === 'disconnected') {
88
+ return (0, jsx_runtime_1.jsx)("div", { style: errMsgStyle, children: "Studio server disconnected" });
89
+ }
90
+ if (!exists) {
91
+ return ((0, jsx_runtime_1.jsxs)("div", { style: errMsgStyle, children: [currentAsset, " does not exist in your public folder."] }));
92
+ }
93
+ const fileSize = () => {
94
+ const fileFromStaticFiles = staticFiles.find((file) => file.name === currentAsset);
95
+ if (fileFromStaticFiles) {
96
+ return (0, format_bytes_1.formatBytes)(fileFromStaticFiles === null || fileFromStaticFiles === void 0 ? void 0 : fileFromStaticFiles.sizeInBytes);
97
+ }
98
+ };
99
+ if (!currentAsset) {
100
+ return null;
101
+ }
102
+ if (fileType === 'audio') {
103
+ try {
104
+ return ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("audio", { src: staticFileSrc, controls: true }) }));
105
+ }
106
+ catch (err) {
107
+ return (0, jsx_runtime_1.jsx)("div", { style: errMsgStyle, children: "The audio could not be loaded" });
108
+ }
109
+ }
110
+ if (fileType === 'video') {
111
+ try {
112
+ return (0, jsx_runtime_1.jsx)("video", { src: staticFileSrc, controls: true });
113
+ }
114
+ catch (err) {
115
+ return (0, jsx_runtime_1.jsx)("div", { style: errMsgStyle, children: "The video could not be loaded" });
116
+ }
117
+ }
118
+ if (fileType === 'image') {
119
+ try {
120
+ return (0, jsx_runtime_1.jsx)("img", { src: staticFileSrc });
121
+ }
122
+ catch (err) {
123
+ return (0, jsx_runtime_1.jsx)("div", { style: errMsgStyle, children: "The image could not be loaded" });
124
+ }
125
+ }
126
+ if (fileType === 'json') {
127
+ return (0, jsx_runtime_1.jsx)(JSONViewer_1.JSONViewer, { src: staticFileSrc });
128
+ }
129
+ if (fileType === 'txt') {
130
+ return (0, jsx_runtime_1.jsx)(TextViewer_1.TextViewer, { src: staticFileSrc });
131
+ }
132
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: msgStyle, children: currentAsset }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1 }), (0, jsx_runtime_1.jsxs)("div", { style: msgStyle, children: ["Size: ", fileSize(), " "] })] }));
133
+ };
134
+ const VideoPreview = ({ canvasSize, contentDimensions, canvasContent }) => {
135
+ if (!contentDimensions) {
136
+ return ((0, jsx_runtime_1.jsx)("div", { style: spinnerContainer, children: (0, jsx_runtime_1.jsx)(Spinner_1.Spinner, { duration: 0.5, size: 24 }) }));
137
+ }
138
+ return ((0, jsx_runtime_1.jsx)(CompWhenItHasDimensions, { contentDimensions: contentDimensions, canvasSize: canvasSize, canvasContent: canvasContent }));
139
+ };
140
+ exports.VideoPreview = VideoPreview;
141
+ const CompWhenItHasDimensions = ({ contentDimensions, canvasSize, canvasContent }) => {
28
142
  const { size: previewSize } = (0, react_1.useContext)(preview_size_1.PreviewSizeContext);
29
- const portalContainer = (0, react_1.useRef)(null);
30
- const config = (0, remotion_1.useVideoConfig)();
31
- const { checkerboard } = (0, react_1.useContext)(checkerboard_1.CheckerboardContext);
32
- const { centerX, centerY, yCorrection, xCorrection, scale } = player_1.PlayerInternals.calculateCanvasTransformation({
33
- canvasSize,
34
- compositionHeight: config.height,
35
- compositionWidth: config.width,
36
- previewSize: previewSize.size,
37
- });
143
+ const { centerX, centerY, yCorrection, xCorrection, scale } = (0, react_1.useMemo)(() => {
144
+ if (contentDimensions === 'none') {
145
+ return {
146
+ centerX: 0,
147
+ centerY: 0,
148
+ yCorrection: 0,
149
+ xCorrection: 0,
150
+ scale: 1,
151
+ };
152
+ }
153
+ return player_1.PlayerInternals.calculateCanvasTransformation({
154
+ canvasSize,
155
+ compositionHeight: contentDimensions.height,
156
+ compositionWidth: contentDimensions.width,
157
+ previewSize: previewSize.size,
158
+ });
159
+ }, [canvasSize, contentDimensions, previewSize.size]);
38
160
  const outer = (0, react_1.useMemo)(() => {
39
161
  return {
40
- width: config.width * scale,
41
- height: config.height * scale,
162
+ width: contentDimensions === 'none' ? '100%' : contentDimensions.width * scale,
163
+ height: contentDimensions === 'none'
164
+ ? '100%'
165
+ : contentDimensions.height * scale,
42
166
  display: 'flex',
43
167
  flexDirection: 'column',
44
168
  position: 'absolute',
45
169
  left: centerX - previewSize.translation.x,
46
170
  top: centerY - previewSize.translation.y,
47
171
  overflow: 'hidden',
172
+ justifyContent: canvasContent.type === 'asset' ? 'center' : 'flex-start',
173
+ alignItems: canvasContent.type === 'asset' &&
174
+ (0, exports.getPreviewFileType)(canvasContent.asset) === 'audio'
175
+ ? 'center'
176
+ : 'normal',
48
177
  };
49
178
  }, [
179
+ contentDimensions,
180
+ scale,
50
181
  centerX,
51
- centerY,
52
- config.height,
53
- config.width,
54
182
  previewSize.translation.x,
55
183
  previewSize.translation.y,
56
- scale,
184
+ centerY,
185
+ canvasContent,
57
186
  ]);
187
+ return ((0, jsx_runtime_1.jsx)("div", { style: outer, children: canvasContent.type === 'asset' ? ((0, jsx_runtime_1.jsx)(AssetComponent, { currentAsset: canvasContent.asset })) : ((0, jsx_runtime_1.jsx)(PortalContainer, { contentDimensions: contentDimensions, scale: scale, xCorrection: xCorrection, yCorrection: yCorrection })) }));
188
+ };
189
+ const PortalContainer = ({ scale, xCorrection, yCorrection, contentDimensions }) => {
190
+ const { checkerboard } = (0, react_1.useContext)(checkerboard_1.CheckerboardContext);
58
191
  const style = (0, react_1.useMemo)(() => {
59
192
  return containerStyle({
60
193
  checkerboard,
61
194
  scale,
62
195
  xCorrection,
63
196
  yCorrection,
64
- width: config.width,
65
- height: config.height,
197
+ width: contentDimensions.width,
198
+ height: contentDimensions.height,
66
199
  });
67
200
  }, [
68
201
  checkerboard,
69
- config.height,
70
- config.width,
202
+ contentDimensions.height,
203
+ contentDimensions.width,
71
204
  scale,
72
205
  xCorrection,
73
206
  yCorrection,
@@ -79,13 +212,6 @@ const Inner = ({ canvasSize }) => {
79
212
  current === null || current === void 0 ? void 0 : current.removeChild(remotion_1.Internals.portalNode());
80
213
  };
81
214
  }, []);
82
- return ((0, jsx_runtime_1.jsx)("div", { style: outer, children: (0, jsx_runtime_1.jsx)("div", { ref: portalContainer, style: style }) }));
83
- };
84
- const VideoPreview = ({ canvasSize }) => {
85
- const config = remotion_1.Internals.useUnsafeVideoConfig();
86
- if (!config) {
87
- return null;
88
- }
89
- return (0, jsx_runtime_1.jsx)(Inner, { canvasSize: canvasSize });
215
+ const portalContainer = (0, react_1.useRef)(null);
216
+ return (0, jsx_runtime_1.jsx)("div", { ref: portalContainer, style: style });
90
217
  };
91
- exports.VideoPreview = VideoPreview;
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const RenderPreview: React.FC<{
3
+ path: string;
4
+ }>;