UNPKG

selection-popover

Version:

Easy-to-use, composable react selection popover.

1 lines 35.1 kB
{"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import * as React from 'react'\nimport { createContext } from '@radix-ui/react-context'\nimport { useComposedRefs } from '@radix-ui/react-compose-refs'\nimport { Presence } from '@radix-ui/react-presence'\nimport { useControllableState } from '@radix-ui/react-use-controllable-state'\nimport { Primitive } from '@radix-ui/react-primitive'\nimport { useSize } from '@radix-ui/react-use-size'\nimport { Portal as PortalPrimitive } from '@radix-ui/react-portal'\nimport { DismissableLayer } from '@radix-ui/react-dismissable-layer'\nimport { useLayoutEffect } from '@radix-ui/react-use-layout-effect'\nimport * as ArrowPrimitive from '@radix-ui/react-arrow'\nimport {\n useFloating,\n autoUpdate,\n offset,\n shift,\n limitShift,\n flip,\n hide,\n arrow as floatingUIarrow,\n inline,\n} from '@floating-ui/react-dom'\n\nimport type { Placement, Middleware } from '@floating-ui/react-dom'\n\nconst SIDE_OPTIONS = ['top', 'right', 'bottom', 'left'] as const\nconst ALIGN_OPTIONS = ['start', 'center', 'end'] as const\n\ntype Side = (typeof SIDE_OPTIONS)[number]\ntype Align = (typeof ALIGN_OPTIONS)[number]\n\n/* -------------------------------------------------------------------------------------------------\n * Selection\n * -----------------------------------------------------------------------------------------------*/\n\ntype VirtualReference = {\n getBoundingClientRect(): DOMRect\n getClientRects(): DOMRectList\n}\ntype SelectionContextValue = {\n open: boolean\n onOpenChange(open: boolean): void\n onOpen(callback: () => void): void\n onClose(): void\n whileSelect: boolean\n virtualRef: VirtualReference\n onVirtualRefChange(virtualRef: VirtualReference): void\n content: HTMLDivElement | null\n onContentChange(content: HTMLDivElement | null): void\n disabled: boolean\n}\nconst [SelectionProvider, useSelectionContext] = createContext<SelectionContextValue>('Selection')\n\ninterface SelectionProps {\n children?: React.ReactNode\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?(open: boolean): void\n whileSelect?: boolean\n disabled?: boolean\n openDelay?: number\n closeDelay?: number\n}\nconst Selection = (props: SelectionProps) => {\n const {\n children,\n open: openProp,\n defaultOpen,\n onOpenChange,\n whileSelect = false,\n disabled = false,\n openDelay,\n closeDelay,\n } = props\n const openTimerRef = React.useRef(0)\n const closeTimerRef = React.useRef(0)\n const [content, setContent] = React.useState<HTMLDivElement | null>(null)\n const [virtualRef, setVirtualRef] = React.useState({\n getBoundingClientRect: () => DOMRect.fromRect(),\n getClientRects: () => new DOMRectList(),\n })\n const [open = false, setOpen] = useControllableState({\n prop: openProp,\n defaultProp: defaultOpen,\n onChange: onOpenChange,\n })\n const handleOpen = React.useCallback(\n (callback: () => void) => {\n clearTimeout(closeTimerRef.current)\n openTimerRef.current = window.setTimeout(callback, openDelay)\n },\n [openDelay],\n )\n const handleClose = React.useCallback(() => {\n clearTimeout(openTimerRef.current)\n closeTimerRef.current = window.setTimeout(() => setOpen(false), closeDelay)\n }, [closeDelay, setOpen])\n\n return (\n <SelectionProvider\n open={open}\n onOpenChange={setOpen}\n onOpen={handleOpen}\n onClose={handleClose}\n whileSelect={whileSelect}\n virtualRef={virtualRef}\n onVirtualRefChange={setVirtualRef}\n content={content}\n onContentChange={setContent}\n disabled={disabled}\n >\n {children}\n </SelectionProvider>\n )\n}\n\n/* -------------------------------------------------------------------------------------------------\n * SelectionTrigger\n * -----------------------------------------------------------------------------------------------*/\n\nconst TRIGGER_NAME = 'SelectionTrigger'\n\ntype SelectionTriggerElement = SelectionTriggerImplElement\ninterface SelectionTriggerProps extends SelectionTriggerImplProps { }\n\nconst SelectionTrigger = React.forwardRef<SelectionTriggerElement, SelectionTriggerProps>(\n (props, forwardedRef) => {\n const context = useSelectionContext(TRIGGER_NAME)\n const ref = React.useRef<HTMLDivElement>(null)\n const composedRefs = useComposedRefs(forwardedRef, ref)\n\n return context.whileSelect ? (\n <SelectionTriggerWhileSelect {...props} ref={forwardedRef} />\n ) : (\n <SelectionTriggerImpl\n {...props}\n ref={composedRefs}\n onPointerUp={(event) => {\n props.onPointerUp?.(event)\n\n if (event.pointerType !== 'mouse') return\n\n context.onOpen(() => {\n const selection = document.getSelection()\n if (!selection) return\n const trigger = ref.current\n const wasSelectionInsideTrigger = trigger?.contains(selection.anchorNode)\n if (!wasSelectionInsideTrigger) return\n if (selection.toString().trim() === '') return\n if (selection.isCollapsed) return\n const range = selection.getRangeAt(0)\n context.onOpenChange(true)\n context.onVirtualRefChange({\n getBoundingClientRect: () => range.getBoundingClientRect(),\n getClientRects: () => range.getClientRects(),\n })\n })\n }}\n />\n )\n },\n)\n\nSelectionTrigger.displayName = TRIGGER_NAME\n\n/* ---------------------------------------------------------------------------------------------- */\n\nlet originalBodyUserSelect: string\n\ntype SelectionTriggerWhileSelectElement = SelectionTriggerImplElement\ninterface SelectionTriggerWhileSelectProps extends SelectionTriggerImplProps { }\n\nconst SelectionTriggerWhileSelect = React.forwardRef<\n SelectionTriggerWhileSelectElement,\n SelectionTriggerWhileSelectProps\n>((props, forwardedRef) => {\n const context = useSelectionContext(TRIGGER_NAME)\n const [containSelection, setContainSelection] = React.useState(false)\n const ref = React.useRef<HTMLDivElement>(null)\n const pointerTypeRef = React.useRef('')\n const hasOpenedRef = React.useRef(false)\n const composedRefs = useComposedRefs(forwardedRef, ref)\n const handlePointerUp = React.useCallback(() => {\n setContainSelection(false)\n }, [])\n\n const { onOpen, onOpenChange, onVirtualRefChange } = context\n\n React.useEffect(() => {\n if (!context.disabled) {\n const handleSelection = () => {\n if (pointerTypeRef.current !== 'mouse') return\n const selection = document.getSelection()\n if (!selection) return\n const node = ref.current\n const wasSelectionInsideTrigger = node?.contains(selection.anchorNode)\n if (!wasSelectionInsideTrigger) {\n hasOpenedRef.current = false\n return\n }\n if (selection.isCollapsed) {\n hasOpenedRef.current = false\n return\n }\n const hasTextSelected = selection.toString().trim() !== ''\n if (hasTextSelected) {\n const range = selection?.getRangeAt(0)\n if (!hasOpenedRef.current) onOpen(() => onOpenChange(true))\n hasOpenedRef.current = true\n onVirtualRefChange({\n getBoundingClientRect: () => range.getBoundingClientRect(),\n getClientRects: () => range.getClientRects(),\n })\n }\n }\n document.addEventListener('selectionchange', handleSelection)\n return () => document.removeEventListener('selectionchange', handleSelection)\n }\n }, [context.disabled, onOpenChange, onOpen, onVirtualRefChange])\n\n React.useEffect(() => {\n if (containSelection) {\n const body = document.body\n\n // Safari requires prefix\n originalBodyUserSelect = body.style.userSelect || body.style.webkitUserSelect\n\n body.style.userSelect = 'none'\n body.style.webkitUserSelect = 'none'\n\n return () => {\n body.style.userSelect = originalBodyUserSelect\n body.style.webkitUserSelect = originalBodyUserSelect\n }\n }\n }, [containSelection])\n\n React.useEffect(() => {\n return () => document.removeEventListener('pointerup', handlePointerUp)\n }, [handlePointerUp])\n\n return (\n <SelectionTriggerImpl\n {...props}\n ref={composedRefs}\n onPointerDown={(event) => {\n props.onPointerDown?.(event)\n\n pointerTypeRef.current = event.pointerType\n setContainSelection(true)\n document.addEventListener('pointerup', handlePointerUp, { once: true })\n }}\n style={{\n userSelect: containSelection ? 'text' : undefined,\n WebkitUserSelect: containSelection ? 'text' : undefined,\n ...props.style,\n }}\n />\n )\n})\n\n/* ---------------------------------------------------------------------------------------------- */\n\ntype SelectionTriggerImplElement = React.ElementRef<typeof Primitive.div>\ntype PrimitiveDivProps = React.ComponentPropsWithoutRef<typeof Primitive.div>\ninterface SelectionTriggerImplProps extends PrimitiveDivProps { }\n\nconst SelectionTriggerImpl = React.forwardRef<\n SelectionTriggerImplElement,\n SelectionTriggerImplProps\n>((props, forwardedRef) => {\n const context = useSelectionContext(TRIGGER_NAME)\n const [disablePointerEvents, setDisablePointerEvents] = React.useState(false)\n const handlePointerUp = React.useCallback(() => {\n setDisablePointerEvents(false)\n }, [])\n\n React.useEffect(() => {\n if (context.content && disablePointerEvents) {\n const content = context.content\n const originalContentPointerEvents = content.style.pointerEvents\n\n content.style.pointerEvents = 'none'\n\n return () => {\n content.style.pointerEvents = originalContentPointerEvents\n }\n }\n }, [context.content, disablePointerEvents])\n\n React.useEffect(() => {\n return () => document.removeEventListener('pointerup', handlePointerUp)\n }, [handlePointerUp])\n\n return (\n <Primitive.div\n {...props}\n ref={forwardedRef}\n onPointerDown={(event) => {\n props.onPointerDown?.(event)\n\n setDisablePointerEvents(true)\n document.addEventListener('pointerup', handlePointerUp, { once: true })\n }}\n />\n )\n})\n\n/* -------------------------------------------------------------------------------------------------\n * SelectionPortal\n * -----------------------------------------------------------------------------------------------*/\n\nconst PORTAL_NAME = 'SelectionPortal'\n\ntype PortalContextValue = { forceMount?: true }\nconst [PortalProvider, usePortalContext] = createContext<PortalContextValue>(PORTAL_NAME, {\n forceMount: undefined,\n})\n\ntype PortalProps = React.ComponentPropsWithoutRef<typeof PortalPrimitive>\ninterface SelectionPortalProps extends Omit<PortalProps, 'asChild'> {\n children?: React.ReactNode\n forceMount?: true\n}\n\nconst SelectionPortal = (props: SelectionPortalProps) => {\n const { forceMount, container, children } = props\n const context = useSelectionContext(PORTAL_NAME)\n return (\n <PortalProvider forceMount={forceMount}>\n <Presence present={forceMount || context.open}>\n <PortalPrimitive asChild container={container}>\n {children}\n </PortalPrimitive>\n </Presence>\n </PortalProvider>\n )\n}\n\nSelectionPortal.displayName = PORTAL_NAME\n\n/* -------------------------------------------------------------------------------------------------\n * SelectionContent\n * -----------------------------------------------------------------------------------------------*/\n\nconst CONTENT_NAME = 'SelectionContent'\n\ntype SelectionContentElement = SelectionContentImplElement\ninterface SelectionContentProps extends SelectionContentImplProps {\n forceMount?: true\n}\n\nconst SelectionContent = React.forwardRef<SelectionContentElement, SelectionContentProps>(\n (props, forwardedRef) => {\n const portalContext = usePortalContext(CONTENT_NAME)\n const { forceMount = portalContext.forceMount, ...contentProps } = props\n const context = useSelectionContext(CONTENT_NAME)\n return (\n <Presence present={forceMount || context.open}>\n <SelectionContentImpl {...contentProps} ref={forwardedRef} />\n </Presence>\n )\n },\n)\n\n/* ---------------------------------------------------------------------------------------------- */\n\ntype SelectionContentContextValue = {\n placedSide: Side\n onArrowChange(arrow: HTMLSpanElement | null): void\n arrowX?: number\n arrowY?: number\n shouldHideArrow: boolean\n}\n\nconst [SelectionContentProvider, useContentContext] =\n createContext<SelectionContentContextValue>(CONTENT_NAME)\n\ntype Boundary = Element | null\n\ntype SelectionContentImplElement = React.ElementRef<typeof Primitive.div>\ntype DismissableLayerProps = React.ComponentPropsWithoutRef<typeof DismissableLayer>\ninterface SelectionContentImplProps extends PrimitiveDivProps {\n side?: Side\n sideOffset?: number\n align?: Align\n alignOffset?: number\n arrowPadding?: number\n collisionBoundary?: Boundary | Boundary[]\n collisionPadding?: number | Partial<Record<Side, number>>\n sticky?: 'partial' | 'always'\n hideWhenDetached?: boolean\n avoidCollisions?: boolean\n onEscapeKeyDown?: DismissableLayerProps['onEscapeKeyDown']\n onPointerDownOutside?: DismissableLayerProps['onPointerDownOutside']\n onFocusOutside?: DismissableLayerProps['onFocusOutside']\n onInteractOutside?: DismissableLayerProps['onInteractOutside']\n}\n\nconst SelectionContentImpl = React.forwardRef<\n SelectionContentImplElement,\n SelectionContentImplProps\n>((props, forwardedRef) => {\n const {\n side = 'top',\n sideOffset = 0,\n align = 'center',\n alignOffset = 0,\n arrowPadding = 0,\n sticky = 'partial',\n collisionBoundary = [],\n collisionPadding: collisionPaddingProp = 0,\n hideWhenDetached = false,\n avoidCollisions = true,\n onEscapeKeyDown,\n onPointerDownOutside,\n onFocusOutside,\n onInteractOutside,\n ...contentProps\n } = props\n const context = useSelectionContext(CONTENT_NAME)\n const { onClose, onContentChange } = context\n const [content, setContent] = React.useState<HTMLDivElement | null>(null)\n const composedRefs = useComposedRefs(forwardedRef, (node) => setContent(node))\n\n const [arrow, setArrow] = React.useState<HTMLSpanElement | null>(null)\n const arrowSize = useSize(arrow)\n const arrowWidth = arrowSize?.width ?? 0\n const arrowHeight = arrowSize?.height ?? 0\n\n const desiredPlacement = (side + (align !== 'center' ? '-' + align : '')) as Placement\n\n const collisionPadding =\n typeof collisionPaddingProp === 'number'\n ? collisionPaddingProp\n : { top: 0, right: 0, bottom: 0, left: 0, ...collisionPaddingProp }\n\n const boundary = Array.isArray(collisionBoundary) ? collisionBoundary : [collisionBoundary]\n const hasExplicitBoundaries = boundary.length > 0\n\n const detectOverflowOptions = {\n padding: collisionPadding,\n boundary: boundary.filter(isNotNull),\n altBoundary: hasExplicitBoundaries,\n }\n\n const { x, y, strategy, placement, refs, middlewareData, isPositioned } = useFloating({\n strategy: 'fixed',\n placement: desiredPlacement,\n whileElementsMounted: autoUpdate,\n middleware: [\n inline(),\n anchorCssProperties(),\n offset({ mainAxis: sideOffset + arrowHeight, alignmentAxis: alignOffset }),\n avoidCollisions ? flip(detectOverflowOptions) : undefined,\n avoidCollisions\n ? shift({\n mainAxis: true,\n crossAxis: false,\n limiter: sticky === 'partial' ? limitShift() : undefined,\n ...detectOverflowOptions,\n })\n : undefined,\n arrow ? floatingUIarrow({ element: arrow, padding: arrowPadding }) : undefined,\n transformOrigin({ arrowWidth, arrowHeight }),\n hideWhenDetached ? hide({ strategy: 'referenceHidden' }) : undefined,\n ],\n })\n\n useLayoutEffect(() => {\n refs.setReference(context.virtualRef)\n onContentChange(refs.floating.current as HTMLDivElement)\n }, [context.virtualRef, onContentChange, refs])\n\n const [placedSide, placedAlign] = getSideAndAlignFromPlacement(placement)\n\n const arrowX = middlewareData.arrow?.x\n const arrowY = middlewareData.arrow?.y\n const cannotCenterArrow = middlewareData.arrow?.centerOffset !== 0\n\n const [contentZIndex, setContentZIndex] = React.useState<string>()\n useLayoutEffect(() => {\n if (content) setContentZIndex(window.getComputedStyle(content).zIndex)\n }, [content])\n\n return (\n <div\n ref={refs.setFloating}\n style={{\n position: strategy,\n top: 0,\n left: 0,\n transform: isPositioned\n ? `translate3d(${Math.round(x ?? 0)}px, ${Math.round(y ?? 0)}px, 0)`\n : 'translate3d(0, -200%, 0)',\n minWidth: 'max-content',\n zIndex: contentZIndex,\n }}\n >\n <SelectionContentProvider\n placedSide={placedSide}\n onArrowChange={setArrow}\n arrowX={arrowX}\n arrowY={arrowY}\n shouldHideArrow={cannotCenterArrow}\n >\n <DismissableLayer\n asChild\n onEscapeKeyDown={onEscapeKeyDown}\n onPointerDownOutside={onPointerDownOutside}\n onFocusOutside={onFocusOutside}\n onInteractOutside={onInteractOutside}\n onDismiss={onClose}\n >\n <Primitive.div\n data-side={placedSide}\n data-align={placedAlign}\n data-state={context.open ? 'open' : 'closed'}\n {...contentProps}\n ref={composedRefs}\n style={{\n userSelect: 'none',\n ...contentProps.style,\n animation: !isPositioned ? 'none' : undefined,\n opacity: middlewareData.hide?.referenceHidden ? 0 : undefined,\n ['--selection-popover-content-transform-origin' as any]: [\n middlewareData.transformOrigin?.x,\n middlewareData.transformOrigin?.y,\n ].join(' '),\n }}\n />\n </DismissableLayer>\n </SelectionContentProvider>\n </div>\n )\n})\n\nSelectionContent.displayName = CONTENT_NAME\n\n/* -------------------------------------------------------------------------------------------------\n * SelectionArrow\n * -----------------------------------------------------------------------------------------------*/\n\nconst ARROW_NAME = 'SelectionArrow'\n\nconst OPPOSITE_SIDE: Record<Side, Side> = {\n top: 'bottom',\n right: 'left',\n bottom: 'top',\n left: 'right',\n}\n\ntype SelectionArrowElement = React.ElementRef<typeof ArrowPrimitive.Root>\ntype ArrowProps = React.ComponentPropsWithoutRef<typeof ArrowPrimitive.Root>\ninterface SelectionArrowProps extends ArrowProps { }\n\nconst SelectionArrow = React.forwardRef<SelectionArrowElement, SelectionArrowProps>(\n (props, forwardedRef) => {\n const contentContext = useContentContext(ARROW_NAME)\n const baseSide = OPPOSITE_SIDE[contentContext.placedSide]\n\n return (\n <span\n ref={contentContext.onArrowChange}\n style={{\n position: 'absolute',\n left: contentContext.arrowX,\n top: contentContext.arrowY,\n [baseSide]: 0,\n transformOrigin: {\n top: '',\n right: '0 0',\n bottom: 'center 0',\n left: '100% 0',\n }[contentContext.placedSide],\n transform: {\n top: 'translateY(100%)',\n right: 'translateY(50%) rotate(90deg) translateX(-50%)',\n bottom: 'rotate(180deg)',\n left: 'translateY(50%) rotate(-90deg) translateX(50%)',\n }[contentContext.placedSide],\n visibility: contentContext.shouldHideArrow ? 'hidden' : undefined,\n }}\n >\n <ArrowPrimitive.Root\n {...props}\n ref={forwardedRef}\n style={{ ...props.style, display: 'block' }}\n />\n </span>\n )\n },\n)\n\nSelectionArrow.displayName = ARROW_NAME\n\n/* -----------------------------------------------------------------------------------------------*/\n\nfunction isNotNull<T>(value: T | null): value is T {\n return value !== null\n}\n\nfunction getSideAndAlignFromPlacement(placement: Placement) {\n const [side, align = 'center'] = placement.split('-')\n return [side as Side, align as Align] as const\n}\n\nconst anchorCssProperties = (): Middleware => ({\n name: 'anchorCssProperties',\n async fn(data) {\n const { rects, elements, platform } = data\n const { width, height } = rects.reference\n const { width: popoverWidth, height: popoverHeight } = rects.floating\n elements.floating.style.setProperty('--selection-popover-select-width', `${width}px`)\n elements.floating.style.setProperty('--selection-popover-select-height', `${height}px`)\n const newDimensions = await platform.getDimensions(elements.floating)\n if (popoverWidth !== newDimensions.width || popoverHeight !== newDimensions.height) {\n return { reset: { rects: true } }\n }\n return {}\n },\n})\n\nconst transformOrigin = (options: { arrowWidth: number; arrowHeight: number }): Middleware => ({\n name: 'transformOrigin',\n options,\n fn(data) {\n const { placement, rects, middlewareData } = data\n\n const cannotCenterArrow = middlewareData.arrow?.centerOffset !== 0\n const isArrowHidden = cannotCenterArrow\n const arrowWidth = isArrowHidden ? 0 : options.arrowWidth\n const arrowHeight = isArrowHidden ? 0 : options.arrowHeight\n\n const [placedSide, placedAlign] = getSideAndAlignFromPlacement(placement)\n const noArrowAlign = { start: '0%', center: '50%', end: '100%' }[placedAlign]\n\n const arrowXCenter = (middlewareData.arrow?.x ?? 0) + arrowWidth / 2\n const arrowYCenter = (middlewareData.arrow?.y ?? 0) + arrowHeight / 2\n\n let x = ''\n let y = ''\n\n if (placedSide === 'bottom') {\n x = isArrowHidden ? noArrowAlign : `${arrowXCenter}px`\n y = `${-arrowHeight}px`\n } else if (placedSide === 'top') {\n x = isArrowHidden ? noArrowAlign : `${arrowXCenter}px`\n y = `${rects.floating.height + arrowHeight}px`\n } else if (placedSide === 'right') {\n x = `${-arrowHeight}px`\n y = isArrowHidden ? noArrowAlign : `${arrowYCenter}px`\n } else if (placedSide === 'left') {\n x = `${rects.floating.width + arrowHeight}px`\n y = isArrowHidden ? noArrowAlign : `${arrowYCenter}px`\n }\n return { data: { x, y } }\n },\n})\n\nexport {\n Selection as Root,\n SelectionTrigger as Trigger,\n SelectionPortal as Portal,\n SelectionContent as Content,\n SelectionArrow as Arrow,\n}\n"],"mappings":"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","names":["React","createContext","useComposedRefs","Presence","useControllableState","Primitive","useSize","PortalPrimitive","DismissableLayer","useLayoutEffect","ArrowPrimitive","useFloating","autoUpdate","offset","shift","limitShift","flip","hide","floatingUIarrow","inline","SelectionProvider","useSelectionContext","createContext","Selection","props","children","openProp","defaultOpen","onOpenChange","whileSelect","disabled","openDelay","closeDelay","openTimerRef","closeTimerRef","content","setContent","virtualRef","setVirtualRef","open","setOpen","useControllableState","handleOpen","callback","handleClose","TRIGGER_NAME","SelectionTrigger","forwardedRef","context","ref","composedRefs","useComposedRefs","SelectionTriggerWhileSelect","SelectionTriggerImpl","event","_a","selection","trigger","range","originalBodyUserSelect","containSelection","setContainSelection","pointerTypeRef","hasOpenedRef","handlePointerUp","onOpen","onVirtualRefChange","handleSelection","node","body","disablePointerEvents","setDisablePointerEvents","originalContentPointerEvents","Primitive","PORTAL_NAME","PortalProvider","usePortalContext","SelectionPortal","forceMount","container","Presence","PortalPrimitive","CONTENT_NAME","SelectionContent","portalContext","contentProps","SelectionContentImpl","SelectionContentProvider","useContentContext","_b","_c","_d","_e","_f","_g","_h","side","sideOffset","align","alignOffset","arrowPadding","sticky","collisionBoundary","collisionPaddingProp","hideWhenDetached","avoidCollisions","onEscapeKeyDown","onPointerDownOutside","onFocusOutside","onInteractOutside","onClose","onContentChange","arrow","setArrow","arrowSize","useSize","arrowWidth","arrowHeight","desiredPlacement","collisionPadding","boundary","hasExplicitBoundaries","detectOverflowOptions","isNotNull","x","y","strategy","placement","refs","middlewareData","isPositioned","useFloating","autoUpdate","inline","anchorCssProperties","offset","flip","shift","limitShift","floatingUIarrow","transformOrigin","hide","useLayoutEffect","placedSide","placedAlign","getSideAndAlignFromPlacement","arrowX","arrowY","cannotCenterArrow","contentZIndex","setContentZIndex","DismissableLayer","ARROW_NAME","OPPOSITE_SIDE","SelectionArrow","contentContext","baseSide","value","data","rects","elements","platform","width","height","popoverWidth","popoverHeight","newDimensions","options","isArrowHidden","noArrowAlign","arrowXCenter","arrowYCenter"]}