UNPKG

@drivy/cobalt

Version:

Opinionated design system for Drivy's projects.

137 lines (136 loc) 5.01 kB
import { jsx, jsxs } from "react/jsx-runtime"; import { FloatingArrow, FloatingPortal, arrow, autoUpdate, flip as react_flip, offset as react_offset, safePolygon, shift, useClick, useDismiss, useFloating, useHover, useInteractions, useRole, useTransitionStyles } from "@floating-ui/react"; import classnames from "classnames"; import { useEffect, useRef } from "react"; import { zIndexes } from "../../tokens/index.js"; const ANIMATION_TRANSITION_DISTANCE_PX = 4; function useDesktopPopoverCore({ isOpen, onOpenChange, referenceElement, placement = "top", flip = true, tooltip = false, arrow: showArrow = true, theme = "", zIndex = zIndexes.dropdown, appendToBody = true, fixed = false, fitContent = true, withBorder = false, trigger = "click", interactive = false, delay = 0, offset, bodySpacing = false, ariaLabel, onShow, onHidden, getFloatingExtraProps }) { const arrowRef = useRef(null); const [crossAxis, mainAxis] = offset ?? [ 0, showArrow ? 12 : 8 ]; const { refs, floatingStyles, context } = useFloating({ open: isOpen, onOpenChange, placement, strategy: fixed ? "fixed" : "absolute", transform: false, middleware: [ shift({ padding: 8 }), react_offset({ mainAxis, crossAxis }), ...flip ? [ react_flip() ] : [], ...showArrow ? [ arrow({ element: arrowRef }) ] : [] ], whileElementsMounted: autoUpdate, elements: { reference: referenceElement } }); const isHover = "mouseenter" === trigger; const isClick = "click" === trigger; const hover = useHover(context, { enabled: isHover, move: false, delay, handleClose: isHover && interactive ? safePolygon() : void 0 }); 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: "top" === side ? `translateY(${ANIMATION_TRANSITION_DISTANCE_PX}px)` : "bottom" === side ? `translateY(-${ANIMATION_TRANSITION_DISTANCE_PX}px)` : "left" === side ? `translateX(${ANIMATION_TRANSITION_DISTANCE_PX}px)` : `translateX(-${ANIMATION_TRANSITION_DISTANCE_PX}px)` }) }); const prevMountedRef = useRef(false); useEffect(()=>{ if (isMounted && !prevMountedRef.current) onShow?.(); if (!isMounted && prevMountedRef.current) onHidden?.(); prevMountedRef.current = isMounted; }, [ isMounted, onShow, onHidden ]); const renderFloating = (content)=>{ if (!isMounted) return null; const body = bodySpacing ? /*#__PURE__*/ jsx("div", { className: "cobalt-popover--bodySpacing", children: content }) : content; const extraFloatingProps = getFloatingExtraProps?.() ?? {}; const { onMouseEnter, onMouseLeave, ...restExtraFloatingProps } = extraFloatingProps; const node = /*#__PURE__*/ jsxs("div", { ref: refs.setFloating, style: { ...floatingStyles, ...transitionStyles, zIndex }, className: classnames("cobalt-popover", { "cobalt-popover--withArrow": showArrow, "cobalt-popover--fitContent": fitContent, "cobalt-popover--withBorder": withBorder }), "data-placement": context.placement, "data-theme": classnames(theme, { tooltip: tooltip }), ...getFloatingProps({ "aria-label": ariaLabel, ...restExtraFloatingProps, onMouseEnter, onMouseLeave }), children: [ showArrow && /*#__PURE__*/ jsx(FloatingArrow, { ref: arrowRef, context: context, className: "cobalt-popover__arrow" }), body ] }); return appendToBody ? /*#__PURE__*/ jsx(FloatingPortal, { children: node }) : node; }; return { refs: { setReference: refs.setReference, setFloating: refs.setFloating }, getReferenceProps, renderFloating, isMounted }; } export { useDesktopPopoverCore }; //# sourceMappingURL=useDesktopPopoverCore.js.map