@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
1 lines • 16.7 kB
Source Map (JSON)
{"version":3,"file":"Popover.cjs","names":["getDefaultZIndex","createVarsResolver","getRadius","getShadow","useProps","useStyles","useResolvedStylesApi","useDirection","useMantineEnv","usePopover","getFloatingPosition","PopoverContextProvider","Transition","OptionalPortal","Overlay","PopoverTarget","PopoverDropdown"],"sources":["../../../src/components/Popover/Popover.tsx"],"sourcesContent":["import { useCallback, useRef, useState } from 'react';\nimport { useClickOutside, useId } from '@mantine/hooks';\nimport {\n createVarsResolver,\n ElementProps,\n ExtendComponent,\n Factory,\n getDefaultZIndex,\n getRadius,\n getShadow,\n MantineRadius,\n MantineShadow,\n StylesApiProps,\n useDirection,\n useMantineEnv,\n useProps,\n useResolvedStylesApi,\n useStyles,\n} from '../../core';\nimport {\n ArrowPosition,\n FloatingAxesOffsets,\n FloatingPosition,\n FloatingStrategy,\n getFloatingPosition,\n} from '../../utils/Floating';\nimport { Overlay, OverlayProps } from '../Overlay';\nimport { BasePortalProps, OptionalPortal } from '../Portal';\nimport { Transition, TransitionOverride } from '../Transition';\nimport { PopoverContextProvider, PopoverContextValue } from './Popover.context';\nimport { PopoverMiddlewares, PopoverWidth } from './Popover.types';\nimport { PopoverDropdown, PopoverDropdownProps } from './PopoverDropdown/PopoverDropdown';\nimport { PopoverTarget, PopoverTargetProps } from './PopoverTarget/PopoverTarget';\nimport { usePopover } from './use-popover';\nimport classes from './Popover.module.css';\n\nexport type PopoverStylesNames = 'dropdown' | 'arrow' | 'overlay';\nexport type PopoverCssVariables = {\n dropdown: '--popover-radius' | '--popover-shadow';\n};\n\nexport interface __PopoverProps {\n /** Dropdown position relative to the target element @default 'bottom' */\n position?: FloatingPosition;\n\n /** Offset of the dropdown element @default 8 */\n offset?: number | FloatingAxesOffsets;\n\n /** Called when dropdown position changes */\n onPositionChange?: (position: FloatingPosition) => void;\n\n /** Called when dropdown closes */\n onClose?: () => void;\n\n /** Called when the popover is dismissed by clicking outside or by pressing escape */\n onDismiss?: () => void;\n\n /** Called when dropdown opens */\n onOpen?: () => void;\n\n /** If set, the dropdown is not unmounted from the DOM when hidden. `display: none` styles are added instead. */\n keepMounted?: boolean;\n\n /** Props passed down to the `Transition` component. Use to configure duration and animation type. @default { duration: 150, transition: 'fade' } */\n transitionProps?: TransitionOverride;\n\n /** Called when exit transition ends */\n onExitTransitionEnd?: () => void;\n\n /** Called when enter transition ends */\n onEnterTransitionEnd?: () => void;\n\n /** Dropdown width, or `'target'` to make dropdown width the same as target element @default 'max-content' */\n width?: PopoverWidth;\n\n /** Floating ui middlewares to configure position handling @default { flip: true, shift: true, inline: false } */\n middlewares?: PopoverMiddlewares;\n\n /** Determines whether component should have an arrow @default false */\n withArrow?: boolean;\n\n /** Determines whether the overlay should be displayed when the dropdown is opened @default false */\n withOverlay?: boolean;\n\n /** Props passed down to `Overlay` component */\n overlayProps?: OverlayProps & ElementProps<'div'>;\n\n /** Arrow size in px @default 7 */\n arrowSize?: number;\n\n /** Arrow offset in px @default 5 */\n arrowOffset?: number;\n\n /** Arrow `border-radius` in px @default 0 */\n arrowRadius?: number;\n\n /** Arrow position */\n arrowPosition?: ArrowPosition;\n\n /** Determines whether dropdown should be rendered within the `Portal` @default true */\n withinPortal?: boolean;\n\n /** Props to pass down to the `Portal` when `withinPortal` is true */\n portalProps?: BasePortalProps;\n\n /** Dropdown `z-index` @default 300 */\n zIndex?: string | number;\n\n /** Key of `theme.radius` or any valid CSS value to set border-radius @default theme.defaultRadius */\n radius?: MantineRadius;\n\n /** Key of `theme.shadows` or any other valid CSS `box-shadow` value */\n shadow?: MantineShadow;\n\n /** If set, popover dropdown will not be rendered */\n disabled?: boolean;\n\n /** Determines whether focus should be automatically returned to control when dropdown closes @default false */\n returnFocus?: boolean;\n\n /** Changes floating ui [position strategy](https://floating-ui.com/docs/usefloating#strategy) @default 'absolute' */\n floatingStrategy?: FloatingStrategy;\n\n /** If set, the dropdown is hidden when the element is hidden with styles or not visible on the screen @default true */\n hideDetached?: boolean;\n\n /** Prevents popover from flipping/shifting when it the dropdown is visible */\n preventPositionChangeWhenVisible?: boolean;\n}\n\nexport interface PopoverProps extends __PopoverProps, StylesApiProps<PopoverFactory> {\n __staticSelector?: string;\n\n /** `Popover.Target` and `Popover.Dropdown` components */\n children?: React.ReactNode;\n\n /** Initial opened state for uncontrolled component */\n defaultOpened?: boolean;\n\n /** Controlled dropdown opened state */\n opened?: boolean;\n\n /** Called with current state when dropdown opens or closes */\n onChange?: (opened: boolean) => void;\n\n /** Determines whether dropdown should be closed on outside clicks @default true */\n closeOnClickOutside?: boolean;\n\n /** Events that trigger outside clicks */\n clickOutsideEvents?: string[];\n\n /** Determines whether focus should be trapped within dropdown @default false */\n trapFocus?: boolean;\n\n /** Determines whether dropdown should be closed when `Escape` key is pressed @default true */\n closeOnEscape?: boolean;\n\n /** Id base to create accessibility connections */\n id?: string;\n\n /** Determines whether dropdown and target elements should have accessible roles @default true */\n withRoles?: boolean;\n}\n\nexport type PopoverFactory = Factory<{\n props: PopoverProps;\n stylesNames: PopoverStylesNames;\n vars: PopoverCssVariables;\n}>;\n\nconst defaultProps = {\n position: 'bottom',\n offset: 8,\n transitionProps: { transition: 'fade', duration: 150 },\n middlewares: { flip: true, shift: true, inline: false },\n arrowSize: 7,\n arrowOffset: 5,\n arrowRadius: 0,\n arrowPosition: 'side',\n closeOnClickOutside: true,\n withinPortal: true,\n closeOnEscape: true,\n trapFocus: false,\n withRoles: true,\n returnFocus: false,\n withOverlay: false,\n hideDetached: true,\n clickOutsideEvents: ['mousedown', 'touchstart'],\n zIndex: getDefaultZIndex('popover'),\n __staticSelector: 'Popover',\n width: 'max-content',\n} satisfies Partial<PopoverProps>;\n\nconst varsResolver = createVarsResolver<PopoverFactory>((_, { radius, shadow }) => ({\n dropdown: {\n '--popover-radius': radius === undefined ? undefined : getRadius(radius),\n '--popover-shadow': getShadow(shadow),\n },\n}));\n\nexport function Popover(_props: PopoverProps) {\n const props = useProps('Popover', defaultProps, _props);\n const {\n children,\n position,\n offset,\n onPositionChange,\n opened,\n transitionProps,\n onExitTransitionEnd,\n onEnterTransitionEnd,\n width,\n middlewares,\n withArrow,\n arrowSize,\n arrowOffset,\n arrowRadius,\n arrowPosition,\n unstyled,\n classNames,\n styles,\n closeOnClickOutside,\n withinPortal,\n portalProps,\n closeOnEscape,\n clickOutsideEvents,\n trapFocus,\n onClose,\n onDismiss,\n onOpen,\n onChange,\n zIndex,\n radius,\n shadow,\n id,\n defaultOpened,\n __staticSelector,\n withRoles,\n disabled,\n returnFocus,\n variant,\n keepMounted,\n vars,\n floatingStrategy,\n withOverlay,\n overlayProps,\n hideDetached,\n attributes,\n preventPositionChangeWhenVisible,\n ...others\n } = props;\n\n const getStyles = useStyles<PopoverFactory>({\n name: __staticSelector,\n props,\n classes,\n classNames,\n styles,\n unstyled,\n attributes,\n rootSelector: 'dropdown',\n vars,\n varsResolver,\n });\n\n const { resolvedStyles } = useResolvedStylesApi<PopoverFactory>({ classNames, styles, props });\n\n const [dropdownVisible, setDropdownVisible] = useState(opened ?? defaultOpened ?? false);\n const positionRef = useRef<FloatingPosition>(position);\n const arrowRef = useRef<HTMLDivElement | null>(null);\n const [targetNode, setTargetNode] = useState<HTMLElement | null>(null);\n const [dropdownNode, setDropdownNode] = useState<HTMLElement | null>(null);\n const { dir } = useDirection();\n const env = useMantineEnv();\n\n const uid = useId(id);\n const popover = usePopover({\n middlewares,\n width,\n position: getFloatingPosition(dir, position),\n offset: typeof offset === 'number' ? offset + (withArrow ? arrowSize / 2 : 0) : offset,\n arrowRef,\n arrowOffset,\n onPositionChange,\n opened,\n defaultOpened,\n onChange,\n onOpen,\n onClose,\n onDismiss,\n strategy: floatingStrategy,\n dropdownVisible,\n setDropdownVisible,\n positionRef,\n disabled,\n preventPositionChangeWhenVisible,\n keepMounted,\n });\n\n useClickOutside(\n () => {\n if (closeOnClickOutside) {\n popover.onClose();\n onDismiss?.();\n }\n },\n clickOutsideEvents,\n [targetNode, dropdownNode]\n );\n\n const reference = useCallback(\n (node: HTMLElement) => {\n setTargetNode(node);\n popover.floating.refs.setReference(node);\n },\n [popover.floating.refs.setReference]\n );\n\n const floating = useCallback(\n (node: HTMLElement) => {\n setDropdownNode(node);\n popover.floating.refs.setFloating(node);\n },\n [popover.floating.refs.setFloating]\n );\n\n const onExited = useCallback(() => {\n transitionProps?.onExited?.();\n onExitTransitionEnd?.();\n setDropdownVisible(false);\n // Only reset position if preventPositionChangeWhenVisible is false\n // to maintain the flipped position on subsequent opens\n if (!preventPositionChangeWhenVisible) {\n positionRef.current = position;\n }\n }, [transitionProps?.onExited, onExitTransitionEnd, preventPositionChangeWhenVisible, position]);\n\n const onEntered = useCallback(() => {\n transitionProps?.onEntered?.();\n onEnterTransitionEnd?.();\n }, [transitionProps?.onEntered, onEnterTransitionEnd]);\n\n return (\n <PopoverContextProvider\n value={{\n returnFocus,\n disabled,\n controlled: popover.controlled,\n reference,\n floating,\n x: popover.floating.x,\n y: popover.floating.y,\n arrowX: popover.floating?.middlewareData?.arrow?.x,\n arrowY: popover.floating?.middlewareData?.arrow?.y,\n opened: popover.opened,\n arrowRef,\n transitionProps: { ...transitionProps, onExited, onEntered },\n width,\n withArrow,\n arrowSize,\n arrowOffset,\n arrowRadius,\n arrowPosition,\n placement: popover.floating.placement,\n trapFocus,\n withinPortal,\n portalProps,\n zIndex,\n radius,\n shadow,\n closeOnEscape,\n onDismiss,\n onClose: popover.onClose,\n onToggle: popover.onToggle,\n getTargetId: () => uid,\n getDropdownId: () => `${uid}-dropdown`,\n withRoles,\n targetProps: others,\n __staticSelector,\n classNames,\n styles,\n unstyled,\n variant,\n keepMounted,\n getStyles,\n resolvedStyles,\n floatingStrategy,\n referenceHidden:\n hideDetached && env !== 'test'\n ? popover.floating.middlewareData.hide?.referenceHidden\n : false,\n }}\n >\n {children}\n {withOverlay && (\n <Transition\n transition=\"fade\"\n mounted={popover.opened}\n duration={transitionProps?.duration || 250}\n exitDuration={transitionProps?.exitDuration || 250}\n >\n {(transitionStyles) => (\n <OptionalPortal withinPortal={withinPortal}>\n <Overlay\n {...overlayProps}\n {...getStyles('overlay', {\n className: overlayProps?.className,\n style: [transitionStyles, overlayProps?.style],\n })}\n />\n </OptionalPortal>\n )}\n </Transition>\n )}\n </PopoverContextProvider>\n );\n}\n\nPopover.Target = PopoverTarget;\nPopover.Dropdown = PopoverDropdown;\nPopover.varsResolver = varsResolver;\nPopover.displayName = '@mantine/core/Popover';\nPopover.extend = (input: ExtendComponent<PopoverFactory>) => input;\n\nexport namespace Popover {\n export type Props = PopoverProps;\n export type __Props = __PopoverProps;\n export type Factory = PopoverFactory;\n export type StylesNames = PopoverStylesNames;\n export type TargetProps = PopoverTargetProps;\n export type DropdownProps = PopoverDropdownProps;\n export type Width = PopoverWidth;\n export type ContextValue = PopoverContextValue;\n\n export namespace Target {\n export type Props = PopoverTargetProps;\n }\n\n export namespace Dropdown {\n export type Props = PopoverDropdownProps;\n }\n}\n"],"mappings":"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"}