@entur/tooltip 3.0.2 → 4.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.cjs.production.min.js","sources":["../src/Popover.tsx","../src/index.tsx","../src/Tooltip.tsx"],"sourcesContent":["import React, { cloneElement, createContext, useContext } from 'react';\n\nimport { usePopper } from 'react-popper';\nimport { Placement } from '@popperjs/core';\nimport classNames from 'classnames';\n\nimport { Contrast } from '@entur/layout';\nimport { useOnClickOutside } from '@entur/utils';\n\nimport './Popover.scss';\n\ntype PopoverContentCallbackProps = {\n ref: React.Ref<HTMLDivElement>;\n};\n\ntype PopoverContextProps = {\n showPopover: boolean;\n triggerElement?: React.RefObject<HTMLButtonElement>;\n contentElement: React.RefObject<HTMLDivElement>;\n styles: { [key: string]: React.CSSProperties };\n attributes: { [key: string]: { [key: string]: string } | undefined };\n closeButtonProps: Record<string, unknown>;\n popoverContentProps: (\n e: PopoverContentCallbackProps,\n ) => Record<string, unknown>;\n triggerProps: () => Record<string, unknown>;\n [key: string]: any;\n};\n\nconst PopoverContext = createContext<PopoverContextProps | undefined>(\n undefined,\n);\nconst usePopoverContext = () => {\n const context = useContext(PopoverContext);\n if (context == null) {\n throw Error('usePopoverContext must be used within <Popover/>');\n }\n return context;\n};\n\nconst useCustomState = (\n state?: boolean,\n setState?: React.Dispatch<React.SetStateAction<boolean>>,\n): [boolean, React.Dispatch<React.SetStateAction<boolean>>, boolean] => {\n const [internalState, setInternalState] = React.useState<boolean>(false);\n const controlled = state !== undefined && setState !== undefined;\n if (controlled) return [state, setState, controlled];\n return [internalState, setInternalState, controlled];\n};\n\nexport type PopoverProps = {\n /** Innholdet i Popover */\n children: React.ReactNode;\n /** Plasseringen av Popover\n * @default \"bottom-start\"\n */\n placement?: Placement;\n /** Hvis du ønsker å styre state selv kan du sende inn state her */\n showPopover?: boolean;\n /** Hvis du ønsker å styre state selv kan du sende inn setState her */\n setShowPopover?: React.Dispatch<React.SetStateAction<boolean>>;\n};\n\nexport const Popover: React.FC<PopoverProps> = ({\n children,\n placement = 'bottom-start',\n showPopover: controlledState,\n setShowPopover: setControlledState,\n}) => {\n const [showPopover, setShowPopover, controlled] = useCustomState(\n controlledState,\n setControlledState,\n );\n const triggerElement = React.useRef(null);\n const contentElement = React.useRef(null);\n\n const { styles, attributes, forceUpdate } = usePopper(\n triggerElement.current,\n contentElement.current,\n {\n modifiers: [\n { name: 'arrow', enabled: false },\n {\n name: 'offset',\n options: {\n offset: [0, 8],\n },\n },\n ],\n placement: placement,\n },\n );\n\n React.useEffect(() => {\n if (forceUpdate) {\n forceUpdate();\n }\n }, [showPopover, forceUpdate]);\n\n const triggerProps = React.useCallback(() => {\n const buttonProps = {\n 'aria-haspopup': 'dialog',\n 'aria-expanded': showPopover,\n ref: triggerElement,\n type: 'button',\n };\n const buttonOnClick = {\n onClick: (e: React.MouseEvent) => {\n e.preventDefault();\n setShowPopover(prev => !prev);\n },\n };\n return controlled ? buttonProps : { ...buttonProps, ...buttonOnClick };\n }, [triggerElement, showPopover, setShowPopover, controlled]);\n\n useOnClickOutside([contentElement, triggerElement], () =>\n setShowPopover(false),\n );\n const closeButtonProps = {\n onClick: (e: React.MouseEvent) => {\n e.preventDefault();\n setShowPopover(false);\n },\n type: 'button',\n };\n const popoverContentProps = React.useCallback(() => {\n const contentProps = {\n role: 'dialog',\n 'aria-modal': 'false',\n ref: contentElement,\n onKeyDown: (event: React.KeyboardEvent) => {\n if (event.key === 'Escape') {\n showPopover && setShowPopover(false);\n }\n },\n onBlur: (event: React.FocusEvent) => {\n const elementReceivingFocus = event.relatedTarget as HTMLElement;\n // The check for 'tabindex=-1' is a special case for focus handling in Docz\n if (\n !elementReceivingFocus ||\n elementReceivingFocus.getAttribute('tabindex') === '-1'\n )\n return;\n const focusElementIsPopover = elementContainsElement(\n contentElement.current,\n elementReceivingFocus,\n );\n const focusElementIsTrigger = elementContainsElement(\n triggerElement.current,\n elementReceivingFocus,\n );\n const isValidBlur = !focusElementIsPopover && !focusElementIsTrigger;\n if (showPopover && isValidBlur) setShowPopover(false);\n },\n };\n return contentProps;\n }, [contentElement, showPopover, setShowPopover]);\n const contextValue: PopoverContextProps = {\n showPopover,\n triggerElement,\n contentElement,\n styles,\n attributes,\n popoverContentProps,\n closeButtonProps,\n triggerProps,\n };\n return (\n <PopoverContext.Provider value={contextValue}>\n {children}\n </PopoverContext.Provider>\n );\n};\n\nexport type PopoverTriggerProps = {\n /** Knapp som skal brukes for å åpne Popover */\n children: React.ReactElement;\n};\n\nexport const PopoverTrigger: React.FC<PopoverTriggerProps> = ({ children }) => {\n const { triggerProps } = usePopoverContext();\n const child = React.Children.only(children) as React.ReactElement<any>;\n return cloneElement(child, triggerProps());\n};\n\nexport type PopoverCloseButtonProps = {\n /** En valgfri knapp som kan legges inn for å lukke Popover */\n children: React.ReactElement;\n};\n\nexport const PopoverCloseButton: React.FC<PopoverCloseButtonProps> = ({\n children,\n ...rest\n}) => {\n const { closeButtonProps } = usePopoverContext();\n return cloneElement(children, { ...closeButtonProps, ...rest });\n};\n\nexport type PopoverContentProps = {\n /**Innholdet til Popover */\n children: React.ReactNode;\n};\n\nexport const PopoverContent = React.forwardRef<\n HTMLDivElement,\n PopoverContentProps\n>(({ children }, ref: React.Ref<HTMLDivElement>) => {\n const { showPopover, attributes, styles, popoverContentProps } =\n usePopoverContext();\n const props = popoverContentProps({ ref });\n return (\n <Contrast\n className={classNames(\n 'eds-popover',\n {\n 'eds-popover--hidden': !showPopover,\n },\n 'eds-contrast',\n )}\n style={styles.popper}\n aria-hidden={!showPopover}\n {...attributes.styles}\n {...props}\n >\n {children}\n </Contrast>\n );\n});\n\nfunction elementContainsElement(\n parent: HTMLElement | null,\n child: HTMLElement,\n) {\n if (!parent) return false;\n return parent === child || parent.contains(child);\n}\n","import { warnAboutMissingStyles } from '@entur/utils';\nimport './index.scss';\n\nwarnAboutMissingStyles('tooltip');\n\nexport * from './Tooltip';\nexport * from './Popover';\n","import React, { cloneElement, useState } from 'react';\nimport { Manager, Reference, Popper } from 'react-popper';\nimport classNames from 'classnames';\nimport { useRandomId } from '@entur/utils';\nimport { Placement as PopperPlacementProps } from '@popperjs/core';\nimport { CloseIcon } from '@entur/icons';\nimport { IconButton } from '@entur/button';\nimport './Tooltip.scss';\n\ntype Modifier = {\n name: string;\n enabled?: boolean;\n requires?: Array<string>;\n requiresIfExists?: Array<string>;\n options?: Record<string, unknown>;\n data?: Record<string, unknown>;\n [key: string]: any;\n};\n\n/** @deprecated use variant=\"negative\" instead */\nconst error = 'error';\n\nexport type TooltipProps = {\n /** Plassering av tooltip-en */\n placement:\n | 'top'\n | 'top-left'\n | 'top-right'\n | 'left'\n | 'right'\n | 'bottom-left' // bottom-start\n | 'bottom'\n | 'bottom-right'; // bottom-end\n /** Innholdet i tooltip-boksen */\n content: React.ReactNode;\n /** Elementet som skal ha tooltip-funksjonalitet */\n children: React.ReactElement;\n /** Om tooltipen skal vises */\n isOpen?: boolean;\n /** Ekstra klassenavn for tooltip */\n className?: string;\n /** Åpner ikke tooltip ved hover-events\n * @default false\n */\n disableHoverListener?: boolean;\n /** Åpner ikke tooltip ved focus-events\n * @default false\n */\n disableFocusListener?: boolean;\n disableKeyboardListener?: boolean;\n disableClickListner?: boolean;\n /** Viser en lukkeknapp om man kontrollerer åpningen av Tooltip vha `isOpen`\n * @default true\n */\n showCloseButton?: boolean;\n /** Valideringsvariant for Tooltip */\n variant?: 'negative' | typeof error;\n /** En array av modifiers som sendes til Popper, rammeverket som brukes til plassering av Tooltip\n * @default [{ name: 'offset', options: { offset: [0, 10]} }]\n */\n popperModifiers?: Modifier[];\n [key: string]: any;\n};\n\nexport const Tooltip: React.FC<TooltipProps> = ({\n placement,\n content,\n children,\n className,\n isOpen = false,\n disableHoverListener = false,\n disableFocusListener = false,\n disableKeyboardListener = true,\n disableClickListner = true,\n showCloseButton = true,\n variant,\n popperModifiers = [\n {\n name: 'offset',\n options: { offset: [0, 10] },\n },\n ],\n ...rest\n}) => {\n const [showTooltip, setShowTooltip] = useState(isOpen || false);\n let hoverTimer: ReturnType<typeof setTimeout>;\n\n const handleOpen: (event: React.MouseEvent) => void = event => {\n event.persist();\n hoverTimer = setTimeout(() => {\n setShowTooltip(true);\n }, 150);\n };\n const onMouseExit: () => void = () => {\n setShowTooltip(false);\n clearTimeout(hoverTimer);\n };\n React.useEffect(() => {\n return () => {\n clearTimeout(hoverTimer);\n };\n });\n\n const tooltipId = useRandomId('eds-tooltip');\n React.useEffect(() => {\n setShowTooltip(isOpen);\n }, [isOpen]);\n\n React.useEffect(() => {\n if (!content) {\n setShowTooltip(false);\n }\n }, [content]);\n\n let popperPlacement = placement as PopperPlacementProps;\n if (placement.includes('-')) {\n if (placement.includes('right')) {\n popperPlacement = placement.replace(\n 'right',\n 'end',\n ) as PopperPlacementProps;\n }\n if (placement.includes('left')) {\n popperPlacement = placement.replace(\n 'left',\n 'start',\n ) as PopperPlacementProps;\n }\n }\n\n const childProps: {\n 'aria-describedby'?: string;\n onFocus?: () => void;\n onBlur?: () => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: () => void;\n onKeyDown?: (e: React.KeyboardEvent) => void;\n onKeyUp?: (e: React.KeyboardEvent) => void;\n onClick?: (e: React.MouseEvent) => void;\n } = {};\n childProps['aria-describedby'] = showTooltip ? tooltipId : undefined;\n\n if (!disableFocusListener) {\n childProps.onFocus = () => setShowTooltip(true);\n childProps.onBlur = () => setShowTooltip(false);\n }\n if (!disableHoverListener) {\n childProps.onMouseEnter = e => handleOpen(e);\n childProps.onMouseLeave = () => onMouseExit();\n }\n if (!disableKeyboardListener) {\n childProps.onKeyDown = e => {\n if (e.key === 'Escape') setShowTooltip(false);\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n setShowTooltip(!showTooltip);\n }\n };\n }\n if (!disableClickListner) {\n childProps.onClick = () => setShowTooltip(!showTooltip);\n }\n\n return (\n <Manager>\n <Reference>\n {({ ref }) =>\n cloneElement(children, {\n ref: ref,\n ...childProps,\n })\n }\n </Reference>\n {showTooltip && (\n <Popper\n modifiers={[{ name: 'arrow', enabled: false }, ...popperModifiers]}\n placement={popperPlacement}\n >\n {({ ref, style, placement: popperPlacement }) => (\n <div\n className={classNames(\n 'eds-tooltip',\n className,\n `eds-tooltip--${popperPlacement}`,\n {\n 'eds-tooltip--negative':\n variant === error || variant === 'negative',\n },\n )}\n ref={ref}\n style={style}\n role=\"tooltip\"\n id={tooltipId}\n data-placement={popperPlacement}\n {...rest}\n >\n {content}\n {isOpen && showCloseButton && (\n <IconButton\n className=\"eds-tooltip__close-button\"\n onClick={() => setShowTooltip(false)}\n type=\"button\"\n >\n <CloseIcon />\n </IconButton>\n )}\n </div>\n )}\n </Popper>\n )}\n </Manager>\n );\n};\n"],"names":["PopoverContext","createContext","undefined","usePopoverContext","context","useContext","Error","PopoverContent","React","forwardRef","ref","children","_usePopoverContext3","showPopover","attributes","styles","props","popoverContentProps","Contrast","_extends","className","classNames","style","popper","elementContainsElement","parent","child","contains","warnAboutMissingStyles","_ref","_ref$placement","placement","_useCustomState","state","setState","_React$useState","useState","controlled","useCustomState","setShowPopover","triggerElement","useRef","contentElement","usePopper","current","modifiers","name","enabled","options","offset","forceUpdate","useEffect","triggerProps","useCallback","buttonProps","type","onClick","e","preventDefault","prev","useOnClickOutside","closeButtonProps","role","onKeyDown","event","key","onBlur","elementReceivingFocus","relatedTarget","getAttribute","focusElementIsPopover","focusElementIsTrigger","createElement","Provider","value","_ref3","rest","_objectWithoutPropertiesLoose","_excluded","_usePopoverContext2","cloneElement","_ref2","Children","only","hoverTimer","content","_ref$isOpen","isOpen","_ref$disableHoverList","disableHoverListener","_ref$disableFocusList","disableFocusListener","_ref$disableKeyboardL","disableKeyboardListener","_ref$disableClickList","disableClickListner","_ref$showCloseButton","showCloseButton","variant","_ref$popperModifiers","popperModifiers","_useState","showTooltip","setShowTooltip","clearTimeout","tooltipId","useRandomId","popperPlacement","includes","replace","childProps","onFocus","onMouseEnter","persist","setTimeout","onMouseLeave","Manager","Reference","Popper","concat","id","IconButton","CloseIcon"],"mappings":"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"}
1
+ {"version":3,"file":"tooltip.cjs.production.min.js","sources":["../src/utils.ts","../src/Popover.tsx","../src/index.tsx","../src/Tooltip.tsx"],"sourcesContent":["import { Placement as FloatingUIPlacement } from '@floating-ui/react-dom';\n\nexport type Placement =\n | 'top'\n | 'top-left'\n | 'top-start'\n | 'top-right'\n | 'top-end'\n | 'left'\n | 'right'\n | 'bottom-left'\n | 'bottom-start'\n | 'bottom'\n | 'bottom-right'\n | 'bottom-end';\n\nexport function standardisePlacement(placement: string): FloatingUIPlacement {\n switch (placement) {\n case 'top-left':\n return 'top-start';\n case 'top-right':\n return 'top-end';\n case 'bottom-left':\n return 'bottom-start';\n case 'bottom-right':\n return 'bottom-end';\n default:\n return placement as FloatingUIPlacement;\n }\n}\n","import React, {\n cloneElement,\n createContext,\n MutableRefObject,\n useContext,\n} from 'react';\n\nimport classNames from 'classnames';\nimport {\n useFloating,\n autoUpdate,\n offset,\n flip,\n shift,\n limitShift,\n} from '@floating-ui/react-dom';\n\nimport { Contrast } from '@entur/layout';\nimport { mergeRefs, useOnClickOutside } from '@entur/utils';\nimport { space } from '@entur/tokens';\n\nimport { Placement, standardisePlacement } from './utils';\n\nimport './Popover.scss';\n\nexport type PopoverProps = {\n /** Innholdet i Popover */\n children: React.ReactNode;\n /** Plasseringen av Popover\n * @default \"bottom-start\"\n */\n placement?: Placement;\n /** Hvis du ønsker å styre state selv kan du sende inn state her */\n showPopover?: boolean;\n /** Hvis du ønsker å styre state selv kan du sende inn setState her */\n setShowPopover?: React.Dispatch<React.SetStateAction<boolean>>;\n};\n\nexport const Popover: React.FC<PopoverProps> = ({\n children,\n placement = 'bottom-start',\n showPopover: controlledState,\n setShowPopover: setControlledState,\n}) => {\n const [showPopover, setShowPopover, controlled] = useCustomState(\n controlledState,\n setControlledState,\n );\n\n // calculations for floating-UI popover position\n const { refs, floatingStyles } = useFloating<HTMLButtonElement>({\n whileElementsMounted: (ref, float, update) =>\n autoUpdate(ref, float, update),\n placement: standardisePlacement(placement),\n middleware: [\n offset(space.extraSmall),\n flip(),\n shift({ padding: space.extraSmall, limiter: limitShift({ offset: 8 }) }),\n ],\n });\n\n useOnClickOutside([refs.floating, refs.reference], () =>\n setShowPopover(false),\n );\n\n const popoverTriggerProps = {\n 'aria-haspopup': 'dialog',\n 'aria-expanded': showPopover,\n ref: refs.setReference,\n type: 'button',\n ...(!controlled && {\n onClick: () => setShowPopover(prev => !prev),\n }),\n };\n\n const popoverContentProps = {\n role: 'dialog',\n 'aria-modal': false,\n 'aria-hidden': !showPopover,\n ref: refs.setFloating,\n style: { ...(!showPopover && { display: 'none' }) },\n onKeyDown: (event: React.KeyboardEvent) => {\n if (event.key === 'Escape') setShowPopover(false);\n },\n onBlur: (event: React.FocusEvent) => {\n const elementReceivingFocus = event.relatedTarget as HTMLElement;\n // The check for 'tabindex=-1' is a special case for focus handling in Docz\n if (\n !elementReceivingFocus ||\n elementReceivingFocus.getAttribute('tabindex') === '-1'\n )\n return;\n const focusedElementIsPopover = elementContainsElement(\n refs.floating.current,\n elementReceivingFocus,\n );\n const focusedElementIsTrigger = elementContainsElement(\n refs.reference.current,\n elementReceivingFocus,\n );\n const popoverShouldClose =\n !focusedElementIsPopover && !focusedElementIsTrigger;\n if (showPopover && popoverShouldClose) setShowPopover(false);\n },\n };\n\n const closeButtonProps = {\n onClick: () => setShowPopover(false),\n type: 'button',\n };\n\n const contextValue: PopoverContextProps = {\n showPopover,\n floatingStyles,\n popoverTriggerProps,\n popoverContentProps,\n closeButtonProps,\n };\n\n return (\n <PopoverContext.Provider value={contextValue}>\n {children}\n </PopoverContext.Provider>\n );\n};\n\nexport type PopoverTriggerProps = {\n /** Knapp som skal brukes for å åpne Popover */\n children: React.ReactElement;\n};\n\nexport const PopoverTrigger: React.FC<PopoverTriggerProps> = ({ children }) => {\n const { popoverTriggerProps } = usePopoverContext();\n const child = React.Children.only(children) as React.ReactElement<any>;\n return cloneElement(child, popoverTriggerProps);\n};\n\nexport type PopoverCloseButtonProps = {\n /** En valgfri knapp som kan legges inn for å lukke Popover */\n children: React.ReactElement;\n};\n\nexport const PopoverCloseButton: React.FC<PopoverCloseButtonProps> = ({\n children,\n ...rest\n}) => {\n const { closeButtonProps } = usePopoverContext();\n return cloneElement(children, { ...closeButtonProps, ...rest });\n};\n\nexport type PopoverContentProps = {\n /**Innholdet til Popover */\n children: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n};\n\nexport const PopoverContent = React.forwardRef<\n HTMLDivElement,\n PopoverContentProps\n>(({ children, className, style }, ref: React.Ref<HTMLDivElement>) => {\n const { floatingStyles, popoverContentProps } = usePopoverContext();\n return (\n <Contrast\n className={classNames(className, 'eds-popover')}\n {...popoverContentProps}\n style={{ ...floatingStyles, ...popoverContentProps.style, ...style }}\n // @ts-expect-error correct type for floating cannot be set via useFloating\n ref={mergeRefs(popoverContentProps.ref, ref)}\n >\n {children}\n </Contrast>\n );\n});\n\ntype PopoverContextProps = {\n showPopover: boolean;\n floatingStyles: React.CSSProperties;\n closeButtonProps: Record<string, unknown>;\n popoverContentProps: {\n role: string;\n 'aria-modal': boolean;\n 'aria-hidden': boolean;\n ref: MutableRefObject<HTMLElement> | ((node: HTMLElement | null) => void);\n style: React.CSSProperties;\n onKeyDown: (event: React.KeyboardEvent) => void;\n onBlur: (event: React.FocusEvent) => void;\n };\n popoverTriggerProps: Record<string, unknown>;\n};\n\nconst PopoverContext = createContext<PopoverContextProps | undefined>(\n undefined,\n);\nconst usePopoverContext = () => {\n const context = useContext(PopoverContext);\n if (context == null) {\n throw Error('usePopoverContext must be used within <Popover/>');\n }\n return context;\n};\n\nconst useCustomState = (\n state?: boolean,\n setState?: React.Dispatch<React.SetStateAction<boolean>>,\n): [boolean, React.Dispatch<React.SetStateAction<boolean>>, boolean] => {\n const [internalState, setInternalState] = React.useState<boolean>(false);\n const controlled = state !== undefined && setState !== undefined;\n if (controlled) return [state, setState, controlled];\n return [internalState, setInternalState, controlled];\n};\n\nfunction elementContainsElement(\n parent: HTMLElement | null,\n child: HTMLElement,\n) {\n if (!parent) return false;\n return parent === child || parent.contains(child);\n}\n","import { warnAboutMissingStyles } from '@entur/utils';\nimport './index.scss';\n\nwarnAboutMissingStyles('tooltip');\n\nexport * from './Tooltip';\nexport * from './Popover';\nexport { Placement } from './utils';\n","import React, { cloneElement, useRef, useState } from 'react';\n\nimport classNames from 'classnames';\nimport {\n useFloating,\n autoUpdate,\n offset,\n flip,\n shift,\n arrow,\n limitShift,\n} from '@floating-ui/react-dom';\n\nimport { useRandomId } from '@entur/utils';\nimport { CloseIcon } from '@entur/icons';\nimport { IconButton } from '@entur/button';\nimport { space, borderRadiuses } from '@entur/tokens';\n\nimport { Placement, standardisePlacement } from './utils';\n\nimport './Tooltip.scss';\n\ntype Modifier = {\n name: string;\n enabled?: boolean;\n requires?: Array<string>;\n requiresIfExists?: Array<string>;\n options?: Record<string, unknown>;\n data?: Record<string, unknown>;\n [key: string]: any;\n};\n\ntype ChildEventListner = {\n 'aria-describedby'?: string;\n onFocus?: () => void;\n onBlur?: () => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: () => void;\n onKeyDown?: (e: React.KeyboardEvent) => void;\n onKeyUp?: (e: React.KeyboardEvent) => void;\n onClick?: (e: React.MouseEvent) => void;\n};\n\n/** @deprecated use variant=\"negative\" instead */\nconst error = 'error';\n\nexport type TooltipProps = {\n /** Plassering av tooltip-en */\n placement: Placement;\n /** Innholdet i tooltip-boksen */\n content: React.ReactNode;\n /** Elementet som skal ha tooltip-funksjonalitet */\n children: React.ReactElement;\n /** Om tooltip-en skal vises */\n isOpen?: boolean;\n /** Ekstra klassenavn for tooltip */\n className?: string;\n /** Åpner ikke tooltip ved hover-events\n * @default false\n */\n disableHoverListener?: boolean;\n /** Åpner ikke tooltip ved focus-events\n * @default false\n */\n disableFocusListener?: boolean;\n disableKeyboardListener?: boolean;\n disableClickListner?: boolean;\n /** Viser en lukkeknapp om man kontrollerer åpningen av Tooltip vha `isOpen`\n * @default true\n */\n showCloseButton?: boolean;\n /** Valideringsvariant for Tooltip */\n variant?: 'negative' | typeof error;\n /** @deprecated Ikke lenger støttet. Meld fra på #talk-designsystem hvis du trenger støtte for\n * overskrivinger av plasseringen til Tooltip!\n */\n popperModifiers?: Modifier[];\n [key: string]: any;\n};\n\nexport const Tooltip: React.FC<TooltipProps> = ({\n placement,\n content,\n children,\n className,\n isOpen = false,\n disableHoverListener = false,\n disableFocusListener = false,\n disableKeyboardListener = true,\n disableClickListner = true,\n showCloseButton = true,\n variant,\n style,\n ...rest\n}) => {\n const [showTooltip, setShowTooltip] = useState(isOpen);\n const tooltipArrowRef = useRef(null);\n const tooltipId = useRandomId('eds-tooltip');\n let hoverOpenTimer: ReturnType<typeof setTimeout>;\n let hoverCloseTimer: ReturnType<typeof setTimeout>;\n\n // calculations for floating-UI tooltip position\n const {\n refs,\n floatingStyles,\n middlewareData,\n placement: actualPlacement,\n } = useFloating({\n whileElementsMounted: (ref, float, update) =>\n autoUpdate(ref, float, update),\n placement: standardisePlacement(placement),\n middleware: [\n offset(space.extraSmall),\n flip(),\n shift({ padding: space.extraSmall, limiter: limitShift({ offset: 8 }) }),\n arrow({\n element: tooltipArrowRef,\n padding: borderRadiuses.medium,\n }),\n ],\n });\n\n const onMouseEnter = () => {\n clearTimeout(hoverCloseTimer);\n hoverOpenTimer = setTimeout(() => {\n setShowTooltip(true);\n }, 150);\n };\n\n const onMouseLeave = () => {\n clearTimeout(hoverOpenTimer);\n hoverCloseTimer = setTimeout(() => {\n setShowTooltip(false);\n }, 300);\n };\n\n React.useEffect(() => {\n return () => {\n clearTimeout(hoverOpenTimer);\n clearTimeout(hoverCloseTimer);\n };\n }, []);\n\n const referenceListenerProps: ChildEventListner = {\n 'aria-describedby': showTooltip ? tooltipId : undefined,\n // focusListner\n ...(!disableFocusListener && { onFocus: () => setShowTooltip(true) }),\n ...(!disableFocusListener && { onBlur: () => setShowTooltip(false) }),\n // hoverListner\n ...(!disableHoverListener && { onMouseEnter }),\n ...(!disableHoverListener && { onMouseLeave }),\n // keyboardListner\n ...(!disableKeyboardListener && {\n onKeyDown: e => {\n if (e.key === 'Escape') setShowTooltip(false);\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n setShowTooltip(!showTooltip);\n }\n },\n }),\n // clickListner\n ...(!disableClickListner && {\n onClick: () => setShowTooltip(!showTooltip),\n }),\n };\n\n return (\n <>\n {cloneElement(children, {\n ref: refs.setReference,\n ...referenceListenerProps,\n })}\n <div\n className={classNames(className, 'eds-tooltip', {\n 'eds-tooltip--negative': variant === error || variant === 'negative',\n })}\n ref={refs.setFloating}\n style={{\n ...floatingStyles,\n display: showTooltip && content ? undefined : 'none',\n ...style,\n }}\n role=\"tooltip\"\n id={tooltipId}\n onMouseEnter={!disableHoverListener ? onMouseEnter : undefined}\n onMouseLeave={!disableHoverListener ? onMouseLeave : undefined}\n {...rest}\n >\n {content}\n {isOpen && showCloseButton && (\n <IconButton\n className=\"eds-tooltip__close-button\"\n onClick={() => setShowTooltip(false)}\n type=\"button\"\n aria-label=\"Lukk tooltip\"\n >\n <CloseIcon aria-hidden=\"true\" />\n </IconButton>\n )}\n <div\n className={`eds-tooltip__arrow--${actualPlacement?.split('-')?.[0]}`}\n ref={tooltipArrowRef}\n style={{\n left: middlewareData.arrow?.x,\n top: middlewareData.arrow?.y,\n }}\n />\n </div>\n </>\n );\n};\n"],"names":["standardisePlacement","placement","PopoverContent","React","forwardRef","ref","children","className","style","_usePopoverContext3","usePopoverContext","floatingStyles","popoverContentProps","createElement","Contrast","_extends","classNames","mergeRefs","PopoverContext","createContext","undefined","context","useContext","Error","elementContainsElement","parent","child","contains","warnAboutMissingStyles","_ref","_ref$placement","_useCustomState","state","setState","_React$useState","useState","controlled","useCustomState","showPopover","setShowPopover","_useFloating","useFloating","whileElementsMounted","float","update","autoUpdate","middleware","offset","space","extraSmall","flip","shift","padding","limiter","limitShift","refs","useOnClickOutside","floating","reference","popoverTriggerProps","setReference","type","onClick","prev","role","setFloating","display","onKeyDown","event","key","onBlur","elementReceivingFocus","relatedTarget","getAttribute","focusedElementIsPopover","current","focusedElementIsTrigger","Provider","value","closeButtonProps","_ref3","rest","_objectWithoutPropertiesLoose","_excluded","_usePopoverContext2","cloneElement","_ref2","Children","only","_actualPlacement$spli","_middlewareData$arrow","_middlewareData$arrow2","hoverOpenTimer","hoverCloseTimer","content","_ref$isOpen","isOpen","_ref$disableHoverList","disableHoverListener","_ref$disableFocusList","disableFocusListener","_ref$disableKeyboardL","disableKeyboardListener","_ref$disableClickList","disableClickListner","_ref$showCloseButton","showCloseButton","variant","showTooltip","_useState","setShowTooltip","tooltipArrowRef","useRef","tooltipId","useRandomId","arrow","element","borderRadiuses","medium","middlewareData","actualPlacement","onMouseEnter","clearTimeout","setTimeout","onMouseLeave","useEffect","referenceListenerProps","onFocus","e","preventDefault","Fragment","id","IconButton","CloseIcon","split","left","x","top","y"],"mappings":"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"}
@@ -1,9 +1,10 @@
1
- import { useRandomId, useOnClickOutside, warnAboutMissingStyles } from '@entur/utils';
2
- import React, { useState, cloneElement, createContext, useContext } from 'react';
3
- import { Manager, Reference, Popper, usePopper } from 'react-popper';
1
+ import { useRandomId, useOnClickOutside, mergeRefs, warnAboutMissingStyles } from '@entur/utils';
2
+ import React, { useState, useRef, cloneElement, createContext, useContext } from 'react';
4
3
  import classNames from 'classnames';
4
+ import { useFloating, autoUpdate, offset, flip, shift, limitShift, arrow } from '@floating-ui/react-dom';
5
5
  import { CloseIcon } from '@entur/icons';
6
6
  import { IconButton } from '@entur/button';
7
+ import { space, borderRadiuses } from '@entur/tokens';
7
8
  import { Contrast } from '@entur/layout';
8
9
 
9
10
  function _extends() {
@@ -33,10 +34,26 @@ function _objectWithoutPropertiesLoose(source, excluded) {
33
34
  return target;
34
35
  }
35
36
 
36
- var _excluded$1 = ["placement", "content", "children", "className", "isOpen", "disableHoverListener", "disableFocusListener", "disableKeyboardListener", "disableClickListner", "showCloseButton", "variant", "popperModifiers"];
37
+ function standardisePlacement(placement) {
38
+ switch (placement) {
39
+ case 'top-left':
40
+ return 'top-start';
41
+ case 'top-right':
42
+ return 'top-end';
43
+ case 'bottom-left':
44
+ return 'bottom-start';
45
+ case 'bottom-right':
46
+ return 'bottom-end';
47
+ default:
48
+ return placement;
49
+ }
50
+ }
51
+
52
+ var _excluded$1 = ["placement", "content", "children", "className", "isOpen", "disableHoverListener", "disableFocusListener", "disableKeyboardListener", "disableClickListner", "showCloseButton", "variant", "style"];
37
53
  /** @deprecated use variant="negative" instead */
38
54
  var error = 'error';
39
55
  var Tooltip = function Tooltip(_ref) {
56
+ var _actualPlacement$spli, _middlewareData$arrow, _middlewareData$arrow2;
40
57
  var placement = _ref.placement,
41
58
  content = _ref.content,
42
59
  children = _ref.children,
@@ -54,134 +71,114 @@ var Tooltip = function Tooltip(_ref) {
54
71
  _ref$showCloseButton = _ref.showCloseButton,
55
72
  showCloseButton = _ref$showCloseButton === void 0 ? true : _ref$showCloseButton,
56
73
  variant = _ref.variant,
57
- _ref$popperModifiers = _ref.popperModifiers,
58
- popperModifiers = _ref$popperModifiers === void 0 ? [{
59
- name: 'offset',
60
- options: {
61
- offset: [0, 10]
62
- }
63
- }] : _ref$popperModifiers,
74
+ style = _ref.style,
64
75
  rest = _objectWithoutPropertiesLoose(_ref, _excluded$1);
65
- var _useState = useState(isOpen || false),
76
+ var _useState = useState(isOpen),
66
77
  showTooltip = _useState[0],
67
78
  setShowTooltip = _useState[1];
68
- var hoverTimer;
69
- var handleOpen = function handleOpen(event) {
70
- event.persist();
71
- hoverTimer = setTimeout(function () {
79
+ var tooltipArrowRef = useRef(null);
80
+ var tooltipId = useRandomId('eds-tooltip');
81
+ var hoverOpenTimer;
82
+ var hoverCloseTimer;
83
+ // calculations for floating-UI tooltip position
84
+ var _useFloating = useFloating({
85
+ whileElementsMounted: function whileElementsMounted(ref, _float, update) {
86
+ return autoUpdate(ref, _float, update);
87
+ },
88
+ placement: standardisePlacement(placement),
89
+ middleware: [offset(space.extraSmall), flip(), shift({
90
+ padding: space.extraSmall,
91
+ limiter: limitShift({
92
+ offset: 8
93
+ })
94
+ }), arrow({
95
+ element: tooltipArrowRef,
96
+ padding: borderRadiuses.medium
97
+ })]
98
+ }),
99
+ refs = _useFloating.refs,
100
+ floatingStyles = _useFloating.floatingStyles,
101
+ middlewareData = _useFloating.middlewareData,
102
+ actualPlacement = _useFloating.placement;
103
+ var onMouseEnter = function onMouseEnter() {
104
+ clearTimeout(hoverCloseTimer);
105
+ hoverOpenTimer = setTimeout(function () {
72
106
  setShowTooltip(true);
73
107
  }, 150);
74
108
  };
75
- var onMouseExit = function onMouseExit() {
76
- setShowTooltip(false);
77
- clearTimeout(hoverTimer);
109
+ var onMouseLeave = function onMouseLeave() {
110
+ clearTimeout(hoverOpenTimer);
111
+ hoverCloseTimer = setTimeout(function () {
112
+ setShowTooltip(false);
113
+ }, 300);
78
114
  };
79
115
  React.useEffect(function () {
80
116
  return function () {
81
- clearTimeout(hoverTimer);
117
+ clearTimeout(hoverOpenTimer);
118
+ clearTimeout(hoverCloseTimer);
82
119
  };
83
- });
84
- var tooltipId = useRandomId('eds-tooltip');
85
- React.useEffect(function () {
86
- setShowTooltip(isOpen);
87
- }, [isOpen]);
88
- React.useEffect(function () {
89
- if (!content) {
90
- setShowTooltip(false);
91
- }
92
- }, [content]);
93
- var popperPlacement = placement;
94
- if (placement.includes('-')) {
95
- if (placement.includes('right')) {
96
- popperPlacement = placement.replace('right', 'end');
97
- }
98
- if (placement.includes('left')) {
99
- popperPlacement = placement.replace('left', 'start');
100
- }
101
- }
102
- var childProps = {};
103
- childProps['aria-describedby'] = showTooltip ? tooltipId : undefined;
104
- if (!disableFocusListener) {
105
- childProps.onFocus = function () {
120
+ }, []);
121
+ var referenceListenerProps = _extends({
122
+ 'aria-describedby': showTooltip ? tooltipId : undefined
123
+ }, !disableFocusListener && {
124
+ onFocus: function onFocus() {
106
125
  return setShowTooltip(true);
107
- };
108
- childProps.onBlur = function () {
126
+ }
127
+ }, !disableFocusListener && {
128
+ onBlur: function onBlur() {
109
129
  return setShowTooltip(false);
110
- };
111
- }
112
- if (!disableHoverListener) {
113
- childProps.onMouseEnter = function (e) {
114
- return handleOpen(e);
115
- };
116
- childProps.onMouseLeave = function () {
117
- return onMouseExit();
118
- };
119
- }
120
- if (!disableKeyboardListener) {
121
- childProps.onKeyDown = function (e) {
130
+ }
131
+ }, !disableHoverListener && {
132
+ onMouseEnter: onMouseEnter
133
+ }, !disableHoverListener && {
134
+ onMouseLeave: onMouseLeave
135
+ }, !disableKeyboardListener && {
136
+ onKeyDown: function onKeyDown(e) {
122
137
  if (e.key === 'Escape') setShowTooltip(false);
123
138
  if (e.key === ' ' || e.key === 'Enter') {
124
139
  e.preventDefault();
125
140
  setShowTooltip(!showTooltip);
126
141
  }
127
- };
128
- }
129
- if (!disableClickListner) {
130
- childProps.onClick = function () {
142
+ }
143
+ }, !disableClickListner && {
144
+ onClick: function onClick() {
131
145
  return setShowTooltip(!showTooltip);
132
- };
133
- }
134
- return React.createElement(Manager, null, React.createElement(Reference, null, function (_ref2) {
135
- var ref = _ref2.ref;
136
- return cloneElement(children, _extends({
137
- ref: ref
138
- }, childProps));
139
- }), showTooltip && React.createElement(Popper, {
140
- modifiers: [{
141
- name: 'arrow',
142
- enabled: false
143
- }].concat(popperModifiers),
144
- placement: popperPlacement
145
- }, function (_ref3) {
146
- var ref = _ref3.ref,
147
- style = _ref3.style,
148
- popperPlacement = _ref3.placement;
149
- return React.createElement("div", _extends({
150
- className: classNames('eds-tooltip', className, "eds-tooltip--" + popperPlacement, {
151
- 'eds-tooltip--negative': variant === error || variant === 'negative'
152
- }),
153
- ref: ref,
154
- style: style,
155
- role: "tooltip",
156
- id: tooltipId,
157
- "data-placement": popperPlacement
158
- }, rest), content, isOpen && showCloseButton && React.createElement(IconButton, {
159
- className: "eds-tooltip__close-button",
160
- onClick: function onClick() {
161
- return setShowTooltip(false);
162
- },
163
- type: "button"
164
- }, React.createElement(CloseIcon, null)));
165
- }));
146
+ }
147
+ });
148
+ return React.createElement(React.Fragment, null, cloneElement(children, _extends({
149
+ ref: refs.setReference
150
+ }, referenceListenerProps)), React.createElement("div", _extends({
151
+ className: classNames(className, 'eds-tooltip', {
152
+ 'eds-tooltip--negative': variant === error || variant === 'negative'
153
+ }),
154
+ ref: refs.setFloating,
155
+ style: _extends({}, floatingStyles, {
156
+ display: showTooltip && content ? undefined : 'none'
157
+ }, style),
158
+ role: "tooltip",
159
+ id: tooltipId,
160
+ onMouseEnter: !disableHoverListener ? onMouseEnter : undefined,
161
+ onMouseLeave: !disableHoverListener ? onMouseLeave : undefined
162
+ }, rest), content, isOpen && showCloseButton && React.createElement(IconButton, {
163
+ className: "eds-tooltip__close-button",
164
+ onClick: function onClick() {
165
+ return setShowTooltip(false);
166
+ },
167
+ type: "button",
168
+ "aria-label": "Lukk tooltip"
169
+ }, React.createElement(CloseIcon, {
170
+ "aria-hidden": "true"
171
+ })), React.createElement("div", {
172
+ className: "eds-tooltip__arrow--" + (actualPlacement == null ? void 0 : (_actualPlacement$spli = actualPlacement.split('-')) == null ? void 0 : _actualPlacement$spli[0]),
173
+ ref: tooltipArrowRef,
174
+ style: {
175
+ left: (_middlewareData$arrow = middlewareData.arrow) == null ? void 0 : _middlewareData$arrow.x,
176
+ top: (_middlewareData$arrow2 = middlewareData.arrow) == null ? void 0 : _middlewareData$arrow2.y
177
+ }
178
+ })));
166
179
  };
167
180
 
168
181
  var _excluded = ["children"];
169
- var PopoverContext = /*#__PURE__*/createContext(undefined);
170
- var usePopoverContext = function usePopoverContext() {
171
- var context = useContext(PopoverContext);
172
- if (context == null) {
173
- throw Error('usePopoverContext must be used within <Popover/>');
174
- }
175
- return context;
176
- };
177
- var useCustomState = function useCustomState(state, setState) {
178
- var _React$useState = React.useState(false),
179
- internalState = _React$useState[0],
180
- setInternalState = _React$useState[1];
181
- var controlled = state !== undefined && setState !== undefined;
182
- if (controlled) return [state, setState, controlled];
183
- return [internalState, setInternalState, controlled];
184
- };
185
182
  var Popover = function Popover(_ref) {
186
183
  var children = _ref.children,
187
184
  _ref$placement = _ref.placement,
@@ -192,86 +189,69 @@ var Popover = function Popover(_ref) {
192
189
  showPopover = _useCustomState[0],
193
190
  setShowPopover = _useCustomState[1],
194
191
  controlled = _useCustomState[2];
195
- var triggerElement = React.useRef(null);
196
- var contentElement = React.useRef(null);
197
- var _usePopper = usePopper(triggerElement.current, contentElement.current, {
198
- modifiers: [{
199
- name: 'arrow',
200
- enabled: false
201
- }, {
202
- name: 'offset',
203
- options: {
204
- offset: [0, 8]
205
- }
206
- }],
207
- placement: placement
192
+ // calculations for floating-UI popover position
193
+ var _useFloating = useFloating({
194
+ whileElementsMounted: function whileElementsMounted(ref, _float, update) {
195
+ return autoUpdate(ref, _float, update);
196
+ },
197
+ placement: standardisePlacement(placement),
198
+ middleware: [offset(space.extraSmall), flip(), shift({
199
+ padding: space.extraSmall,
200
+ limiter: limitShift({
201
+ offset: 8
202
+ })
203
+ })]
208
204
  }),
209
- styles = _usePopper.styles,
210
- attributes = _usePopper.attributes,
211
- forceUpdate = _usePopper.forceUpdate;
212
- React.useEffect(function () {
213
- if (forceUpdate) {
214
- forceUpdate();
215
- }
216
- }, [showPopover, forceUpdate]);
217
- var triggerProps = React.useCallback(function () {
218
- var buttonProps = {
219
- 'aria-haspopup': 'dialog',
220
- 'aria-expanded': showPopover,
221
- ref: triggerElement,
222
- type: 'button'
223
- };
224
- var buttonOnClick = {
225
- onClick: function onClick(e) {
226
- e.preventDefault();
227
- setShowPopover(function (prev) {
228
- return !prev;
229
- });
230
- }
231
- };
232
- return controlled ? buttonProps : _extends({}, buttonProps, buttonOnClick);
233
- }, [triggerElement, showPopover, setShowPopover, controlled]);
234
- useOnClickOutside([contentElement, triggerElement], function () {
205
+ refs = _useFloating.refs,
206
+ floatingStyles = _useFloating.floatingStyles;
207
+ useOnClickOutside([refs.floating, refs.reference], function () {
235
208
  return setShowPopover(false);
236
209
  });
210
+ var popoverTriggerProps = _extends({
211
+ 'aria-haspopup': 'dialog',
212
+ 'aria-expanded': showPopover,
213
+ ref: refs.setReference,
214
+ type: 'button'
215
+ }, !controlled && {
216
+ onClick: function onClick() {
217
+ return setShowPopover(function (prev) {
218
+ return !prev;
219
+ });
220
+ }
221
+ });
222
+ var popoverContentProps = {
223
+ role: 'dialog',
224
+ 'aria-modal': false,
225
+ 'aria-hidden': !showPopover,
226
+ ref: refs.setFloating,
227
+ style: _extends({}, !showPopover && {
228
+ display: 'none'
229
+ }),
230
+ onKeyDown: function onKeyDown(event) {
231
+ if (event.key === 'Escape') setShowPopover(false);
232
+ },
233
+ onBlur: function onBlur(event) {
234
+ var elementReceivingFocus = event.relatedTarget;
235
+ // The check for 'tabindex=-1' is a special case for focus handling in Docz
236
+ if (!elementReceivingFocus || elementReceivingFocus.getAttribute('tabindex') === '-1') return;
237
+ var focusedElementIsPopover = elementContainsElement(refs.floating.current, elementReceivingFocus);
238
+ var focusedElementIsTrigger = elementContainsElement(refs.reference.current, elementReceivingFocus);
239
+ var popoverShouldClose = !focusedElementIsPopover && !focusedElementIsTrigger;
240
+ if (showPopover && popoverShouldClose) setShowPopover(false);
241
+ }
242
+ };
237
243
  var closeButtonProps = {
238
- onClick: function onClick(e) {
239
- e.preventDefault();
240
- setShowPopover(false);
244
+ onClick: function onClick() {
245
+ return setShowPopover(false);
241
246
  },
242
247
  type: 'button'
243
248
  };
244
- var popoverContentProps = React.useCallback(function () {
245
- var contentProps = {
246
- role: 'dialog',
247
- 'aria-modal': 'false',
248
- ref: contentElement,
249
- onKeyDown: function onKeyDown(event) {
250
- if (event.key === 'Escape') {
251
- showPopover && setShowPopover(false);
252
- }
253
- },
254
- onBlur: function onBlur(event) {
255
- var elementReceivingFocus = event.relatedTarget;
256
- // The check for 'tabindex=-1' is a special case for focus handling in Docz
257
- if (!elementReceivingFocus || elementReceivingFocus.getAttribute('tabindex') === '-1') return;
258
- var focusElementIsPopover = elementContainsElement(contentElement.current, elementReceivingFocus);
259
- var focusElementIsTrigger = elementContainsElement(triggerElement.current, elementReceivingFocus);
260
- var isValidBlur = !focusElementIsPopover && !focusElementIsTrigger;
261
- if (showPopover && isValidBlur) setShowPopover(false);
262
- }
263
- };
264
- return contentProps;
265
- }, [contentElement, showPopover, setShowPopover]);
266
249
  var contextValue = {
267
250
  showPopover: showPopover,
268
- triggerElement: triggerElement,
269
- contentElement: contentElement,
270
- styles: styles,
271
- attributes: attributes,
251
+ floatingStyles: floatingStyles,
252
+ popoverTriggerProps: popoverTriggerProps,
272
253
  popoverContentProps: popoverContentProps,
273
- closeButtonProps: closeButtonProps,
274
- triggerProps: triggerProps
254
+ closeButtonProps: closeButtonProps
275
255
  };
276
256
  return React.createElement(PopoverContext.Provider, {
277
257
  value: contextValue
@@ -280,9 +260,9 @@ var Popover = function Popover(_ref) {
280
260
  var PopoverTrigger = function PopoverTrigger(_ref2) {
281
261
  var children = _ref2.children;
282
262
  var _usePopoverContext = usePopoverContext(),
283
- triggerProps = _usePopoverContext.triggerProps;
263
+ popoverTriggerProps = _usePopoverContext.popoverTriggerProps;
284
264
  var child = React.Children.only(children);
285
- return cloneElement(child, triggerProps());
265
+ return cloneElement(child, popoverTriggerProps);
286
266
  };
287
267
  var PopoverCloseButton = function PopoverCloseButton(_ref3) {
288
268
  var children = _ref3.children,
@@ -292,23 +272,36 @@ var PopoverCloseButton = function PopoverCloseButton(_ref3) {
292
272
  return cloneElement(children, _extends({}, closeButtonProps, rest));
293
273
  };
294
274
  var PopoverContent = /*#__PURE__*/React.forwardRef(function (_ref4, ref) {
295
- var children = _ref4.children;
275
+ var children = _ref4.children,
276
+ className = _ref4.className,
277
+ style = _ref4.style;
296
278
  var _usePopoverContext3 = usePopoverContext(),
297
- showPopover = _usePopoverContext3.showPopover,
298
- attributes = _usePopoverContext3.attributes,
299
- styles = _usePopoverContext3.styles,
279
+ floatingStyles = _usePopoverContext3.floatingStyles,
300
280
  popoverContentProps = _usePopoverContext3.popoverContentProps;
301
- var props = popoverContentProps({
302
- ref: ref
303
- });
304
281
  return React.createElement(Contrast, _extends({
305
- className: classNames('eds-popover', {
306
- 'eds-popover--hidden': !showPopover
307
- }, 'eds-contrast'),
308
- style: styles.popper,
309
- "aria-hidden": !showPopover
310
- }, attributes.styles, props), children);
282
+ className: classNames(className, 'eds-popover')
283
+ }, popoverContentProps, {
284
+ style: _extends({}, floatingStyles, popoverContentProps.style, style),
285
+ // @ts-expect-error correct type for floating cannot be set via useFloating
286
+ ref: mergeRefs(popoverContentProps.ref, ref)
287
+ }), children);
311
288
  });
289
+ var PopoverContext = /*#__PURE__*/createContext(undefined);
290
+ var usePopoverContext = function usePopoverContext() {
291
+ var context = useContext(PopoverContext);
292
+ if (context == null) {
293
+ throw Error('usePopoverContext must be used within <Popover/>');
294
+ }
295
+ return context;
296
+ };
297
+ var useCustomState = function useCustomState(state, setState) {
298
+ var _React$useState = React.useState(false),
299
+ internalState = _React$useState[0],
300
+ setInternalState = _React$useState[1];
301
+ var controlled = state !== undefined && setState !== undefined;
302
+ if (controlled) return [state, setState, controlled];
303
+ return [internalState, setInternalState, controlled];
304
+ };
312
305
  function elementContainsElement(parent, child) {
313
306
  if (!parent) return false;
314
307
  return parent === child || parent.contains(child);