UNPKG

@wix/design-system

Version:

@wix/design-system

144 lines 5.79 kB
import { useEffect, useMemo } from 'react'; import { useFloating, autoUpdate, flip, shift, useClick, useDismiss, useRole, useInteractions, size, offset, autoPlacement, } from '@floating-ui/react'; import { APPEND_TO } from '../PopoverNext.constants'; import { ZIndex } from '../../common/ZIndex'; import { usePositioning } from './usePositioning'; import deprecationLog from '../../utils/deprecationLog'; import { useTransition } from './useTransition'; const formatWidth = (value) => typeof value === 'number' ? `${value}px` : value; export function usePopover({ dataHook, open = false, onOpenChange, focusManagerEnabled = true, appendTo = APPEND_TO.parent, dynamicWidth = false, zIndex = ZIndex.popover, width, minWidth, maxWidth, excludeClass, moveBy, flip: shouldFlip = true, placement = 'bottom', fixed = false, rootRef, showDelay = 0, hideDelay = 0, timeout: duration = 0, skin, transitionSettings, onClickOutside, overlay = false, }) { useEffect(() => { if (showDelay) { deprecationLog('<PopoverNext /> - prop `showDelay` is deprecated. Use transitionSettings instead.'); } if (hideDelay) { deprecationLog('<PopoverNext /> - prop `hideDelay` is deprecated. Use transitionSettings instead.'); } if (duration) { deprecationLog('<PopoverNext /> - prop `timeout` is deprecated. Use transitionSettings instead.'); } }, [showDelay, hideDelay, duration]); const positioning = usePositioning({ flip: shouldFlip, fixed, placement, appendTo, rootRef, }); const data = useFloating({ open, onOpenChange: (newOpen, _, reason) => onOpenChange(newOpen, reason), whileElementsMounted: (referenceEl, floatingEl, update) => autoUpdate(referenceEl, floatingEl, update, { animationFrame: true, }), placement: positioning.placement, middleware: [ size({ apply({ rects, elements }) { const styles = { overflow: 'hidden', wordBreak: 'normal', }; if (width) { styles.width = formatWidth(width); if (minWidth) { styles.minWidth = formatWidth(minWidth); } if (maxWidth) { styles.maxWidth = formatWidth(maxWidth); } } else if (dynamicWidth) { styles.minWidth = `${rects.reference.width}px`; if (maxWidth) { styles.maxWidth = formatWidth(maxWidth); } } else { if (minWidth) { styles.minWidth = formatWidth(minWidth); } if (maxWidth) { styles.maxWidth = formatWidth(maxWidth); } } if (appendTo === 'window') { styles.minWidth = !!minWidth ? formatWidth(minWidth) : 'fit-content'; styles.width = !!width ? formatWidth(width) : formatWidth(rects.reference.width); if (maxWidth) { styles.maxWidth = formatWidth(maxWidth); } } Object.assign(elements.floating.style, styles); }, }), !!positioning.flip ? flip(positioning.flip) : undefined, !!positioning.autoPlacement ? autoPlacement(positioning.autoPlacement) : undefined, shift(positioning.shift), offset({ mainAxis: moveBy?.y, crossAxis: moveBy?.x }), ].filter(Boolean), }); const context = data.context; const click = useClick(context); const dismiss = useDismiss(context, { outsidePress: event => { const classes = event.target.classList; if (excludeClass && classes.contains(excludeClass)) { return false; } onClickOutside?.(event); return true; }, escapeKey: true, }); const role = useRole(context); const interactions = useInteractions([click, dismiss, role]); const convertToTransitionSettings = (duration) => { if (!duration || typeof duration === 'number') { return duration; } return { open: duration.enter, close: duration.exit }; }; const { isMounted, styles: transitionStyles } = useTransition({ ...transitionSettings, duration: transitionSettings?.duration ?? convertToTransitionSettings(duration), closeDelay: transitionSettings?.closeDelay ?? hideDelay, openDelay: transitionSettings?.openDelay ?? showDelay, context, }); return useMemo(() => ({ dataHook, focusManagerEnabled, interactions, context, appendTo, zIndex, open: isMounted, popoverStyles: { ...context.floatingStyles, }, transitionStyles, portalRoot: positioning.portalRoot, skin, overlay, }), [ dataHook, focusManagerEnabled, interactions, context, isMounted, zIndex, appendTo, positioning, transitionStyles, skin, overlay, ]); } //# sourceMappingURL=usePopover.js.map