@remotion/studio 4.0.120 → 4.0.122

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.
@@ -1,5 +1,5 @@
1
1
 
2
2
  
3
- > @remotion/studio@4.0.118 build /Users/jonathanburger/remotion/packages/studio
3
+ > @remotion/studio@4.0.121 build /Users/jonathanburger/remotion/packages/studio
4
4
  > tsc -d
5
5
 
@@ -9,6 +9,7 @@ const player_1 = require("@remotion/player");
9
9
  const react_1 = require("react");
10
10
  const react_dom_1 = __importDefault(require("react-dom"));
11
11
  const colors_1 = require("../../helpers/colors");
12
+ const mobile_layout_1 = require("../../helpers/mobile-layout");
12
13
  const use_keybinding_1 = require("../../helpers/use-keybinding");
13
14
  const caret_1 = require("../../icons/caret");
14
15
  const z_index_1 = require("../../state/z-index");
@@ -50,6 +51,7 @@ const MenuSubItem = ({ label, leaveLeftSpace, leftItem, onActionChosen, id, sele
50
51
  triggerOnWindowResize: true,
51
52
  shouldApplyCssTransforms: true,
52
53
  });
54
+ const mobileLayout = (0, mobile_layout_1.useMobileLayout)();
53
55
  const { currentZIndex } = (0, z_index_1.useZIndex)();
54
56
  const style = (0, react_1.useMemo)(() => {
55
57
  return {
@@ -57,9 +59,14 @@ const MenuSubItem = ({ label, leaveLeftSpace, leftItem, onActionChosen, id, sele
57
59
  backgroundColor: selected ? colors_1.CLEAR_HOVER : 'transparent',
58
60
  };
59
61
  }, [selected]);
60
- const onItemTriggered = (0, react_1.useCallback)((e) => {
62
+ const onPointerUp = (0, react_1.useCallback)((e) => {
63
+ if (subMenu) {
64
+ setSubMenuActivated('with-mouse');
65
+ setHovered(true);
66
+ return;
67
+ }
61
68
  onActionChosen(id, e);
62
- }, [id, onActionChosen]);
69
+ }, [id, onActionChosen, setSubMenuActivated, subMenu]);
63
70
  const onPointerEnter = (0, react_1.useCallback)(() => {
64
71
  onItemSelected(id);
65
72
  setHovered(true);
@@ -74,12 +81,13 @@ const MenuSubItem = ({ label, leaveLeftSpace, leftItem, onActionChosen, id, sele
74
81
  if (!selected || !size || !subMenu || !subMenuActivated) {
75
82
  return null;
76
83
  }
84
+ const left = size.left + size.width + styles_1.SUBMENU_LEFT_INSET;
77
85
  return {
78
86
  ...styles_1.menuContainerTowardsBottom,
79
- left: size.left + size.width + styles_1.SUBMENU_LEFT_INSET,
87
+ left: mobileLayout ? left * 0.7 : left,
80
88
  top: size.top - styles_1.MENU_VERTICAL_PADDING,
81
89
  };
82
- }, [selected, size, subMenu, subMenuActivated]);
90
+ }, [mobileLayout, selected, size, subMenu, subMenuActivated]);
83
91
  (0, react_1.useEffect)(() => {
84
92
  if (!hovered || !subMenu) {
85
93
  return;
@@ -98,7 +106,7 @@ const MenuSubItem = ({ label, leaveLeftSpace, leftItem, onActionChosen, id, sele
98
106
  });
99
107
  }
100
108
  }, [selected]);
101
- return ((0, jsx_runtime_1.jsx)("div", { ref: ref, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, style: style, onPointerUp: onItemTriggered, role: "button", className: is_menu_item_1.MENU_ITEM_CLASSNAME, children: (0, jsx_runtime_1.jsxs)(layout_1.Row, { align: "center", children: [leaveLeftSpace ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: leftSpace, children: leftItem }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1 })] })) : null, (0, jsx_runtime_1.jsx)("div", { style: labelStyle, ...{ title: typeof label === 'string' ? label : undefined }, children: label }), ' ', (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), subMenu ? (0, jsx_runtime_1.jsx)(caret_1.CaretRight, {}) : null, keyHint && !(0, use_keybinding_1.areKeyboardShortcutsDisabled)() ? ((0, jsx_runtime_1.jsx)("span", { style: keyHintCss, children: keyHint })) : null, portalStyle && subMenu
109
+ return ((0, jsx_runtime_1.jsx)("div", { ref: ref, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, style: style, onPointerUp: onPointerUp, role: "button", className: is_menu_item_1.MENU_ITEM_CLASSNAME, children: (0, jsx_runtime_1.jsxs)(layout_1.Row, { align: "center", children: [leaveLeftSpace ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: leftSpace, children: leftItem }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1 })] })) : null, (0, jsx_runtime_1.jsx)("div", { style: labelStyle, ...{ title: typeof label === 'string' ? label : undefined }, children: label }), ' ', (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), subMenu ? (0, jsx_runtime_1.jsx)(caret_1.CaretRight, {}) : null, keyHint && !(0, use_keybinding_1.areKeyboardShortcutsDisabled)() ? ((0, jsx_runtime_1.jsx)("span", { style: keyHintCss, children: keyHint })) : null, portalStyle && subMenu
102
110
  ? react_dom_1.default.createPortal((0, jsx_runtime_1.jsx)(SubMenu_1.SubMenuComponent, { onQuitFullMenu: onQuitMenu, subMenu: subMenu, onQuitSubMenu: onQuitSubmenu, portalStyle: portalStyle, subMenuActivated: subMenuActivated }), (0, portals_1.getPortal)(currentZIndex))
