UNPKG

@remotion/studio

Version:

APIs for interacting with the Remotion Studio

174 lines (173 loc) 7.83 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Combobox = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const player_1 = require("@remotion/player"); const react_1 = require("react"); const react_dom_1 = __importDefault(require("react-dom")); const colors_1 = require("../../helpers/colors"); const mobile_layout_1 = require("../../helpers/mobile-layout"); const noop_1 = require("../../helpers/noop"); const caret_1 = require("../../icons/caret"); const z_index_1 = require("../../state/z-index"); const layout_1 = require("../layout"); const is_menu_item_1 = require("../Menu/is-menu-item"); const portals_1 = require("../Menu/portals"); const styles_1 = require("../Menu/styles"); const MenuContent_1 = require("./MenuContent"); const container = { padding: '8px 10px', display: 'inline-block', backgroundColor: colors_1.INPUT_BACKGROUND, borderWidth: 1, borderStyle: 'solid', maxWidth: '100%', }; const label = { flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', fontSize: 14, textAlign: 'left', }; const Combobox = ({ values, selectedId, style: customStyle, title }) => { const [hovered, setIsHovered] = (0, react_1.useState)(false); const [opened, setOpened] = (0, react_1.useState)(false); const ref = (0, react_1.useRef)(null); const { tabIndex, currentZIndex } = (0, z_index_1.useZIndex)(); const size = player_1.PlayerInternals.useElementSize(ref, { triggerOnWindowResize: true, shouldApplyCssTransforms: true, }); const refresh = size === null || size === void 0 ? void 0 : size.refresh; const onHide = (0, react_1.useCallback)(() => { setOpened(false); }, []); (0, react_1.useEffect)(() => { const { current } = ref; if (!current) { return; } const onMouseEnter = () => setIsHovered(true); const onMouseLeave = () => setIsHovered(false); const onPointerDown = () => { return setOpened((o) => { if (!o) { refresh === null || refresh === void 0 ? void 0 : refresh(); } return !o; }); }; const onClick = (e) => { e.stopPropagation(); const isKeyboardInitiated = e.detail === 0; if (!isKeyboardInitiated) { return; } return setOpened((o) => { if (!o) { refresh === null || refresh === void 0 ? void 0 : refresh(); window.addEventListener('pointerup', (evt) => { if (!(0, is_menu_item_1.isMenuItem)(evt.target)) { setOpened(false); } }, { once: true, }); } return !o; }); }; current.addEventListener('mouseenter', onMouseEnter); current.addEventListener('mouseleave', onMouseLeave); current.addEventListener('pointerdown', onPointerDown); current.addEventListener('click', onClick); return () => { current.removeEventListener('mouseenter', onMouseEnter); current.removeEventListener('mouseleave', onMouseLeave); current.removeEventListener('pointerdown', onPointerDown); current.removeEventListener('click', onClick); }; }, [refresh]); const spaceToBottom = (0, react_1.useMemo)(() => { const margin = 10; if (size && opened) { return size.windowSize.height - (size.top + size.height) - margin; } return 0; }, [opened, size]); const spaceToTop = (0, react_1.useMemo)(() => { const margin = 10; if (size && opened) { return size.top - margin; } return 0; }, [opened, size]); const derivedMaxHeight = (0, react_1.useMemo)(() => { return spaceToTop > spaceToBottom ? spaceToTop : spaceToBottom; }, [spaceToBottom, spaceToTop]); const isMobileLayout = (0, mobile_layout_1.useMobileLayout)(); const portalStyle = (0, react_1.useMemo)(() => { if (!opened || !size) { return null; } const spaceToRight = size.windowSize.width - size.left; const spaceToLeft = size.left + size.width; const minSpaceRequired = isMobileLayout ? styles_1.MAX_MOBILE_MENU_WIDTH : styles_1.MAX_MENU_WIDTH; const verticalLayout = spaceToTop > spaceToBottom ? 'bottom' : 'top'; const canOpenOnLeft = spaceToLeft >= minSpaceRequired; const canOpenOnRight = spaceToRight >= minSpaceRequired; const horizontalLayout = canOpenOnRight ? 'left' : 'right'; return { ...(verticalLayout === 'top' ? { ...styles_1.menuContainerTowardsBottom, top: size.top + size.height, } : { ...styles_1.menuContainerTowardsTop, bottom: size.windowSize.height - size.top, }), ...(horizontalLayout === 'left' ? { left: size.left, } : canOpenOnLeft ? { right: size.windowSize.width - size.left - size.width, } : { left: 0 }), }; }, [isMobileLayout, opened, size, spaceToBottom, spaceToTop]); const selected = values.find((v) => v.id === selectedId); const style = (0, react_1.useMemo)(() => { return { ...container, ...(customStyle !== null && customStyle !== void 0 ? customStyle : {}), userSelect: 'none', WebkitUserSelect: 'none', color: 'white', display: 'inline-flex', flexDirection: 'row', alignItems: 'center', borderColor: opened ? colors_1.SELECTED_BACKGROUND : hovered ? colors_1.INPUT_BORDER_COLOR_HOVERED : colors_1.INPUT_BORDER_COLOR_UNHOVERED, }; }, [customStyle, hovered, opened]); return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [ jsx_runtime_1.jsxs("button", { ref: ref, title: title, tabIndex: tabIndex, type: "button", style: style, className: is_menu_item_1.MENU_INITIATOR_CLASSNAME, children: [selected ? (jsx_runtime_1.jsx("div", { title: typeof selected.label === 'string' ? selected.label : undefined, style: label, children: selected === null || selected === void 0 ? void 0 : selected.label })) : null, jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), " ", jsx_runtime_1.jsx(caret_1.CaretDown, {}) ] }), portalStyle ? 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: onHide, onEscape: onHide, children: jsx_runtime_1.jsx("div", { style: portalStyle, children: jsx_runtime_1.jsx(MenuContent_1.MenuContent, { onNextMenu: noop_1.noop, onPreviousMenu: noop_1.noop, values: values, onHide: onHide, leaveLeftSpace: true, preselectIndex: values.findIndex((v) => selected && v.id === selected.id), topItemCanBeUnselected: false, fixedHeight: derivedMaxHeight }) }) }) }) }), (0, portals_1.getPortal)(currentZIndex)) : null] })); }; exports.Combobox = Combobox;