{"version":3,"file":"Popover.cjs","sources":["../../../../src/components/popover/Popover.tsx"],"sourcesContent":["import {\n    FloatingFocusManager,\n    FloatingPortal,\n    type ReferenceElement,\n    type VirtualElement,\n    autoUpdate,\n    flip,\n    offset,\n    shift,\n    useClick,\n    useDismiss,\n    useFloating,\n    useFocus,\n    useHover,\n    useInteractions,\n    useMergeRefs,\n    useRole,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport * as React from \"react\";\nimport { getThemeAndSize } from \"../../utilities/getThemeAndSize.js\";\nimport type { PopoverOptions } from \"./types.js\";\n\nconst usePopover = ({\n    open: _open,\n    onOpenChange: _onOpenChange,\n    placement = \"bottom-start\",\n    strategy = \"absolute\",\n    modal = true,\n    offset: _offset = 4,\n    positionReference,\n    hoverOptions,\n    focusOptions,\n    clickOptions,\n    roleOptions,\n    dismissOptions,\n}: PopoverOptions) => {\n    const [uncontrolledOpen, setUncontrolledOpen] = React.useState(_open);\n\n    const open = _open ?? uncontrolledOpen;\n    const onOpenChange = _onOpenChange ?? setUncontrolledOpen;\n\n    const data = useFloating({\n        open,\n        onOpenChange,\n        placement,\n        strategy,\n        middleware: [\n            offset(_offset),\n            flip({ padding: 5, fallbackPlacements: [\"bottom\", \"top\"] }),\n            shift({ padding: 12 }),\n        ],\n        whileElementsMounted: autoUpdate,\n    });\n\n    const context = data.context;\n\n    const click = useClick(context, {\n        enabled: false,\n        ...clickOptions,\n    });\n    const hover = useHover(context, { enabled: false, ...hoverOptions });\n    const focus = useFocus(context, { enabled: false, ...focusOptions });\n    const dismiss = useDismiss(context, dismissOptions);\n    const role = useRole(context, roleOptions);\n\n    const interactions = useInteractions([click, dismiss, focus, hover, role]);\n\n    React.useLayoutEffect(() => {\n        if (positionReference) {\n            data.refs.setPositionReference(positionReference?.current);\n        }\n    }, [positionReference, data.refs]);\n\n    return React.useMemo(\n        () => ({\n            open,\n            onOpenChange,\n            modal,\n            ...interactions,\n            ...data,\n        }),\n        [open, onOpenChange, modal, interactions, data],\n    );\n};\n\ntype PopoverContextType = ReturnType<typeof usePopover> | null;\n\nconst PopoverContext = React.createContext<PopoverContextType>(null);\n\nconst usePopoverContext = () => {\n    const context = React.useContext(PopoverContext);\n\n    if (context == null) {\n        throw new Error(\n            \"Popover komponenter må brukes innenfor en <Popover /> komponent\",\n        );\n    }\n\n    return context;\n};\n\nexport const Popover = ({\n    children,\n    ...restOptions\n}: {\n    children: React.ReactNode;\n} & PopoverOptions) => {\n    const popover = usePopover({ ...restOptions });\n    return (\n        <PopoverContext.Provider value={popover}>\n            {children}\n        </PopoverContext.Provider>\n    );\n};\n\ninterface PopoverTriggerProps {\n    children: React.ReactNode;\n    /**\n     * Rendrer komponenten som child-elementet sitt, og slår sammen egenskaper og props.\n     *\n     * Default er `false`.\n     *\n     * @example\n     * ```tsx\n     * <Component asChild foo=\"bar\">\n     *    <Child baz=\"qux\" />\n     * </Component>\n     *\n     * // Rendrer følgende:\n     * <Child foo=\"bar\" baz=\"qux\" />\n     * ```\n     */\n    asChild?: boolean;\n}\n\nconst PopoverTrigger = React.forwardRef<\n    HTMLElement,\n    React.HTMLProps<HTMLElement> & PopoverTriggerProps\n>(function PopoverTrigger({ children, asChild = false, ...props }, propRef) {\n    const { refs, getReferenceProps, open, onOpenChange } = usePopoverContext();\n    const childrenRef = (children as any).ref;\n    const ref = useMergeRefs([refs.setReference, propRef, childrenRef]);\n\n    if (asChild && React.isValidElement(children)) {\n        return React.cloneElement(\n            children,\n            getReferenceProps({\n                ref,\n                ...props,\n                ...children.props,\n            }),\n        );\n    }\n\n    return (\n        <button\n            ref={ref}\n            onClick={() => onOpenChange?.(!open)}\n            aria-expanded={open}\n            {...getReferenceProps({\n                ...props,\n                className: clsx(\"jkl-popover-trigger\", props.className),\n            })}\n        >\n            {children}\n        </button>\n    );\n});\n\ninterface PopoverContentProps {\n    /**\n     * Padding rundt innholdet i popoveren.\n     *\n     * Default er `0`.\n     */\n    padding?: 0 | 8 | 16 | 24;\n    /**\n     *\n     * Angir hvilket element som skal motta fokus ved åpning.\n     * Kan være en tabbar index eller en referanse til et element.\"\n     *\n     * Default er `0`, som betyr at det første fokuserbare elementet i popoveren får fokus.\n     * @see https://floating-ui.com/docs/FloatingFocusManager#initialfocus\n     */\n    initialFocus?: number | React.RefObject<HTMLElement>;\n    /**\n     * Angir om fokus skal returneres til triggeren når popoveren lukkes.\n     *\n     * Default er `true`.\n     * @see https://floating-ui.com/docs/FloatingFocusManager#returnfocus\n     */\n    returnFocus?: boolean;\n}\n\n// Er popover-elementet posisjonert i forhold til et annet element enn triggeren?\nconst isCustomPositioned = (\n    referenceElement: ReferenceElement,\n): referenceElement is VirtualElement => {\n    if (!referenceElement) return false;\n\n    return \"contextElement\" in referenceElement;\n};\n\nconst PopoverContent = React.forwardRef<\n    HTMLDivElement,\n    React.HTMLProps<HTMLDivElement> & PopoverContentProps\n>(function PopoverContent(\n    {\n        style,\n        className,\n        padding = 0,\n        initialFocus = 0,\n        returnFocus = true,\n        ...props\n    },\n    propRef,\n) {\n    const { context, modal, refs, open, floatingStyles, getFloatingProps } =\n        usePopoverContext();\n    const ref = useMergeRefs([refs.setFloating, propRef]);\n\n    const referenceElement = refs.reference.current as ReferenceElement;\n\n    const { theme, size } = isCustomPositioned(referenceElement)\n        ? getThemeAndSize(referenceElement.contextElement)\n        : getThemeAndSize(referenceElement);\n\n    const floatingPortalRef = React.useRef<HTMLElement | null>(null);\n\n    // TODO: Løser et problem hvor nestede portaler ikke \"fester\" seg til det nærmeste portal-elementet. Fjernes når alle komponenter som rendres i en portal tar i bruk popover komponenten da den håndterer dette internt. Issue: https://github.com/fremtind/jokul/issues/4356\n    React.useEffect(() => {\n        floatingPortalRef.current =\n            context.elements.domReference?.closest<HTMLElement>(\n                \"[data-portal]\",\n            ) || document.body;\n    }, [context.elements.domReference]);\n\n    if (!open) return null;\n\n    return (\n        <FloatingPortal root={floatingPortalRef.current}>\n            <FloatingFocusManager\n                context={context}\n                modal={modal}\n                initialFocus={initialFocus}\n                returnFocus={returnFocus}\n            >\n                <div\n                    data-theme={theme}\n                    data-size={size}\n                    className={clsx(\"jkl jkl-popover\", className)}\n                    ref={ref}\n                    style={\n                        {\n                            ...style,\n                            ...floatingStyles,\n                            \"--popover-padding\": `var(--jkl-spacing-${padding})`,\n                        } as React.CSSProperties\n                    }\n                    {...getFloatingProps(props)}\n                >\n                    {props.children}\n                </div>\n            </FloatingFocusManager>\n        </FloatingPortal>\n    );\n});\n\nPopover.Trigger = PopoverTrigger;\nPopover.Content = PopoverContent;\n\nexport default Popover;\n"],"names":["PopoverContext","React","createContext","usePopoverContext","context","useContext","Error","Popover","children","restOptions","popover","open","_open","onOpenChange","_onOpenChange","placement","strategy","modal","offset","_offset","positionReference","hoverOptions","focusOptions","clickOptions","roleOptions","dismissOptions","uncontrolledOpen","setUncontrolledOpen","useState","data","useFloating","middleware","flip","padding","fallbackPlacements","shift","whileElementsMounted","autoUpdate","click","useClick","enabled","hover","useHover","focus","useFocus","dismiss","useDismiss","role","useRole","interactions","useInteractions","useLayoutEffect","refs","setPositionReference","current","useMemo","usePopover","Provider","value","PopoverTrigger","forwardRef","asChild","props","propRef","getReferenceProps","childrenRef","ref","useMergeRefs","setReference","isValidElement","cloneElement","jsx","onClick","className","clsx","PopoverContent","style","initialFocus","returnFocus","floatingStyles","getFloatingProps","setFloating","referenceElement","reference","theme","size","getThemeAndSize","contextElement","floatingPortalRef","useRef","useEffect","elements","domReference","closest","document","body","FloatingPortal","root","FloatingFocusManager","Trigger","Content"],"mappings":"kjBAwFMA,EAAiBC,EAAMC,cAAkC,MAEzDC,EAAoB,KACtB,MAAMC,EAAUH,EAAMI,WAAWL,GAEjC,GAAe,MAAXI,EACA,MAAM,IAAIE,MACN,mEAIR,OAAOF,GAGEG,EAAU,EACnBC,SAAAA,KACGC,MAIH,MAAMC,EArFS,GACfC,KAAMC,EACNC,aAAcC,EACdC,UAAAA,EAAY,eACZC,SAAAA,EAAW,WACXC,MAAAA,GAAQ,EACRC,OAAQC,EAAU,EAClBC,kBAAAA,EACAC,aAAAA,EACAC,aAAAA,EACAC,aAAAA,EACAC,YAAAA,EACAC,eAAAA,MAEA,MAAOC,EAAkBC,GAAuB1B,EAAM2B,SAAShB,GAEzDD,EAAOC,GAASc,EAChBb,EAAeC,GAAiBa,EAEhCE,EAAOC,EAAAA,YAAY,CACrBnB,KAAAA,EACAE,aAAAA,EACAE,UAAAA,EACAC,SAAAA,EACAe,WAAY,CACRb,EAAAA,OAAOC,GACPa,EAAAA,KAAK,CAAEC,QAAS,EAAGC,mBAAoB,CAAC,SAAU,SAClDC,QAAM,CAAEF,QAAS,MAErBG,qBAAsBC,EAAAA,aAGpBjC,EAAUyB,EAAKzB,QAEfkC,EAAQC,EAAAA,SAASnC,EAAS,CAC5BoC,SAAS,KACNjB,IAEDkB,EAAQC,EAAAA,SAAStC,EAAS,CAAEoC,SAAS,KAAUnB,IAC/CsB,EAAQC,EAAAA,SAASxC,EAAS,CAAEoC,SAAS,KAAUlB,IAC/CuB,EAAUC,EAAAA,WAAW1C,EAASqB,GAC9BsB,EAAOC,EAAAA,QAAQ5C,EAASoB,GAExByB,EAAeC,EAAAA,gBAAgB,CAACZ,EAAOO,EAASF,EAAOF,EAAOM,IAEpE9C,OAAAA,EAAMkD,gBAAgB,KACd/B,GACAS,EAAKuB,KAAKC,qBAAqBjC,GAAmBkC,UAEvD,CAAClC,EAAmBS,EAAKuB,OAErBnD,EAAMsD,QACT,MACI5C,KAAAA,EACAE,aAAAA,EACAI,MAAAA,KACGgC,KACApB,IAEP,CAAClB,EAAME,EAAcI,EAAOgC,EAAcpB,KA0B9B2B,CAAW,IAAK/C,IAChC,aACKT,EAAeyD,SAAf,CAAwBC,MAAOhD,EAC3BF,SAAAA,KAyBPmD,EAAiB1D,EAAM2D,WAG3B,UAA0BpD,SAAAA,EAAUqD,QAAAA,GAAU,KAAUC,GAASC,GAC/D,MAAQX,KAAAA,EAAMY,kBAAAA,EAAmBrD,KAAAA,EAAME,aAAAA,GAAiBV,IAClD8D,EAAezD,EAAiB0D,IAChCA,EAAMC,EAAAA,aAAa,CAACf,EAAKgB,aAAcL,EAASE,IAEtD,OAAIJ,GAAW5D,EAAMoE,eAAe7D,GACzBP,EAAMqE,aACT9D,EACAwD,EAAkB,CACdE,IAAAA,KACGJ,KACAtD,EAASsD,SAMpBS,EAAAA,IAAC,SAAA,CACGL,IAAAA,EACAM,QAAS,IAAM3D,KAAgBF,GAC/B,gBAAeA,KACXqD,EAAkB,IACfF,EACHW,UAAWC,EAAAA,KAAK,sBAAuBZ,EAAMW,aAGhDjE,SAAAA,GAGb,GAoCMmE,EAAiB1E,EAAM2D,WAG3B,UAEMgB,MAAAA,EACAH,UAAAA,EACAxC,QAAAA,EAAU,EACV4C,aAAAA,EAAe,EACfC,YAAAA,GAAc,KACXhB,GAEPC,GAEA,MAAQ3D,QAAAA,EAASa,MAAAA,EAAOmC,KAAAA,EAAMzC,KAAAA,EAAMoE,eAAAA,EAAgBC,iBAAAA,GAChD7E,IACE+D,EAAMC,EAAAA,aAAa,CAACf,EAAK6B,YAAalB,IAEtCmB,EAAmB9B,EAAK+B,UAAU7B,SAEhC8B,MAAAA,EAAOC,KAAAA,IA3BfH,EA2B2CA,IAvBpC,mBAAoBA,EAwBrBI,EAAAA,gBAAgBJ,EAAiBK,gBACjCD,EAAAA,gBAAgBJ,GAEhBM,EAAoBvF,EAAMwF,OAA2B,MA/B3DP,MAyCA,OAPAjF,EAAMyF,UAAU,KACZF,EAAkBlC,QACdlD,EAAQuF,SAASC,cAAcC,QAC3B,kBACCC,SAASC,MACnB,CAAC3F,EAAQuF,SAASC,eAEhBjF,EAGD4D,EAAAA,IAACyB,EAAAA,eAAA,CAAeC,KAAMT,EAAkBlC,QACpC9C,SAAA+D,EAAAA,IAAC2B,EAAAA,qBAAA,CACG9F,QAAAA,EACAa,MAAAA,EACA4D,aAAAA,EACAC,YAAAA,EAEAtE,SAAA+D,EAAAA,IAAC,MAAA,CACG,aAAYa,EACZ,YAAWC,EACXZ,UAAWC,EAAAA,KAAK,kBAAmBD,GACnCP,IAAAA,EACAU,MACI,IACOA,KACAG,EACH,oBAAqB,qBAAqB9C,SAG9C+C,EAAiBlB,GAEpBtD,SAAAsD,EAAMtD,eAxBL,IA6BtB,GAEAD,EAAQ4F,QAAUxC,EAClBpD,EAAQ6F,QAAUzB"}