103
111
  : null] }) }));
104
112
  };
@@ -2,11 +2,23 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SubMenuComponent = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const mobile_layout_1 = require("../../helpers/mobile-layout");
5
7
  const noop_1 = require("../../helpers/noop");
6
8
  const z_index_1 = require("../../state/z-index");
7
9
  const MenuContent_1 = require("../NewComposition/MenuContent");
10
+ const portals_1 = require("./portals");
8
11
  const SubMenuComponent = ({ portalStyle, subMenuActivated, subMenu, onQuitFullMenu, onQuitSubMenu, }) => {
9
- return ((0, jsx_runtime_1.jsx)(z_index_1.HigherZIndex, { onEscape: onQuitFullMenu, onOutsideClick: noop_1.noop, children: (0, jsx_runtime_1.jsx)("div", { style: portalStyle, className: "css-reset", children: (0, jsx_runtime_1.jsx)(MenuContent_1.MenuContent, { onNextMenu: noop_1.noop, onPreviousMenu: onQuitSubMenu, values: subMenu.items, onHide: noop_1.noop, leaveLeftSpace: subMenu.leaveLeftSpace, preselectIndex: subMenuActivated === 'without-mouse' &&
12
+ const mobileLayout = (0, mobile_layout_1.useMobileLayout)();
13
+ const onOutsideClick = (0, react_1.useCallback)((e) => {
14
+ if (portals_1.portals.find((p) => p.contains(e)) || mobileLayout) {
15
+ onQuitSubMenu();
16
+ }
17
+ else {
18
+ onQuitFullMenu();
19
+ }
20
+ }, [mobileLayout, onQuitFullMenu, onQuitSubMenu]);
21
+ return ((0, jsx_runtime_1.jsx)(z_index_1.HigherZIndex, { onEscape: onQuitFullMenu, onOutsideClick: onOutsideClick, children: (0, jsx_runtime_1.jsx)("div", { style: portalStyle, className: "css-reset", children: (0, jsx_runtime_1.jsx)(MenuContent_1.MenuContent, { onNextMenu: noop_1.noop, onPreviousMenu: onQuitSubMenu, values: subMenu.items, onHide: onQuitFullMenu, leaveLeftSpace: subMenu.leaveLeftSpace, preselectIndex: subMenuActivated === 'without-mouse' &&
10
22
  typeof subMenu.preselectIndex === 'number'
11
23
  ? subMenu.preselectIndex
12
24
  : false, topItemCanBeUnselected: false, fixedHeight: null }) }) }));
@@ -1 +1,2 @@
1
+ export declare const portals: Element[];
1
2
  export declare const getPortal: (i: number) => Element;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getPortal = void 0;
4
- const portals = [
3
+ exports.getPortal = exports.portals = void 0;
4
+ exports.portals = [
5
5
  document.getElementById('menuportal-0'),
6
6
  document.getElementById('menuportal-1'),
7
7
  document.getElementById('menuportal-2'),
@@ -10,6 +10,6 @@ const portals = [
10
10
  document.getElementById('menuportal-5'),
11
11
  ];
12
12
  const getPortal = (i) => {
13
- return portals[i];
13
+ return exports.portals[i];
14
14
  };
15
15
  exports.getPortal = getPortal;
@@ -4,6 +4,7 @@ exports.MenuToolbar = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const colors_1 = require("../helpers/colors");
7
+ const mobile_layout_1 = require("../helpers/mobile-layout");
7
8
  const use_menu_structure_1 = require("../helpers/use-menu-structure");
8
9
  const layout_1 = require("./layout");
9
10
  const MenuItem_1 = require("./Menu/MenuItem");
@@ -21,23 +22,36 @@ const row = {
21
22
  paddingRight: 10,
22
23
  backgroundColor: colors_1.BACKGROUND,
23
24
  };
24
- const fixedWidthRight = {
25
- width: '330px',
26
- display: 'flex',
27
- alignItems: 'center',
28
- justifyContent: 'flex-end',
29
- };
30
- const fixedWidthLeft = {
31
- minWidth: '330px',
32
- display: 'flex',
33
- alignItems: 'center',
34
- justifyContent: 'flex-start',
35
- };
36
25
  const flex = {
37
26
  flex: 1,
38
27
  };
39
28
  const MenuToolbar = ({ readOnlyStudio }) => {
40
29
  const [selected, setSelected] = (0, react_1.useState)(null);
30
+ const mobileLayout = (0, mobile_layout_1.useMobileLayout)();
31
+ const fixedWidthRight = (0, react_1.useMemo)(() => {
32
+ return {
33
+ ...(mobileLayout
34
+ ? { width: 'fit-content' }
35
+ : {
36
+ width: '330px',
37
+ }),
38
+ display: 'flex',
39
+ alignItems: 'center',
40
+ justifyContent: 'flex-end',
41
+ };
42
+ }, [mobileLayout]);
43
+ const fixedWidthLeft = (0, react_1.useMemo)(() => {
44
+ return {
45
+ ...(mobileLayout
46
+ ? { minWidth: '0px' }
47
+ : {
48
+ minWidth: '330px',
49
+ }),
50
+ display: 'flex',
51
+ alignItems: 'center',
52
+ justifyContent: 'flex-start',
53
+ };
54
+ }, [mobileLayout]);
41
55
  const itemClicked = (0, react_1.useCallback)((itemId) => {
42
56
  setSelected(itemId);
43
57
  }, [setSelected]);
@@ -208,7 +208,8 @@ const MenuContent = ({ onHide, values, preselectIndex, onNextMenu, onPreviousMen
208
208
  }
209
209
  const item = values.find((i) => i.id === selectedItem);
210
210
  if (!item) {
211
- throw new Error('cannot find item');
211
+ // Can happen if resizing the window
212
+ return;
212
213
  }
213
214
  if (item.type === 'divider') {
214
215
  throw new Error('should not select divider');
@@ -236,8 +237,11 @@ const MenuContent = ({ onHide, values, preselectIndex, onNextMenu, onPreviousMen
236
237
  return (0, jsx_runtime_1.jsx)(MenuDivider_1.MenuDivider, {}, item.id);
237
238
  }
238
239
  const onClick = (id, e) => {
239
- onHide();
240
240
  item.onClick(id, e);
241
+ if (item.subMenu) {
242
+ return null;
243
+ }
244
+ onHide();
241
245
  };
242
246
  return ((0, jsx_runtime_1.jsx)(MenuSubItem_1.MenuSubItem, { selected: item.id === selectedItem, onActionChosen: onClick, onItemSelected: onItemSelected, label: item.label, id: item.id, keyHint: item.keyHint, leaveLeftSpace: leaveLeftSpace, leftItem: item.leftItem, subMenu: item.subMenu, onQuitMenu: onHide, onNextMenu: onNextMenu, subMenuActivated: subMenuActivated, setSubMenuActivated: setSubMenuActivated }, item.id));
243
247
  }) }));
@@ -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)" | "#f1c40f" | "rgba(0, 0, 0, 0.6)" | "rgba(255, 255, 255, 0.05)" | "#ff3232";
15
+ }) => "hsla(0, 0%, 100%, 0.15)" | "#ff3232" | "#f1c40f" | "rgba(0, 0, 0, 0.6)" | "rgba(255, 255, 255, 0.05)";
16
16
  export declare const RemotionInput: React.ForwardRefExoticComponent<Omit<Props, "ref"> & React.RefAttributes<HTMLInputElement>>;
17
17
  export {};
@@ -23,4 +23,4 @@ export declare const TIMELINE_TRACK_SEPARATOR = "rgba(0, 0, 0, 0.3)";
23
23
  export declare const getBackgroundFromHoverState: ({ selected, hovered, }: {
24
24
  selected: boolean;
25
25
  hovered: boolean;
26
- }) => "transparent" | "rgba(255, 255, 255, 0.06)" | "hsla(0, 0%, 100%, 0.15)" | "hsla(0, 0%, 100%, 0.25)";
26
+ }) => "transparent" | "hsla(0, 0%, 100%, 0.15)" | "rgba(255, 255, 255, 0.06)" | "hsla(0, 0%, 100%, 0.25)";
@@ -1,10 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useMobileLayout = void 0;
4
- const use_el_size_1 = require("./use-el-size");
4
+ const react_1 = require("react");
5
+ const breakpoint = 900;
6
+ function getIsMobile() {
7
+ return window.innerWidth < breakpoint;
8
+ }
5
9
  const useMobileLayout = () => {
6
- var _a;
7
- const containerSize = (0, use_el_size_1.useElementSize)(typeof document === 'undefined' ? null : document.body);
8
- return ((_a = containerSize === null || containerSize === void 0 ? void 0 : containerSize.width) !== null && _a !== void 0 ? _a : Infinity) < 900;
10
+ const [isMobile, setIsMobile] = (0, react_1.useState)(getIsMobile());
11
+ const isMobileRef = (0, react_1.useRef)(isMobile);
12
+ (0, react_1.useEffect)(() => {
13
+ function handleResize() {
14
+ if (getIsMobile() !== isMobileRef.current) {
15
+ setIsMobile(getIsMobile());
16
+ }
17
+ isMobileRef.current = getIsMobile();
18
+ }
19
+ window.addEventListener('resize', handleResize);
20
+ return () => {
21
+ return window.removeEventListener('resize', handleResize);
22
+ };
23
+ }, []);
24
+ return isMobile;
9
25
  };
10
26
  exports.useMobileLayout = useMobileLayout;
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  import type { Codec } from '@remotion/renderer';
2
3
  import type { RenderType } from '../components/RenderModal/RenderModalAdvanced';
3
4
  type Section = 'general' | 'picture' | 'advanced' | 'data' | 'gif' | 'audio';
@@ -21,6 +21,7 @@ const modals_1 = require("../state/modals");
21
21
  const sidebar_1 = require("../state/sidebar");
22
22
  const client_id_1 = require("./client-id");
23
23
  const get_git_menu_item_1 = require("./get-git-menu-item");
24
+ const mobile_layout_1 = require("./mobile-layout");
24
25
  const open_in_editor_1 = require("./open-in-editor");
25
26
  const pick_color_1 = require("./pick-color");
26
27
  const use_keybinding_1 = require("./use-keybinding");
@@ -160,8 +161,9 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
160
161
  const { setSidebarCollapsedState, sidebarCollapsedStateLeft, sidebarCollapsedStateRight, } = (0, react_1.useContext)(sidebar_1.SidebarContext);
161
162
  const sizes = (0, SizeSelector_1.getUniqueSizes)(size);
162
163
  const isFullscreenSupported = document.fullscreenEnabled || document.webkitFullscreenEnabled;
164
+ const mobileLayout = (0, mobile_layout_1.useMobileLayout)();
163
165
  const structure = (0, react_1.useMemo)(() => {
164
- const struct = [
166
+ let struct = [
165
167
  {
166
168
  id: 'remotion',
167
169
  label: ((0, jsx_runtime_1.jsx)(layout_1.Row, { align: "center", justify: "center", children: (0, jsx_runtime_1.jsx)("svg", { width: ICON_SIZE, height: ICON_SIZE, viewBox: "-100 -100 400 400", style: rotate, children: (0, jsx_runtime_1.jsx)("path", { fill: "#fff", stroke: "#fff", strokeWidth: "100", strokeLinejoin: "round", d: "M 2 172 a 196 100 0 0 0 195 5 A 196 240 0 0 0 100 2.259 A 196 240 0 0 0 2 172 z" }) }) })),
@@ -728,9 +730,36 @@ const useMenuStructure = (closeMenu, readOnlyStudio) => {
728
730
  ],
729
731
  },
730
732
  ].filter(remotion_1.Internals.truthy);
733
+ if (mobileLayout) {
734
+ struct = [
735
+ {
736
+ ...struct[0],
737
+ items: [
738
+ ...struct.slice(1).map((s) => {
739
+ return {
740
+ ...s,
741
+ keyHint: null,
742
+ onClick: () => undefined,
743
+ type: 'item',
744
+ value: s.id,
745
+ leftItem: null,
746
+ subMenu: {
747
+ items: s.items,
748
+ leaveLeftSpace: true,
749
+ preselectIndex: 0,
750
+ },
751
+ quickSwitcherLabel: null,
752
+ };
753
+ }),
754
+ ...struct[0].items,
755
+ ],
756
+ },
757
+ ];
758
+ }
731
759
  return struct;
732
760
  }, [
733
761
  readOnlyStudio,
762
+ mobileLayout,
734
763
  sizes,
735
764
  editorZoomGestures,
736
765
  editorShowRulers,
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  export declare const HigherZIndex: React.FC<{
3
3
  onEscape: () => void;
4
- onOutsideClick: () => void;
4
+ onOutsideClick: (target: Node) => void;
5
5
  children: React.ReactNode;
6
6
  }>;
7
7
  export declare const useZIndex: () => {
@@ -49,13 +49,12 @@ const HigherZIndex = ({ children, onEscape, onOutsideClick }) => {
49
49
  return;
50
50
  }
51
51
  onUp = (upEvent) => {
52
- if (outsideClick &&
53
- highestContext.highestIndex === currentIndex &&
52
+ if (highestContext.highestIndex === currentIndex &&
54
53
  !(0, input_dragger_click_lock_1.getClickLock)() &&
55
54
  // Don't trigger if that click removed that node
56
55
  document.contains(upEvent.target)) {
57
56
  upEvent.stopPropagation();
58
- onOutsideClick();
57
+ onOutsideClick(upEvent.target);
59
58
  }
60
59
  };
61
60
  window.addEventListener('pointerup', onUp, { once: true });
@@ -66,11 +65,11 @@ const HigherZIndex = ({ children, onEscape, onOutsideClick }) => {
66
65
  window.addEventListener('pointerdown', listener);
67
66
  });
68
67
  return () => {
69
- onUp = null;
70
68
  if (onUp) {
71
69
  // @ts-expect-error
72
70
  window.removeEventListener('pointerup', onUp, { once: true });
73
71
  }
72
+ onUp = null;
74
73
  return window.removeEventListener('pointerdown', listener);
75
74
  };
76
75
  }, [currentIndex, highestContext.highestIndex, onOutsideClick]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/studio",
3
- "version": "4.0.120",
3
+ "version": "4.0.122",
4
4
  "description": "Remotion Editor",
5
5
  "main": "dist",
6
6
  "sideEffects": false,
@@ -18,11 +18,11 @@
18
18
  "memfs": "3.4.3",
19
19
  "source-map": "0.7.3",
20
20
  "open": "^8.4.2",
21
- "remotion": "4.0.120",
22
- "@remotion/player": "4.0.120",
23
- "@remotion/media-utils": "4.0.120",
24
- "@remotion/renderer": "4.0.120",
25
- "@remotion/studio-shared": "4.0.120"
21
+ "@remotion/player": "4.0.122",
22
+ "@remotion/media-utils": "4.0.122",
23
+ "remotion": "4.0.122",
24
+ "@remotion/renderer": "4.0.122",
25
+ "@remotion/studio-shared": "4.0.122"
26
26
  },
27
27
  "devDependencies": {
28
28
  "react": "18.2.0",
@@ -40,7 +40,7 @@
40
40
  "prettier-plugin-organize-imports": "3.2.4",
41
41
  "vitest": "0.31.1",
42
42
  "zod": "^3.22.3",
43
- "@remotion/zod-types": "4.0.120"
43
+ "@remotion/zod-types": "4.0.122"
44
44
  },
45
45
  "publishConfig": {
46
46
  "access": "public"