UNPKG

@yamada-ui/react

Version:

React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion

1 lines • 14 kB
{"version":3,"file":"use-popover.cjs","names":["useEnvironment","useDisclosure","usePopper","getEventRelatedTarget","getTriggerProps: PropGetter<\"button\">","mergeRefs","getAnchorProps: PropGetter","getPositionerProps: PropGetter","getContentProps: PropGetter","getHeaderProps: PropGetter","popoverProps: (\n | keyof PopupAnimationProps\n | keyof UsePopoverProps\n)[]","popperProps","useSplitProps"],"sources":["../../../../src/components/popover/use-popover.tsx"],"sourcesContent":["\"use client\"\n\nimport type { FocusEvent, KeyboardEvent, RefObject } from \"react\"\nimport type { Direction, PropGetter } from \"../../core\"\nimport type { UseDisclosureProps } from \"../../hooks/use-disclosure\"\nimport type { UsePopperProps } from \"../../hooks/use-popper\"\nimport type { Dict } from \"../../utils\"\nimport type { PopupAnimationProps } from \"./popover\"\nimport { useCallback, useEffect, useId, useRef } from \"react\"\nimport { useEnvironment, useSplitProps } from \"../../core\"\nimport { useDisclosure } from \"../../hooks/use-disclosure\"\nimport { useEventListener } from \"../../hooks/use-event-listener\"\nimport { useFocusOnShow } from \"../../hooks/use-focus\"\nimport { useOutsideClick } from \"../../hooks/use-outside-click\"\nimport { popperProps, usePopper } from \"../../hooks/use-popper\"\nimport {\n ariaAttr,\n assignRef,\n contains,\n dataAttr,\n focusTransfer,\n focusTrap,\n getEventRelatedTarget,\n handlerAll,\n mergeRefs,\n runKeyAction,\n scrollLock,\n setAttribute,\n useSafeLayoutEffect,\n useUnmountEffect,\n} from \"../../utils\"\n\nexport interface UsePopoverProps\n extends Omit<UseDisclosureProps, \"timing\">,\n UsePopperProps<\"button\"> {\n /**\n * If `true`, focus will be transferred to the first interactive element when the popover opens.\n *\n * @default true\n */\n autoFocus?: boolean\n /**\n * If `true`, scrolling will be disabled on the `body` when the modal opens.\n *\n * @default false\n */\n blockScrollOnMount?: boolean\n /**\n * If `true`, the popover will close when you blur out it by clicking outside or tabbing out.\n *\n * @default true\n */\n closeOnBlur?: boolean\n /**\n * If `true`, the popover will hide on pressing Esc key.\n *\n * @default true\n */\n closeOnEsc?: boolean\n /**\n * If `true`, the popover will hide on scroll.\n *\n * @default false\n */\n closeOnScroll?: boolean\n /**\n * If `true`, the popover will be disabled.\n *\n * @default false\n */\n disabled?: boolean\n /**\n * The `ref` of the element that should receive focus when the popover opens.\n */\n initialFocusRef?: RefObject<HTMLElement | null>\n /**\n * If `true`, the popover will be modal.\n *\n * - scrolling is blocked.\n * - focus is trapped within the popover.\n *\n * @default false\n */\n modal?: boolean\n /**\n * If `true`, the popover will be opened when click on the field.\n *\n * @default true\n */\n openOnClick?: boolean\n /**\n * The placement of the popper relative to its reference.\n *\n * @default 'end'\n */\n placement?: Direction\n /**\n * If `true`, the focus will be transferred to the popover content when the tab key is pressed.\n *\n * @default true\n */\n transferFocus?: boolean\n /**\n * Update the position of the floating element, re-rendering the component if required.\n */\n updateRef?: RefObject<() => void>\n}\n\nexport const usePopover = ({\n autoFocus = true,\n autoUpdate,\n modal = false,\n blockScrollOnMount = modal,\n closeOnBlur = true,\n closeOnEsc = true,\n closeOnScroll,\n defaultOpen,\n disabled,\n elements,\n flip,\n gutter,\n initialFocusRef,\n matchWidth,\n middleware,\n offset,\n open: openProp,\n openOnClick = true,\n placement = \"end\",\n platform,\n preventOverflow,\n strategy,\n transferFocus = true,\n transform,\n updateRef,\n whileElementsMounted,\n onClose: onCloseProp,\n onOpen: onOpenProp,\n}: UsePopoverProps = {}) => {\n const { getDocument } = useEnvironment()\n const headerId = useId()\n const bodyId = useId()\n const contentId = useId()\n const anchorRef = useRef<HTMLElement>(null)\n const triggerRef = useRef<HTMLButtonElement>(null)\n const contentRef = useRef<HTMLElement>(null)\n const openTimeout = useRef<NodeJS.Timeout>(undefined)\n const closeTimeout = useRef<NodeJS.Timeout>(undefined)\n const { open, onClose, onOpen } = useDisclosure({\n defaultOpen,\n open: openProp,\n onClose: onCloseProp,\n onOpen: onOpenProp,\n })\n const { refs, update, getPopperProps } = usePopper<\"button\">({\n autoUpdate,\n elements,\n flip,\n gutter,\n matchWidth,\n middleware,\n offset,\n open,\n placement,\n platform,\n preventOverflow,\n strategy,\n transform,\n whileElementsMounted,\n })\n\n assignRef(updateRef, update)\n\n const onKeyDown = useCallback(\n (ev: KeyboardEvent<HTMLElement>) => {\n runKeyAction(ev, {\n Escape: () => {\n if (!closeOnEsc) return\n\n onClose()\n\n triggerRef.current?.focus()\n },\n })\n },\n [closeOnEsc, onClose],\n )\n\n const onBlur = useCallback(\n (ev: FocusEvent<HTMLDivElement>) => {\n const relatedTarget = getEventRelatedTarget(ev)\n const popup = relatedTarget?.hasAttribute(\"data-popup\")\n\n if (contains(triggerRef.current, relatedTarget)) return\n if (contains(contentRef.current, relatedTarget)) return\n if (contains(contentRef.current, ev.target) && popup) return\n\n if (closeOnBlur) onClose()\n },\n [closeOnBlur, onClose],\n )\n\n useEventListener(getDocument(), \"scroll\", () => {\n if (open && closeOnScroll) onClose()\n })\n\n useFocusOnShow(contentRef, {\n focusTarget: initialFocusRef,\n shouldFocus: autoFocus,\n visible: open,\n })\n\n useOutsideClick({\n ref: [contentRef, triggerRef],\n enabled: open && closeOnBlur,\n handler: onClose,\n })\n\n useSafeLayoutEffect(() => {\n const el = contentRef.current\n const hasHeader = !!getDocument()?.getElementById(headerId)\n const hasBody = !!getDocument()?.getElementById(bodyId)\n\n if (el && hasHeader) setAttribute(el, \"aria-labelledby\", headerId)\n if (el && hasBody) setAttribute(el, \"aria-describedby\", bodyId)\n }, [open, headerId, bodyId])\n\n useEffect(() => {\n if (!open || !modal) return\n\n return focusTrap(contentRef.current)\n }, [open, modal])\n\n useEffect(() => {\n if (!open || !blockScrollOnMount) return\n\n return scrollLock(contentRef.current)\n }, [open, modal, blockScrollOnMount])\n\n useEffect(() => {\n if (!open || modal || !transferFocus) return\n\n return focusTransfer(contentRef.current, triggerRef.current)\n }, [open, modal, transferFocus])\n\n useUnmountEffect(() => {\n clearTimeout(openTimeout.current)\n clearTimeout(closeTimeout.current)\n })\n\n const getTriggerProps: PropGetter<\"button\"> = useCallback(\n ({ ref, ...props } = {}) => ({\n \"aria-controls\": open ? contentId : undefined,\n \"aria-disabled\": ariaAttr(disabled),\n \"aria-expanded\": open,\n \"aria-haspopup\": \"dialog\",\n role: \"button\",\n ...props,\n ref: mergeRefs(ref, triggerRef, (node) => {\n if (anchorRef.current == null) refs.setReference(node)\n }),\n onBlur: handlerAll(props.onBlur, (ev) =>\n !contains(contentRef.current, getEventRelatedTarget(ev)) && closeOnBlur\n ? onClose()\n : void 0,\n ),\n onClick: handlerAll(\n props.onClick,\n !open ? (!disabled && openOnClick ? onOpen : undefined) : onClose,\n ),\n onKeyDown: handlerAll(props.onKeyDown, onKeyDown),\n }),\n [\n closeOnBlur,\n contentId,\n disabled,\n onClose,\n onKeyDown,\n onOpen,\n open,\n openOnClick,\n refs,\n ],\n )\n\n const getAnchorProps: PropGetter = useCallback(\n ({ ref, ...props } = {}) => ({\n ...props,\n ref: mergeRefs(ref, anchorRef, refs.setReference),\n }),\n [refs.setReference],\n )\n\n const getPositionerProps: PropGetter = useCallback(\n (props) => {\n return getPopperProps(props)\n },\n [getPopperProps],\n )\n\n const getContentProps: PropGetter = useCallback(\n ({ ref, ...props } = {}) => ({\n id: contentId,\n \"aria-hidden\": !open,\n \"aria-modal\": modal ? \"true\" : undefined,\n \"data-close\": dataAttr(!open),\n \"data-open\": dataAttr(open),\n \"data-popup\": dataAttr(true),\n role: \"dialog\",\n tabIndex: -1,\n ...props,\n ref: mergeRefs(ref, contentRef),\n onBlur: handlerAll(props.onBlur, onBlur),\n onKeyDown: handlerAll(props.onKeyDown, onKeyDown),\n }),\n [contentId, open, modal, onBlur, onKeyDown],\n )\n\n const getHeaderProps: PropGetter = useCallback(\n (props) => ({\n id: headerId,\n ...props,\n }),\n [headerId],\n )\n\n const getBodyProps: PropGetter = useCallback(\n (props) => ({\n id: bodyId,\n ...props,\n }),\n [bodyId],\n )\n\n const getFooterProps: PropGetter = useCallback((props) => ({ ...props }), [])\n\n return {\n open,\n getAnchorProps,\n getBodyProps,\n getContentProps,\n getFooterProps,\n getHeaderProps,\n getPositionerProps,\n getTriggerProps,\n onClose,\n onOpen,\n }\n}\n\nexport type UsePopoverReturn = ReturnType<typeof usePopover>\n\nexport const popoverProps: (\n | keyof PopupAnimationProps\n | keyof UsePopoverProps\n)[] = [\n ...popperProps,\n \"autoFocus\",\n \"transferFocus\",\n \"blockScrollOnMount\",\n \"closeOnBlur\",\n \"closeOnEsc\",\n \"closeOnScroll\",\n \"openOnClick\",\n \"disabled\",\n \"initialFocusRef\",\n \"modal\",\n \"updateRef\",\n \"defaultOpen\",\n \"onOpen\",\n \"onClose\",\n \"animationScheme\",\n \"duration\",\n]\n\nexport const usePopoverProps = <\n Y extends Dict = Dict,\n M extends keyof PopupAnimationProps | keyof UsePopoverProps =\n | keyof PopupAnimationProps\n | keyof UsePopoverProps,\n>(\n props: Y,\n omitKeys?: M[],\n) => {\n return useSplitProps(\n props,\n popoverProps.filter((key) => !omitKeys?.includes(key as M)),\n ) as unknown as [\n keyof PopupAnimationProps | keyof UsePopoverProps extends M\n ? PopupAnimationProps & UsePopoverProps\n : Omit<PopupAnimationProps & UsePopoverProps, M>,\n Omit<\n Y,\n keyof PopupAnimationProps | keyof UsePopoverProps extends M\n ? keyof PopupAnimationProps | keyof UsePopoverProps\n : Exclude<keyof PopupAnimationProps | keyof UsePopoverProps, M>\n >,\n ]\n}\n"],"mappings":"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"}