@drivy/cobalt
Version:
Opinionated design system for Drivy's projects.
103 lines (100 loc) • 4.75 kB
JavaScript
import { jsx, jsxs } from 'react/jsx-runtime';
import { useFloating, shift, offset, flip, arrow, autoUpdate, useHover, safePolygon, useClick, useDismiss, useRole, useInteractions, useTransitionStyles, FloatingArrow, FloatingPortal } from '@floating-ui/react';
import cx from 'classnames';
import { useRef, useEffect } from 'react';
import { zIndexes } from '../../tokens/index.js';
const ANIMATION_TRANSITION_DISTANCE_PX = 4;
function useDesktopPopoverCore({ isOpen, onOpenChange, referenceElement, placement = "top", flip: flip$1 = true, tooltip = false, arrow: showArrow = true, theme = "", zIndex = zIndexes.dropdown, appendToBody = true, fitContent = true, withBorder = false, trigger = "click", interactive = false, delay = 0, offset: offset$1, bodySpacing = false, ariaLabel, onShow, onHidden, getFloatingExtraProps, }) {
const arrowRef = useRef(null);
const [crossAxis, mainAxis] = offset$1 !== null && offset$1 !== void 0 ? offset$1 : [0, showArrow ? 12 : 8];
const { refs, floatingStyles, context } = useFloating({
open: isOpen,
onOpenChange,
placement,
transform: false,
middleware: [
shift({ padding: 8 }),
offset({ mainAxis, crossAxis }),
...(flip$1 ? [flip()] : []),
...(showArrow ? [arrow({ element: arrowRef })] : []),
],
whileElementsMounted: autoUpdate,
elements: { reference: referenceElement },
});
const isHover = trigger === "mouseenter";
const isClick = trigger === "click";
const hover = useHover(context, {
enabled: isHover,
move: false,
delay,
handleClose: isHover && interactive ? safePolygon() : undefined,
});
const click = useClick(context, {
enabled: isClick,
});
const dismiss = useDismiss(context);
const role = useRole(context, { role: "dialog" });
const { getReferenceProps, getFloatingProps } = useInteractions([
hover,
click,
dismiss,
role,
]);
const { isMounted, styles: transitionStyles } = useTransitionStyles(context, {
duration: { open: 200, close: 150 },
initial: ({ side }) => ({
opacity: 0,
transform: side === "top"
? `translateY(${ANIMATION_TRANSITION_DISTANCE_PX}px)`
: side === "bottom"
? `translateY(-${ANIMATION_TRANSITION_DISTANCE_PX}px)`
: side === "left"
? `translateX(${ANIMATION_TRANSITION_DISTANCE_PX}px)`
: `translateX(-${ANIMATION_TRANSITION_DISTANCE_PX}px)`,
}),
});
const prevMountedRef = useRef(false);
useEffect(() => {
if (isMounted && !prevMountedRef.current)
onShow === null || onShow === void 0 ? void 0 : onShow();
if (!isMounted && prevMountedRef.current)
onHidden === null || onHidden === void 0 ? void 0 : onHidden();
prevMountedRef.current = isMounted;
}, [isMounted, onShow, onHidden]);
const renderFloating = (content) => {
var _a;
if (!isMounted)
return null;
const body = bodySpacing ? (jsx("div", { className: "cobalt-popover--bodySpacing", children: content })) : (content);
const extraFloatingProps = (_a = getFloatingExtraProps === null || getFloatingExtraProps === void 0 ? void 0 : getFloatingExtraProps()) !== null && _a !== void 0 ? _a : {};
const { onMouseEnter, onMouseLeave, ...restExtraFloatingProps } = extraFloatingProps;
const node = (jsxs("div", { ref: refs.setFloating, style: {
...floatingStyles,
...transitionStyles,
zIndex,
}, className: cx("cobalt-popover", {
"cobalt-popover--withArrow": showArrow,
"cobalt-popover--fitContent": fitContent,
"cobalt-popover--withBorder": withBorder,
}), "data-placement": context.placement, "data-theme": cx(theme, {
tooltip: tooltip,
}), ...getFloatingProps({
"aria-label": ariaLabel,
...restExtraFloatingProps,
onMouseEnter,
onMouseLeave,
}), children: [showArrow && (jsx(FloatingArrow, { ref: arrowRef, context: context, className: "cobalt-popover__arrow" })), body] }));
return appendToBody ? jsx(FloatingPortal, { children: node }) : node;
};
return {
refs: {
setReference: refs.setReference,
setFloating: refs.setFloating,
},
getReferenceProps,
renderFloating,
isMounted,
};
}
export { useDesktopPopoverCore };
//# sourceMappingURL=useDesktopPopoverCore.js.map