@remotion/studio
Version:
APIs for interacting with the Remotion Studio
105 lines (104 loc) • 4.39 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useZIndex = exports.HigherZIndex = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const use_keybinding_1 = require("../helpers/use-keybinding");
const highest_z_index_1 = require("./highest-z-index");
const input_dragger_click_lock_1 = require("./input-dragger-click-lock");
const ZIndexContext = (0, react_1.createContext)({
currentIndex: 0,
});
const margin = {
margin: 'auto',
};
const EscapeHook = ({ onEscape }) => {
const keybindings = (0, use_keybinding_1.useKeybinding)();
(0, react_1.useEffect)(() => {
const escape = keybindings.registerKeybinding({
event: 'keydown',
key: 'Escape',
callback: onEscape,
commandCtrlKey: false,
preventDefault: true,
// To dismiss the Quick Switcher menu if input is focused
triggerIfInputFieldFocused: true,
keepRegisteredWhenNotHighestContext: false,
});
return () => {
escape.unregister();
};
}, [keybindings, onEscape]);
return null;
};
const HigherZIndex = ({ children, onEscape, onOutsideClick, disabled }) => {
const context = (0, react_1.useContext)(ZIndexContext);
const highestContext = (0, react_1.useContext)(highest_z_index_1.HighestZIndexContext);
const containerRef = (0, react_1.useRef)(null);
const currentIndex = disabled
? context.currentIndex
: context.currentIndex + 1;
(0, react_1.useEffect)(() => {
if (disabled) {
return;
}
highestContext.registerZIndex(currentIndex);
return () => highestContext.unregisterZIndex(currentIndex);
}, [currentIndex, highestContext, disabled]);
(0, react_1.useEffect)(() => {
if (disabled) {
return;
}
let onUp = null;
const listener = (downEvent) => {
var _a;
const outsideClick = !((_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.contains(downEvent.target));
if (!outsideClick) {
return;
}
onUp = (upEvent) => {
if (highestContext.highestIndex === currentIndex &&
!(0, input_dragger_click_lock_1.getClickLock)() &&
// Don't trigger if that click removed that node
document.contains(upEvent.target)) {
upEvent.stopPropagation();
onOutsideClick(upEvent.target);
}
};
window.addEventListener('pointerup', onUp, { once: true });
};
// If a menu is opened, then this component will also still receive the pointerdown event.
// However we may not interpret it as a outside click, so we need to wait for the next tick
requestAnimationFrame(() => {
window.addEventListener('pointerdown', listener);
});
return () => {
if (onUp) {
// @ts-expect-error
window.removeEventListener('pointerup', onUp, { once: true });
}
onUp = null;
return window.removeEventListener('pointerdown', listener);
};
}, [currentIndex, disabled, highestContext.highestIndex, onOutsideClick]);
const value = (0, react_1.useMemo)(() => {
return {
currentIndex,
};
}, [currentIndex]);
return (jsx_runtime_1.jsxs(ZIndexContext.Provider, { value: value, children: [disabled ? null : jsx_runtime_1.jsx(EscapeHook, { onEscape: onEscape }), jsx_runtime_1.jsx("div", { ref: containerRef, style: margin, children: children })
] }));
};
exports.HigherZIndex = HigherZIndex;
const useZIndex = () => {
const context = (0, react_1.useContext)(ZIndexContext);
const highestContext = (0, react_1.useContext)(highest_z_index_1.HighestZIndexContext);
const isHighestContext = highestContext.highestIndex === context.currentIndex;
return (0, react_1.useMemo)(() => ({
currentZIndex: context.currentIndex,
highestZIndex: highestContext.highestIndex,
isHighestContext,
tabIndex: isHighestContext ? 0 : -1,
}), [context.currentIndex, highestContext.highestIndex, isHighestContext]);
};
exports.useZIndex = useZIndex;