@fremtind/jokul 0.29.0 → 0.30.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.
- package/build/build-stats.html +1 -1
- package/build/cjs/components/menu/Menu.cjs +1 -1
- package/build/cjs/components/menu/Menu.cjs.map +1 -1
- package/build/cjs/components/tooltip/Tooltip.cjs +1 -1
- package/build/cjs/components/tooltip/Tooltip.cjs.map +1 -1
- package/build/cjs/components/tooltip/Tooltip.d.cts +1 -1
- package/build/cjs/components/tooltip/TooltipContent.cjs +1 -1
- package/build/cjs/components/tooltip/TooltipContent.cjs.map +1 -1
- package/build/cjs/components/tooltip/TooltipTrigger.cjs +1 -1
- package/build/cjs/components/tooltip/TooltipTrigger.cjs.map +1 -1
- package/build/es/components/menu/Menu.js +1 -1
- package/build/es/components/menu/Menu.js.map +1 -1
- package/build/es/components/tooltip/Tooltip.d.ts +1 -1
- package/build/es/components/tooltip/Tooltip.js +1 -1
- package/build/es/components/tooltip/Tooltip.js.map +1 -1
- package/build/es/components/tooltip/TooltipContent.js +1 -1
- package/build/es/components/tooltip/TooltipContent.js.map +1 -1
- package/build/es/components/tooltip/TooltipTrigger.js +1 -1
- package/build/es/components/tooltip/TooltipTrigger.js.map +1 -1
- package/package.json +4 -4
- package/src/fonts/Fremtind-Material-Symbols.woff2 +0 -0
- package/src/fonts/FremtindGrotesk-Bold-Web.woff +0 -0
- package/src/fonts/FremtindGrotesk-Bold-Web.woff2 +0 -0
- package/src/fonts/FremtindGrotesk-BoldItalic-Web.woff +0 -0
- package/src/fonts/FremtindGrotesk-BoldItalic-Web.woff2 +0 -0
- package/src/fonts/FremtindGrotesk-Display-Web.woff +0 -0
- package/src/fonts/FremtindGrotesk-Display-Web.woff2 +0 -0
- package/src/fonts/FremtindGrotesk-Italic-Web.woff +0 -0
- package/src/fonts/FremtindGrotesk-Italic-Web.woff2 +0 -0
- package/src/fonts/FremtindGrotesk-Regular-Web.woff +0 -0
- package/src/fonts/FremtindGrotesk-Regular-Web.woff2 +0 -0
- package/src/fonts/FremtindGroteskMono-Regular-Web.woff +0 -0
- package/src/fonts/FremtindGroteskMono-Regular-Web.woff2 +0 -0
- package/src/fonts/styles/_index.scss +1 -0
- package/src/fonts/styles/webfonts.scss +137 -0
- package/styles/components/button/button.css +2 -2
- package/styles/components/button/button.min.css +1 -1
- package/styles/components/checkbox/checkbox.css +4 -4
- package/styles/components/checkbox/checkbox.min.css +1 -1
- package/styles/components/feedback/feedback.css +2 -2
- package/styles/components/feedback/feedback.min.css +1 -1
- package/styles/components/input-group/input-group.css +2 -2
- package/styles/components/input-group/input-group.min.css +1 -1
- package/styles/components/input-panel/checkbox-panel.css +2 -2
- package/styles/components/input-panel/checkbox-panel.min.css +1 -1
- package/styles/components/input-panel/radio-panel.css +2 -2
- package/styles/components/input-panel/radio-panel.min.css +1 -1
- package/styles/components/loader/loader.css +6 -6
- package/styles/components/loader/loader.min.css +1 -1
- package/styles/components/loader/skeleton-loader.css +5 -5
- package/styles/components/loader/skeleton-loader.min.css +1 -1
- package/styles/components/message/message.css +2 -2
- package/styles/components/message/message.min.css +1 -1
- package/styles/components/progress-bar/progress-bar.css +2 -2
- package/styles/components/progress-bar/progress-bar.min.css +1 -1
- package/styles/components/radio-button/radio-button.css +2 -2
- package/styles/components/radio-button/radio-button.min.css +1 -1
- package/styles/components/system-message/system-message.css +2 -2
- package/styles/components/system-message/system-message.min.css +1 -1
- package/styles/components/toast/toast.css +4 -4
- package/styles/components/toast/toast.min.css +1 -1
- package/styles/components/tooltip/tooltip.css +2 -26
- package/styles/components/tooltip/tooltip.min.css +1 -1
- package/styles/components/tooltip/tooltip.scss +3 -31
- package/styles/styles.css +39 -63
- package/styles/styles.min.css +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("@floating-ui/react"),n=require("../../../clsx-E3yX_9sL.cjs"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("@floating-ui/react"),n=require("../../../clsx-E3yX_9sL.cjs"),r=require("react"),s=require("react-is"),o=require("../../hooks/useBrowserPreferences/useBrowserPreferences.cjs");require("../../hooks/useScreen/useScreen.cjs");const i=require("../../hooks/useId/useId.cjs"),l=require("../../utilities/getThemeAndDensity.cjs"),a=require("./useMenuWideEvents.cjs");const u=function(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const n in e)if("default"!==n){const r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:()=>e[n]})}return t.default=e,Object.freeze(t)}(s);function c(e,t=0){switch(e){case"top":default:return`0 ${t}px`;case"left":return`${t}px 0`;case"bottom":return`0 ${-t}px`;case"right":return-t+"px 0"}}const d=r.forwardRef(((s,d)=>{const{children:p,className:f,initialPlacement:m,openOnHover:g=!1,keepOpenOnClickOutside:y=!1,triggerElement:v,isOpen:h,onToggle:x,...j}=s,P=i.useId("jkl-menu"),{prefersReducedMotion:k}=o.useBrowserPreferences(),b=t.useFloatingTree(),w=t.useFloatingNodeId(),F=t.useFloatingParentNodeId(),O=null!=F,I=r.useRef([]),[M,E]=r.useState(null),{allowHover:q,isOpen:R,setIsOpen:N}=a.useMenuWideEvents(b,w,F),S=void 0!==h?h:R;r.useEffect((()=>null==x?void 0:x(S)),[S,x]);const{refs:C,placement:T,context:D,floatingStyles:A}=t.useFloating({nodeId:w,open:S,onOpenChange:N,placement:m||(O?"right-start":"bottom-start"),middleware:[t.offset(2),t.flip({fallbackAxisSideDirection:"end",crossAxis:!1}),t.shift({padding:8})],whileElementsMounted:t.autoUpdate}),{getReferenceProps:B,getFloatingProps:H,getItemProps:$}=t.useInteractions([t.useHover(D,{enabled:g&&q,delay:{open:75},handleClose:t.safePolygon({requireIntent:!0,blockPointerEvents:!0})}),t.useClick(D,{event:"mousedown"}),t.useDismiss(D,{outsidePress:!y}),t.useRole(D,{role:"menu"}),t.useListNavigation(D,{listRef:I,activeIndex:M,nested:O,onNavigate:E})]),K=t.useMergeRefs([C.setReference,d]),{theme:V,density:W}=l.getThemeAndDensity(C.reference.current),{isMounted:z,styles:L}=t.useTransitionStyles(D,{duration:{open:k?0:250,close:k?0:150},initial:({side:e})=>({opacity:0,translate:c(e,5)}),open:({side:e})=>({opacity:1,translate:c(e,0)}),close:({side:e})=>({opacity:0,translate:c(e,5)})});return e.jsxs(t.FloatingNode,{id:w,children:[r.isValidElement(v)&&("button"===v.type||u.isForwardRef(v))?r.cloneElement(v,{...B({...j,ref:K,role:O?"menuitem":void 0,"aria-controls":P,onClick(e){e.stopPropagation()}})}):v,z&&e.jsx(t.FloatingPortal,{children:e.jsx(t.FloatingFocusManager,{context:D,modal:!1,initialFocus:O?-1:0,returnFocus:!O,children:e.jsx("div",{className:n.clsx("jkl jkl-menu",f),"data-theme":V,"data-layout-density":W,role:"menu","data-placement":T,"aria-live":"assertive","aria-hidden":!S,ref:C.setFloating,...H({id:P,style:{...A,...L}}),children:r.Children.map(p,((e,t)=>r.isValidElement(e)&&u.isForwardRef(e)?r.cloneElement(e,$({...e.props,tabIndex:M===t?0:-1,role:"menuitem",ref(e){I.current[t]=e},onClick(t){var n,r;null==(r=(n=e.props).onClick)||r.call(n,t),!t.defaultPrevented&&(null==b||b.events.emit("click"))},onKeyDown(t){var n,r;null==(r=(n=e.props).onKeyDown)||r.call(n,t),!t.defaultPrevented&&(null==b||b.events.emit("keydown"),"menuitemcheckbox"===t.currentTarget.role&&"Enter"===t.key&&N(!1))},onMouseEnter(){q&&S&&E(t)}})):e))})})})]})}));d.displayName="MenuComponent";const p=r.forwardRef(((n,r)=>null===t.useFloatingParentNodeId()?e.jsx(t.FloatingTree,{children:e.jsx(d,{ref:r,...n})}):e.jsx(d,{ref:r,...n})));p.displayName="Menu",exports.Menu=p;
|
|
2
2
|
//# sourceMappingURL=Menu.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.cjs","sources":["../../../../src/components/menu/Menu.tsx"],"sourcesContent":["import {\n autoUpdate,\n flip,\n FloatingFocusManager,\n FloatingNode,\n FloatingPortal,\n FloatingTree,\n offset,\n type Placement,\n safePolygon,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListNavigation,\n useMergeRefs,\n useRole,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport React, {\n type ButtonHTMLAttributes,\n forwardRef,\n type ReactNode,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport * as ReactIs from \"react-is\";\nimport { DataTestAutoId, WithChildren } from \"../../core/types.js\";\nimport { useId } from \"../../hooks/useId/useId.js\";\nimport { getThemeAndDensity } from \"../../utilities/getThemeAndDensity.js\";\nimport { useMenuWideEvents } from \"./useMenuWideEvents.js\";\n\nexport interface MenuProps\n extends DataTestAutoId,\n WithChildren,\n Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"children\"> {\n className?: string;\n /**\n * Initiell plassering av menyen. Dersom det ikke er plass på skjermen der du\n * angir at den skal åpnes vil den slyttes automatisk.\n * @default \"bottom-start\" på toppnivå, \"right-start\" for undermenyer\n * */\n initialPlacement?: Placement;\n /**\n * Angir om menyen skal åpnes ved hover (uten å måtte klikke)\n * @default false\n */\n openOnHover?: boolean;\n /**\n * Angir om menyen skal holdes åpen når man klikker utenfor menyen\n * @default false\n */\n keepOpenOnClickOutside?: boolean;\n /**\n * Elementet som fungerer som trigger for menyen. Dersom elementet ikke er en `<button>`\n * eller en `forwardRef<HTMLButtonElement>` vil det bli lagt inne i en knapp\n * med forhåndsdefinert stil. For å komme raskt i gang kan du bruke komponenten\n * `MenuTriggerButton` fra denne pakken.\n */\n triggerElement: ReactNode;\n /**\n * Kan brukes til å styre utenfra om menyen skal være åpen eller ikke.\n * @default false\n */\n isOpen?: boolean;\n /**\n * Callback som kalles når menyen åpnes eller lukkes.\n */\n onToggle?: (isOpen: boolean) => void;\n}\n\nconst MenuComponent = forwardRef<HTMLButtonElement, MenuProps>(\n (props, forwardedRef) => {\n const {\n children,\n className,\n initialPlacement,\n openOnHover = false,\n keepOpenOnClickOutside = false,\n triggerElement,\n isOpen: isOpenOverride,\n onToggle,\n ...triggerProps\n } = props;\n\n const MenuId = useId(\"jkl-menu\");\n\n const tree = useFloatingTree();\n const nodeId = useFloatingNodeId();\n const parentId = useFloatingParentNodeId();\n const isNested = parentId != null;\n\n const listItemsRef = useRef<Array<HTMLButtonElement | null>>([]);\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const {\n allowHover,\n isOpen: isOpenDefault,\n setIsOpen,\n } = useMenuWideEvents(tree, nodeId, parentId);\n\n const isOpen =\n isOpenOverride !== undefined ? isOpenOverride : isOpenDefault;\n\n useEffect(() => onToggle?.(isOpen), [isOpen, onToggle]);\n\n const { x, y, refs, placement, strategy, context } = useFloating({\n nodeId,\n open: isOpen,\n onOpenChange: setIsOpen,\n placement:\n initialPlacement || (isNested ? \"right-start\" : \"bottom-start\"),\n middleware: [\n offset(2),\n flip({\n fallbackAxisSideDirection: \"end\", // Allow bottom placement in narrow viewports (https://floating-ui.com/docs/flip#fallbackaxissidedirection)\n crossAxis: false, // See https://floating-ui.com/docs/flip#combining-with-shift\n }),\n shift({ padding: 8 }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const { getReferenceProps, getFloatingProps, getItemProps } =\n useInteractions([\n useHover(context, {\n enabled: openOnHover && allowHover,\n delay: { open: 75 },\n handleClose: safePolygon({\n requireIntent: true,\n blockPointerEvents: true,\n }),\n }),\n useClick(context, {\n event: \"mousedown\",\n }),\n useDismiss(context, { outsidePress: !keepOpenOnClickOutside }),\n useRole(context, { role: \"menu\" }),\n useListNavigation(context, {\n listRef: listItemsRef,\n activeIndex,\n nested: isNested,\n onNavigate: setActiveIndex,\n }),\n ]);\n\n const referenceRef = useMergeRefs([refs.setReference, forwardedRef]);\n\n // Siden menyen rendres på rot må vi hente lokal dark/light-verdi fra triggeren\n // Vi må gjøre dette for å ta hensyn til at tema kan styres lokalt for deler av UIet\n const { theme, density } = getThemeAndDensity(\n refs.reference.current as HTMLElement,\n );\n\n return (\n <FloatingNode id={nodeId}>\n {React.isValidElement(triggerElement) &&\n (triggerElement.type === \"button\" ||\n ReactIs.isForwardRef(triggerElement))\n ? // Dersom trigger-elementet er en knapp, sett riktige egenskaper på det\n React.cloneElement(triggerElement, {\n ...getReferenceProps({\n ...triggerProps,\n ref: referenceRef,\n role: isNested ? \"menuitem\" : undefined,\n \"aria-controls\": MenuId,\n onClick(event) {\n event.stopPropagation();\n },\n }),\n })\n : // Ellers, rendre elementet as-is, uten interaktivitet. Krev en ferdig brukbar button for å åpne menyen.\n triggerElement}\n <AnimatePresence>\n {isOpen && (\n <FloatingPortal>\n <FloatingFocusManager\n context={context}\n // Prevent outside content interference.\n modal={false}\n // Only initially focus the root floating menu.\n initialFocus={isNested ? -1 : 0}\n // Only return focus to the root menu's reference when menus close.\n returnFocus={!isNested}\n >\n <motion.div\n className={clsx(\"jkl jkl-menu\", className)}\n data-theme={theme}\n data-layout-density={density}\n role=\"menu\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{\n ease: \"easeIn\",\n duration: 0.1,\n }}\n data-placement={placement}\n aria-live=\"assertive\"\n aria-hidden={!isOpen}\n ref={refs.setFloating}\n {...getFloatingProps({\n id: MenuId,\n style: {\n position: strategy,\n top: y ?? \"\",\n left: x ?? \"\",\n },\n })}\n >\n {React.Children.map(\n children,\n (child, index) => {\n if (\n React.isValidElement(child) &&\n ReactIs.isForwardRef(child)\n ) {\n return React.cloneElement(\n child,\n getItemProps({\n ...child.props,\n tabIndex:\n activeIndex ===\n index\n ? 0\n : -1,\n role: \"menuitem\",\n ref(\n node: HTMLButtonElement,\n ) {\n listItemsRef.current[\n index\n ] = node;\n },\n onClick(event) {\n child.props.onClick?.(\n event as React.MouseEvent<HTMLButtonElement>,\n );\n if (\n event.defaultPrevented\n ) {\n return;\n }\n tree?.events.emit(\n \"click\",\n );\n },\n onKeyDown(event) {\n child.props.onKeyDown?.(\n event,\n );\n if (\n event.defaultPrevented\n ) {\n return;\n }\n tree?.events.emit(\n \"keydown\",\n );\n if (\n event\n .currentTarget\n .role ===\n \"menuitemcheckbox\" &&\n event.key ===\n \"Enter\"\n ) {\n // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/menuitemcheckbox_role#keyboard_interactions\n setIsOpen(\n false,\n );\n }\n },\n onMouseEnter() {\n if (\n allowHover &&\n isOpen\n ) {\n setActiveIndex(\n index,\n );\n }\n },\n }),\n );\n }\n\n return child;\n },\n )}\n </motion.div>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </AnimatePresence>\n </FloatingNode>\n );\n },\n);\nMenuComponent.displayName = \"MenuComponent\";\n\nexport const Menu = forwardRef<HTMLButtonElement, MenuProps>((props, ref) => {\n const parentId = useFloatingParentNodeId();\n\n if (parentId === null) {\n return (\n <FloatingTree>\n <MenuComponent ref={ref} {...props} />\n </FloatingTree>\n );\n }\n\n return <MenuComponent ref={ref} {...props} />;\n});\nMenu.displayName = \"Menu\";\n"],"names":["MenuComponent","forwardRef","props","forwardedRef","children","className","initialPlacement","openOnHover","keepOpenOnClickOutside","triggerElement","isOpen","isOpenOverride","onToggle","triggerProps","MenuId","useId","tree","useFloatingTree","nodeId","useFloatingNodeId","parentId","useFloatingParentNodeId","isNested","listItemsRef","useRef","activeIndex","setActiveIndex","useState","allowHover","isOpenDefault","setIsOpen","useMenuWideEvents","useEffect","x","y","refs","placement","strategy","context","useFloating","open","onOpenChange","middleware","offset","flip","fallbackAxisSideDirection","crossAxis","shift","padding","whileElementsMounted","autoUpdate","getReferenceProps","getFloatingProps","getItemProps","useInteractions","useHover","enabled","delay","handleClose","safePolygon","requireIntent","blockPointerEvents","useClick","event","useDismiss","outsidePress","useRole","role","useListNavigation","listRef","nested","onNavigate","referenceRef","useMergeRefs","setReference","theme","density","getThemeAndDensity","reference","current","jsxs","FloatingNode","id","React","isValidElement","type","ReactIs","isForwardRef","cloneElement","ref","onClick","stopPropagation","jsx","AnimatePresence","FloatingPortal","FloatingFocusManager","modal","initialFocus","returnFocus","motion","div","clsx","initial","opacity","animate","exit","transition","ease","duration","setFloating","style","position","top","left","Children","map","child","index","tabIndex","node","_b","_a","call","defaultPrevented","events","emit","onKeyDown","currentTarget","key","onMouseEnter","displayName","Menu","FloatingTree"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Menu.cjs","sources":["../../../../src/components/menu/Menu.tsx"],"sourcesContent":["import {\n autoUpdate,\n flip,\n FloatingFocusManager,\n FloatingNode,\n FloatingPortal,\n FloatingTree,\n offset,\n type Placement,\n safePolygon,\n shift,\n Side,\n useClick,\n useDismiss,\n useFloating,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListNavigation,\n useMergeRefs,\n useRole,\n useTransitionStyles,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport React, {\n type ButtonHTMLAttributes,\n forwardRef,\n type ReactNode,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport * as ReactIs from \"react-is\";\nimport { DataTestAutoId, WithChildren } from \"../../core/types.js\";\nimport { useBrowserPreferences } from \"../../hooks/index.js\";\nimport { useId } from \"../../hooks/useId/useId.js\";\nimport { getThemeAndDensity } from \"../../utilities/getThemeAndDensity.js\";\nimport { useMenuWideEvents } from \"./useMenuWideEvents.js\";\n\nexport interface MenuProps\n extends DataTestAutoId,\n WithChildren,\n Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"children\"> {\n className?: string;\n /**\n * Initiell plassering av menyen. Dersom det ikke er plass på skjermen der du\n * angir at den skal åpnes vil den slyttes automatisk.\n * @default \"bottom-start\" på toppnivå, \"right-start\" for undermenyer\n * */\n initialPlacement?: Placement;\n /**\n * Angir om menyen skal åpnes ved hover (uten å måtte klikke)\n * @default false\n */\n openOnHover?: boolean;\n /**\n * Angir om menyen skal holdes åpen når man klikker utenfor menyen\n * @default false\n */\n keepOpenOnClickOutside?: boolean;\n /**\n * Elementet som fungerer som trigger for menyen. Dersom elementet ikke er en `<button>`\n * eller en `forwardRef<HTMLButtonElement>` vil det bli lagt inne i en knapp\n * med forhåndsdefinert stil. For å komme raskt i gang kan du bruke komponenten\n * `MenuTriggerButton` fra denne pakken.\n */\n triggerElement: ReactNode;\n /**\n * Kan brukes til å styre utenfra om menyen skal være åpen eller ikke.\n * @default false\n */\n isOpen?: boolean;\n /**\n * Callback som kalles når menyen åpnes eller lukkes.\n */\n onToggle?: (isOpen: boolean) => void;\n}\n\nfunction getTranslation(side: Side, value: number = 0) {\n switch (side) {\n case \"top\":\n return `0 ${value}px`;\n case \"left\":\n return `${value}px 0`;\n case \"bottom\":\n return `0 ${-value}px`;\n case \"right\":\n return `${-value}px 0`;\n\n default:\n return `0 ${value}px`;\n }\n}\n\nconst MenuComponent = forwardRef<HTMLButtonElement, MenuProps>(\n (props, forwardedRef) => {\n const {\n children,\n className,\n initialPlacement,\n openOnHover = false,\n keepOpenOnClickOutside = false,\n triggerElement,\n isOpen: isOpenOverride,\n onToggle,\n ...triggerProps\n } = props;\n\n const MenuId = useId(\"jkl-menu\");\n\n const { prefersReducedMotion } = useBrowserPreferences();\n\n const tree = useFloatingTree();\n const nodeId = useFloatingNodeId();\n const parentId = useFloatingParentNodeId();\n const isNested = parentId != null;\n\n const listItemsRef = useRef<Array<HTMLButtonElement | null>>([]);\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const {\n allowHover,\n isOpen: isOpenDefault,\n setIsOpen,\n } = useMenuWideEvents(tree, nodeId, parentId);\n\n const isOpen =\n isOpenOverride !== undefined ? isOpenOverride : isOpenDefault;\n\n useEffect(() => onToggle?.(isOpen), [isOpen, onToggle]);\n\n const { refs, placement, context, floatingStyles } = useFloating({\n nodeId,\n open: isOpen,\n onOpenChange: setIsOpen,\n placement:\n initialPlacement || (isNested ? \"right-start\" : \"bottom-start\"),\n middleware: [\n offset(2),\n flip({\n fallbackAxisSideDirection: \"end\", // Allow bottom placement in narrow viewports (https://floating-ui.com/docs/flip#fallbackaxissidedirection)\n crossAxis: false, // See https://floating-ui.com/docs/flip#combining-with-shift\n }),\n shift({ padding: 8 }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const { getReferenceProps, getFloatingProps, getItemProps } =\n useInteractions([\n useHover(context, {\n enabled: openOnHover && allowHover,\n delay: { open: 75 },\n handleClose: safePolygon({\n requireIntent: true,\n blockPointerEvents: true,\n }),\n }),\n useClick(context, {\n event: \"mousedown\",\n }),\n useDismiss(context, { outsidePress: !keepOpenOnClickOutside }),\n useRole(context, { role: \"menu\" }),\n useListNavigation(context, {\n listRef: listItemsRef,\n activeIndex,\n nested: isNested,\n onNavigate: setActiveIndex,\n }),\n ]);\n\n const referenceRef = useMergeRefs([refs.setReference, forwardedRef]);\n\n // Siden menyen rendres på rot må vi hente lokal dark/light-verdi fra triggeren\n // Vi må gjøre dette for å ta hensyn til at tema kan styres lokalt for deler av UIet\n const { theme, density } = getThemeAndDensity(\n refs.reference.current as HTMLElement,\n );\n\n const { isMounted, styles: animationStyles } = useTransitionStyles(\n context,\n {\n duration: {\n open: prefersReducedMotion ? 0 : 250,\n close: prefersReducedMotion ? 0 : 150,\n },\n initial: ({ side }) => ({\n opacity: 0,\n translate: getTranslation(side, 5),\n }),\n open: ({ side }) => ({\n opacity: 1,\n translate: getTranslation(side, 0),\n }),\n close: ({ side }) => ({\n opacity: 0,\n translate: getTranslation(side, 5),\n }),\n },\n );\n\n return (\n <FloatingNode id={nodeId}>\n {React.isValidElement(triggerElement) &&\n (triggerElement.type === \"button\" ||\n ReactIs.isForwardRef(triggerElement))\n ? // Dersom trigger-elementet er en knapp, sett riktige egenskaper på det\n React.cloneElement(triggerElement, {\n ...getReferenceProps({\n ...triggerProps,\n ref: referenceRef,\n role: isNested ? \"menuitem\" : undefined,\n \"aria-controls\": MenuId,\n onClick(event) {\n event.stopPropagation();\n },\n }),\n })\n : // Ellers, rendre elementet as-is, uten interaktivitet. Krev en ferdig brukbar button for å åpne menyen.\n triggerElement}\n {isMounted && (\n <FloatingPortal>\n <FloatingFocusManager\n context={context}\n // Prevent outside content interference.\n modal={false}\n // Only initially focus the root floating menu.\n initialFocus={isNested ? -1 : 0}\n // Only return focus to the root menu's reference when menus close.\n returnFocus={!isNested}\n >\n <div\n className={clsx(\"jkl jkl-menu\", className)}\n data-theme={theme}\n data-layout-density={density}\n role=\"menu\"\n data-placement={placement}\n aria-live=\"assertive\"\n aria-hidden={!isOpen}\n ref={refs.setFloating}\n {...getFloatingProps({\n id: MenuId,\n style: {\n ...floatingStyles,\n ...animationStyles,\n },\n })}\n >\n {React.Children.map(\n children,\n (child, index) => {\n if (\n React.isValidElement(child) &&\n ReactIs.isForwardRef(child)\n ) {\n return React.cloneElement(\n child,\n getItemProps({\n ...child.props,\n tabIndex:\n activeIndex === index\n ? 0\n : -1,\n role: \"menuitem\",\n ref(\n node: HTMLButtonElement,\n ) {\n listItemsRef.current[\n index\n ] = node;\n },\n onClick(event) {\n child.props.onClick?.(\n event as React.MouseEvent<HTMLButtonElement>,\n );\n if (\n event.defaultPrevented\n ) {\n return;\n }\n tree?.events.emit(\n \"click\",\n );\n },\n onKeyDown(event) {\n child.props.onKeyDown?.(\n event,\n );\n if (\n event.defaultPrevented\n ) {\n return;\n }\n tree?.events.emit(\n \"keydown\",\n );\n if (\n event.currentTarget\n .role ===\n \"menuitemcheckbox\" &&\n event.key ===\n \"Enter\"\n ) {\n // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/menuitemcheckbox_role#keyboard_interactions\n setIsOpen(false);\n }\n },\n onMouseEnter() {\n if (\n allowHover &&\n isOpen\n ) {\n setActiveIndex(\n index,\n );\n }\n },\n }),\n );\n }\n\n return child;\n },\n )}\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </FloatingNode>\n );\n },\n);\nMenuComponent.displayName = \"MenuComponent\";\n\nexport const Menu = forwardRef<HTMLButtonElement, MenuProps>((props, ref) => {\n const parentId = useFloatingParentNodeId();\n\n if (parentId === null) {\n return (\n <FloatingTree>\n <MenuComponent ref={ref} {...props} />\n </FloatingTree>\n );\n }\n\n return <MenuComponent ref={ref} {...props} />;\n});\nMenu.displayName = \"Menu\";\n"],"names":["getTranslation","side","value","MenuComponent","forwardRef","props","forwardedRef","children","className","initialPlacement","openOnHover","keepOpenOnClickOutside","triggerElement","isOpen","isOpenOverride","onToggle","triggerProps","MenuId","useId","prefersReducedMotion","useBrowserPreferences","tree","useFloatingTree","nodeId","useFloatingNodeId","parentId","useFloatingParentNodeId","isNested","listItemsRef","useRef","activeIndex","setActiveIndex","useState","allowHover","isOpenDefault","setIsOpen","useMenuWideEvents","useEffect","refs","placement","context","floatingStyles","useFloating","open","onOpenChange","middleware","offset","flip","fallbackAxisSideDirection","crossAxis","shift","padding","whileElementsMounted","autoUpdate","getReferenceProps","getFloatingProps","getItemProps","useInteractions","useHover","enabled","delay","handleClose","safePolygon","requireIntent","blockPointerEvents","useClick","event","useDismiss","outsidePress","useRole","role","useListNavigation","listRef","nested","onNavigate","referenceRef","useMergeRefs","setReference","theme","density","getThemeAndDensity","reference","current","isMounted","styles","animationStyles","useTransitionStyles","duration","close","initial","opacity","translate","jsxs","FloatingNode","id","React","isValidElement","type","ReactIs","isForwardRef","cloneElement","ref","onClick","stopPropagation","FloatingPortal","jsx","FloatingFocusManager","modal","initialFocus","returnFocus","clsx","setFloating","style","Children","map","child","index","tabIndex","node","_b","_a","call","defaultPrevented","events","emit","onKeyDown","currentTarget","key","onMouseEnter","displayName","Menu","FloatingTree"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("@floating-ui/react"),n=require("react"),r=n.createContext(null),o=r.Provider;exports.Tooltip=({children:r,...i})=>{const s=(({initialOpen:e=!1,placement:r="top",delay:o=250,triggerOn:i="hover"})=>{const[s,l]=n.useState(e),u=n.useRef(null),c=n.useRef(null),a=t.useFloating({open:s,onOpenChange:l,placement:r,whileElementsMounted:t.autoUpdate,middleware:[t.offset(16),t.flip(),t.shift({padding:16}),t.arrow({element:u,padding:
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("@floating-ui/react"),n=require("react"),r=n.createContext(null),o=r.Provider;exports.Tooltip=({children:r,...i})=>{const s=(({initialOpen:e=!1,placement:r="top",delay:o=250,triggerOn:i="hover"})=>{const[s,l]=n.useState(e),u=n.useRef(null),c=n.useRef(null),a=t.useFloating({open:s,onOpenChange:l,placement:r,whileElementsMounted:t.autoUpdate,middleware:[t.offset(16),t.flip(),t.shift({padding:16}),t.arrow({element:u,padding:8})]}),p=t.useRole(a.context,{role:"tooltip"}),d=t.useDismiss(a.context,{referencePress:!1}),x=t.useClick(a.context,{enabled:"click"===i&&!s}),f=t.useHover(a.context,{enabled:"hover"===i,delay:s?0:o}),g=t.useFocus(a.context,{enabled:"click"!==i||s}),m=t.useInteractions([d,g,p,x,f]);return{triggerOn:i,isOpen:s,setOpen:l,arrowElement:u,...a,refs:{...a.refs,description:c,setDescription:e=>c.current=e},...m}})(i);return e.jsx(o,{value:s,children:r})},exports.TooltipProvider=o,exports.useTooltipContext=()=>{const e=n.useContext(r);if(null===e)throw new Error("Tooltip-komponentene kan kun brukes inne i <Tooltip />");return e};
|
|
2
2
|
//# sourceMappingURL=Tooltip.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.cjs","sources":["../../../../src/components/tooltip/Tooltip.tsx"],"sourcesContent":["import {\n type Placement,\n type UseFloatingReturn,\n arrow,\n autoUpdate,\n flip,\n offset,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFocus,\n useHover,\n useInteractions,\n useRole,\n} from \"@floating-ui/react\";\nimport React, { FC, createContext, useContext, useRef, useState } from \"react\";\nimport { type WithChildren } from \"../../core/types.js\";\n\nexport type TooltipPlacement = Extract<\n Placement,\n \"top-start\" | \"top-end\" | \"left\" | \"right\" | \"top\"\n>;\n\nexport interface TooltipProps {\n /**\n * Sett til true dersom du ønsker at tooltipen skal være åpen som default\n * @default false\n */\n initialOpen?: boolean;\n /**\n * Plassering av tooltipen i forhold til triggeren. Tooltipen vil automatisk\n * bytte posisjon dersom det ikke er plass.\n * @default \"top\"\n */\n placement?: TooltipPlacement;\n /**\n * Valgfri forsinkelse før tooltipen åpner. Ignoreres dersom triggerOn er satt til \"click\"\n * @default 250\n */\n delay?: number;\n /**\n * Angir om tooltipen skal åpnes ved klikk eller hover\n * @default \"hover\"\n */\n triggerOn?: \"click\" | \"hover\";\n}\n\ntype UseTooltipReturn = {\n triggerOn: NonNullable<TooltipProps[\"triggerOn\"]>;\n isOpen: boolean;\n setOpen: React.Dispatch<React.SetStateAction<boolean>>;\n arrowElement: React.RefObject<
|
|
1
|
+
{"version":3,"file":"Tooltip.cjs","sources":["../../../../src/components/tooltip/Tooltip.tsx"],"sourcesContent":["import {\n type Placement,\n type UseFloatingReturn,\n arrow,\n autoUpdate,\n flip,\n offset,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFocus,\n useHover,\n useInteractions,\n useRole,\n} from \"@floating-ui/react\";\nimport React, { FC, createContext, useContext, useRef, useState } from \"react\";\nimport { type WithChildren } from \"../../core/types.js\";\n\nexport type TooltipPlacement = Extract<\n Placement,\n \"top-start\" | \"top-end\" | \"left\" | \"right\" | \"top\"\n>;\n\nexport interface TooltipProps {\n /**\n * Sett til true dersom du ønsker at tooltipen skal være åpen som default\n * @default false\n */\n initialOpen?: boolean;\n /**\n * Plassering av tooltipen i forhold til triggeren. Tooltipen vil automatisk\n * bytte posisjon dersom det ikke er plass.\n * @default \"top\"\n */\n placement?: TooltipPlacement;\n /**\n * Valgfri forsinkelse før tooltipen åpner. Ignoreres dersom triggerOn er satt til \"click\"\n * @default 250\n */\n delay?: number;\n /**\n * Angir om tooltipen skal åpnes ved klikk eller hover\n * @default \"hover\"\n */\n triggerOn?: \"click\" | \"hover\";\n}\n\ntype UseTooltipReturn = {\n triggerOn: NonNullable<TooltipProps[\"triggerOn\"]>;\n isOpen: boolean;\n setOpen: React.Dispatch<React.SetStateAction<boolean>>;\n arrowElement: React.RefObject<SVGSVGElement>;\n refs: {\n description: React.MutableRefObject<HTMLElement | null>;\n setDescription: (element: HTMLElement | null) => void;\n } & UseFloatingReturn[\"refs\"];\n} & UseFloatingReturn &\n ReturnType<typeof useInteractions>;\n\nconst useTooltip = ({\n initialOpen = false,\n placement = \"top\",\n delay = 250,\n triggerOn = \"hover\",\n}: TooltipProps): UseTooltipReturn => {\n const [isOpen, setOpen] = useState(initialOpen);\n const arrowElement = useRef<SVGSVGElement>(null);\n const description = useRef<HTMLElement | null>(null);\n const setDescription = (element: HTMLElement | null) =>\n (description.current = element);\n\n const data = useFloating({\n open: isOpen,\n onOpenChange: setOpen,\n placement,\n whileElementsMounted: autoUpdate,\n middleware: [\n offset(16),\n flip(),\n shift({ padding: 16 }),\n arrow({ element: arrowElement, padding: 8 }),\n ],\n });\n\n const role = useRole(data.context, { role: \"tooltip\" });\n const dismiss = useDismiss(data.context, { referencePress: false });\n const click = useClick(data.context, {\n enabled: triggerOn === \"click\" && !isOpen,\n });\n const hover = useHover(data.context, {\n enabled: triggerOn === \"hover\",\n delay: isOpen ? 0 : delay,\n });\n const focus = useFocus(data.context, {\n enabled: triggerOn === \"click\" ? isOpen : true,\n });\n\n const interactions = useInteractions([dismiss, focus, role, click, hover]);\n\n return {\n triggerOn,\n isOpen,\n setOpen,\n arrowElement,\n ...data,\n refs: {\n ...data.refs,\n description,\n setDescription,\n },\n ...interactions,\n };\n};\n\nexport type TooltipContext = ReturnType<typeof useTooltip> | null;\n\nconst tooltipContext = createContext<TooltipContext>(null);\n\nexport const TooltipProvider = tooltipContext.Provider;\n\nexport const useTooltipContext = () => {\n const context = useContext(tooltipContext);\n\n if (context === null) {\n throw new Error(\n \"Tooltip-komponentene kan kun brukes inne i <Tooltip />\",\n );\n }\n\n return context;\n};\n\nexport const Tooltip: FC<TooltipProps & WithChildren> = ({\n children,\n ...options\n}) => {\n const tooltip = useTooltip(options);\n\n return <TooltipProvider value={tooltip}>{children}</TooltipProvider>;\n};\n"],"names":["tooltipContext","createContext","TooltipProvider","Provider","children","options","tooltip","initialOpen","placement","delay","triggerOn","isOpen","setOpen","useState","arrowElement","useRef","description","data","useFloating","open","onOpenChange","whileElementsMounted","autoUpdate","middleware","offset","flip","shift","padding","arrow","element","role","useRole","context","dismiss","useDismiss","referencePress","click","useClick","enabled","hover","useHover","focus","useFocus","interactions","useInteractions","refs","setDescription","current","useTooltip","jsx","value","useContext","Error"],"mappings":"wKAqHMA,EAAiBC,EAAAA,cAA8B,MAExCC,EAAkBF,EAAeG,yBAcU,EACpDC,SAAAA,KACGC,MAEG,MAAAC,EA7ES,GACfC,YAAAA,GAAc,EACdC,UAAAA,EAAY,MACZC,MAAAA,EAAQ,IACRC,UAAAA,EAAY,YAEZ,MAAOC,EAAQC,GAAWC,WAASN,GAC7BO,EAAeC,SAAsB,MACrCC,EAAcD,SAA2B,MAIzCE,EAAOC,EAAAA,YAAY,CACrBC,KAAMR,EACNS,aAAcR,EACdJ,UAAAA,EACAa,qBAAsBC,EAAAA,WACtBC,WAAY,CACRC,EAAAA,OAAO,IACPC,SACAC,QAAM,CAAEC,QAAS,KACjBC,EAAAA,MAAM,CAAEC,QAASf,EAAca,QAAS,OAI1CG,EAAOC,EAAAA,QAAQd,EAAKe,QAAS,CAAEF,KAAM,YACrCG,EAAUC,EAAAA,WAAWjB,EAAKe,QAAS,CAAEG,gBAAgB,IACrDC,EAAQC,EAAAA,SAASpB,EAAKe,QAAS,CACjCM,QAAuB,UAAd5B,IAA0BC,IAEjC4B,EAAQC,EAAAA,SAASvB,EAAKe,QAAS,CACjCM,QAAuB,UAAd5B,EACTD,MAAOE,EAAS,EAAIF,IAElBgC,EAAQC,EAAAA,SAASzB,EAAKe,QAAS,CACjCM,QAAuB,UAAd5B,GAAwBC,IAG/BgC,EAAeC,kBAAgB,CAACX,EAASQ,EAAOX,EAAMM,EAAOG,IAE5D,MAAA,CACH7B,UAAAA,EACAC,OAAAA,EACAC,QAAAA,EACAE,aAAAA,KACGG,EACH4B,KAAM,IACC5B,EAAK4B,KACR7B,YAAAA,EACA8B,eAxCgBjB,GACnBb,EAAY+B,QAAUlB,MAyCpBc,EAAA,EA0BSK,CAAW3C,GAE3B,OAAQ4C,EAAAA,IAAA/C,EAAA,CAAgBgD,MAAO5C,EAAUF,SAAAA,GAAS,sDAlBrB,KACvB,MAAA4B,EAAUmB,aAAWnD,GAE3B,GAAgB,OAAZgC,EACA,MAAM,IAAIoB,MACN,0DAID,OAAApB"}
|
|
@@ -29,7 +29,7 @@ type UseTooltipReturn = {
|
|
|
29
29
|
triggerOn: NonNullable<TooltipProps["triggerOn"]>;
|
|
30
30
|
isOpen: boolean;
|
|
31
31
|
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
|
32
|
-
arrowElement: React.RefObject<
|
|
32
|
+
arrowElement: React.RefObject<SVGSVGElement>;
|
|
33
33
|
refs: {
|
|
34
34
|
description: React.MutableRefObject<HTMLElement | null>;
|
|
35
35
|
setDescription: (element: HTMLElement | null) => void;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("@floating-ui/react"),r=require("../../../clsx-E3yX_9sL.cjs"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("@floating-ui/react"),r=require("../../../clsx-E3yX_9sL.cjs"),s=require("react"),i=require("../../hooks/useBrowserPreferences/useBrowserPreferences.cjs"),n=require("../../hooks/useId/useId.cjs"),o=require("../../utilities/getThemeAndDensity.cjs"),a=require("./Tooltip.cjs");function c(e,t=0){switch(e){case"top":default:return`0 ${t}px`;case"left":return`${t}px 0`;case"bottom":return`0 ${-t}px`;case"right":return-t+"px 0"}}const l=s.forwardRef((function({className:s,children:l,...u},d){const{triggerOn:p,arrowElement:f,getFloatingProps:g,placement:h,floatingStyles:x,refs:j,context:y}=a.useTooltipContext(),m=t.useMergeRefs([d,j.setFloating]),w=n.useId("jkl-tooltip-content"),{prefersReducedMotion:q}=i.useBrowserPreferences(),{isMounted:k,styles:T}=t.useTransitionStyles(y,{duration:{open:q?0:250,close:q?0:150},initial:({side:e})=>({opacity:0,translate:c(e,5)}),open:({side:e})=>({opacity:1,translate:c(e,0)}),close:({side:e})=>({opacity:0,translate:c(e,-5)})}),{density:v,theme:P}=o.getThemeAndDensity(j.reference.current);return e.jsxs(t.FloatingPortal,{children:["hover"===p&&e.jsx("span",{ref:j.setDescription,hidden:!0,children:l},`${w}-trigger`),k&&e.jsx("span",{className:"jkl",children:e.jsxs("span",{ref:m,"data-placement":h,"aria-live":"click"===p?"assertive":void 0,"data-theme":P,"data-layout-density":v,className:r.clsx("jkl-tooltip-content",s),...g({...u,id:w}),style:{...x,...T},children:[l,e.jsx(t.FloatingArrow,{context:y,ref:f,width:24,height:12,fill:"var(--background-color)"})]},w)},`${w}-wrapper`)]})}));exports.TooltipContent=l;
|
|
2
2
|
//# sourceMappingURL=TooltipContent.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TooltipContent.cjs","sources":["../../../../src/components/tooltip/TooltipContent.tsx"],"sourcesContent":["import {\n type
|
|
1
|
+
{"version":3,"file":"TooltipContent.cjs","sources":["../../../../src/components/tooltip/TooltipContent.tsx"],"sourcesContent":["import {\n FloatingArrow,\n FloatingPortal,\n type Side,\n useMergeRefs,\n useTransitionStyles,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport React, { HTMLProps, forwardRef } from \"react\";\nimport { useBrowserPreferences } from \"../../hooks/useBrowserPreferences/useBrowserPreferences.js\";\nimport { useId } from \"../../hooks/useId/useId.js\";\nimport { getThemeAndDensity } from \"../../utilities/getThemeAndDensity.js\";\nimport { useTooltipContext } from \"./Tooltip.js\";\n\nfunction getTranslation(side: Side, value: number = 0) {\n switch (side) {\n case \"top\":\n return `0 ${value}px`;\n case \"left\":\n return `${value}px 0`;\n case \"bottom\":\n return `0 ${-value}px`;\n case \"right\":\n return `${-value}px 0`;\n\n default:\n return `0 ${value}px`;\n }\n}\n\nexport const TooltipContent = forwardRef<\n HTMLDivElement,\n HTMLProps<HTMLDivElement>\n>(function TooltipContent({ className, children, ...props }, forwardedRef) {\n const {\n triggerOn,\n arrowElement,\n getFloatingProps,\n placement,\n floatingStyles,\n refs,\n context,\n } = useTooltipContext();\n const ref = useMergeRefs([forwardedRef, refs.setFloating]);\n const contentId = useId(\"jkl-tooltip-content\");\n const { prefersReducedMotion } = useBrowserPreferences();\n const { isMounted, styles: animationStyles } = useTransitionStyles(\n context,\n {\n duration: {\n open: prefersReducedMotion ? 0 : 250,\n close: prefersReducedMotion ? 0 : 150,\n },\n initial: ({ side }) => ({\n opacity: 0,\n translate: getTranslation(side, 5),\n }),\n open: ({ side }) => ({\n opacity: 1,\n translate: getTranslation(side, 0),\n }),\n close: ({ side }) => ({\n opacity: 0,\n translate: getTranslation(side, -5),\n }),\n },\n );\n\n // Siden tooltipet rendres på rot må vi hente lokal dark/light-verdi fra triggeren\n // Vi må gjøre dette for å ta hensyn til at tema kan styres lokalt for deler av UIet\n const { density, theme } = getThemeAndDensity(\n refs.reference.current as HTMLElement,\n );\n\n return (\n <FloatingPortal>\n {/* For å kunne bruke tekstinnholdet i tooltip som beskrivende tekst, selv når ikke\n tooltip er synlig, må vi rendre et skjult element å referere til for å hente innholdet. */}\n {triggerOn === \"hover\" && (\n <span\n ref={refs.setDescription}\n hidden\n key={`${contentId}-trigger`}\n >\n {children}\n </span>\n )}\n {isMounted && (\n <span className=\"jkl\" key={`${contentId}-wrapper`}>\n <span\n key={contentId}\n ref={ref}\n data-placement={placement}\n aria-live={\n triggerOn === \"click\" ? \"assertive\" : undefined\n }\n data-theme={theme}\n data-layout-density={density}\n className={clsx(\"jkl-tooltip-content\", className)}\n {...getFloatingProps({\n ...props,\n id: contentId,\n })}\n style={{ ...floatingStyles, ...animationStyles }}\n >\n {children}\n <FloatingArrow\n context={context}\n ref={arrowElement}\n width={24}\n height={12}\n fill=\"var(--background-color)\"\n />\n </span>\n </span>\n )}\n </FloatingPortal>\n );\n});\n"],"names":["getTranslation","side","value","TooltipContent","forwardRef","className","children","props","forwardedRef","triggerOn","arrowElement","getFloatingProps","placement","floatingStyles","refs","context","useTooltipContext","ref","useMergeRefs","setFloating","contentId","useId","prefersReducedMotion","useBrowserPreferences","isMounted","styles","animationStyles","useTransitionStyles","duration","open","close","initial","opacity","translate","density","theme","getThemeAndDensity","reference","current","FloatingPortal","jsx","setDescription","hidden","jsxs","clsx","id","style","FloatingArrow","width","height","fill"],"mappings":"iZAcA,SAASA,EAAeC,EAAYC,EAAgB,GAChD,OAAQD,GACJ,IAAK,MASL,QACI,MAAO,KAAKC,MARhB,IAAK,OACD,MAAO,GAAGA,QACd,IAAK,SACM,MAAA,MAAMA,MACjB,IAAK,QACM,OAAIA,EAAJ,OAKnB,CAEa,MAAAC,EAAiBC,EAAAA,YAG5B,UAA0BC,UAAAA,EAAWC,SAAAA,KAAaC,GAASC,GACnD,MACFC,UAAAA,EACAC,aAAAA,EACAC,iBAAAA,EACAC,UAAAA,EACAC,eAAAA,EACAC,KAAAA,EACAC,QAAAA,GACAC,EAAkBA,oBAChBC,EAAMC,EAAAA,aAAa,CAACV,EAAcM,EAAKK,cACvCC,EAAYC,QAAM,wBAChBC,qBAAAA,GAAyBC,EAAAA,yBACzBC,UAAAA,EAAWC,OAAQC,GAAoBC,EAAAA,oBAC3CZ,EACA,CACIa,SAAU,CACNC,KAAMP,EAAuB,EAAI,IACjCQ,MAAOR,EAAuB,EAAI,KAEtCS,QAAS,EAAG9B,KAAAA,OACR+B,QAAS,EACTC,UAAWjC,EAAeC,EAAM,KAEpC4B,KAAM,EAAG5B,KAAAA,OACL+B,QAAS,EACTC,UAAWjC,EAAeC,EAAM,KAEpC6B,MAAO,EAAG7B,KAAAA,OACN+B,QAAS,EACTC,UAAWjC,EAAeC,GAAQ,QAOtCiC,QAAAA,EAASC,MAAAA,GAAUC,EAAAA,mBACvBtB,EAAKuB,UAAUC,SAGnB,cACKC,iBAGI,CAAAjC,SAAA,CAAc,UAAdG,GACG+B,EAAAA,IAAC,OAAA,CACGvB,IAAKH,EAAK2B,eACVC,QAAM,EAGLpC,SAAAA,GAFI,GAAGc,aAKfI,GACGgB,EAAAA,IAAC,OAAK,CAAAnC,UAAU,MACZC,SAAAqC,EAAAA,KAAC,OAAA,CAEG1B,IAAAA,EACA,iBAAgBL,EAChB,YACkB,UAAdH,EAAwB,iBAAc,EAE1C,aAAY0B,EACZ,sBAAqBD,EACrB7B,UAAWuC,EAAAA,KAAK,sBAAuBvC,MACnCM,EAAiB,IACdJ,EACHsC,GAAIzB,IAER0B,MAAO,IAAKjC,KAAmBa,GAE9BpB,SAAA,CAAAA,EACDkC,EAAAA,IAACO,EAAAA,cAAA,CACGhC,QAAAA,EACAE,IAAKP,EACLsC,MAAO,GACPC,OAAQ,GACRC,KAAK,8BArBJ9B,IAFc,GAAGA,eA8B9C"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("@floating-ui/react"),t=require("../../../clsx-E3yX_9sL.cjs"),o=require("react"),l=require("./Tooltip.cjs"),n=o.forwardRef((function({children:n,className:s,...i},
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("@floating-ui/react"),t=require("../../../clsx-E3yX_9sL.cjs"),o=require("react"),l=require("./Tooltip.cjs"),n=o.forwardRef((function({children:n,className:s,...i},a){var c,u;const{isOpen:p,setOpen:f,getReferenceProps:d,refs:g,triggerOn:x}=l.useTooltipContext(),m=n.ref,b=r.useMergeRefs([m,g.setReference,a]),j=()=>{"click"===x&&f(!1)},v=[null==(c=g.reference.current)?void 0:c.textContent,null==(u=g.description.current)?void 0:u.textContent].map((e=>null==e?void 0:e.replaceAll(/[\ue003-\uf8aa]/g,""))).filter(Boolean).join(". ");return o.isValidElement(n)?o.cloneElement(n,d({ref:b,"aria-label":v,...n.props,...i,className:t.clsx(n.props.className,s),"data-tooltip-shown":p,style:{...n.props.style},tabIndex:"click"===x?0:void 0,onBlur:()=>{n.props.onBlur&&n.props.onBlur(),j()}})):e.jsx("button",{"data-tooltip-shown":p,...d({className:t.clsx(s,"jkl-tooltip-trigger"),type:"button",ref:b,onBlur:j,"aria-label":v,...i}),children:n})}));exports.TooltipTrigger=n;
|
|
2
2
|
//# sourceMappingURL=TooltipTrigger.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TooltipTrigger.cjs","sources":["../../../../src/components/tooltip/TooltipTrigger.tsx"],"sourcesContent":["import { useMergeRefs } from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport React, { forwardRef, type HTMLProps } from \"react\";\nimport { useTooltipContext } from \"./Tooltip.js\";\n\nexport const TooltipTrigger = forwardRef<HTMLElement, HTMLProps<HTMLElement>>(\n function TooltipTrigger({ children, className, ...props }, forwardedRef) {\n const { isOpen, setOpen, getReferenceProps, refs, triggerOn } =\n useTooltipContext();\n const childrenRef = (children as any).ref;\n const ref = useMergeRefs([\n childrenRef,\n refs.setReference,\n forwardedRef,\n ]);\n\n const handleBlur = () => {\n triggerOn === \"click\" && setOpen(false);\n };\n\n const ariaLabel = [\n (refs.reference.current as HTMLElement | null)?.textContent,\n refs.description.current?.textContent,\n ]\n .filter(Boolean)\n .join(\". \");\n\n if (React.isValidElement(children)) {\n return React.cloneElement(\n children,\n getReferenceProps({\n ref,\n \"aria-label\": ariaLabel,\n ...children.props,\n ...props,\n className: clsx(children.props.className, className),\n \"data-tooltip-shown\": isOpen,\n style: { ...children.props.style },\n tabIndex: triggerOn === \"click\" ? 0 : undefined,\n onBlur: () => {\n children.props.onBlur && children.props.onBlur();\n handleBlur();\n },\n }),\n );\n }\n\n return (\n <button\n data-tooltip-shown={isOpen}\n {...getReferenceProps({\n className: clsx(className, \"jkl-tooltip-trigger\"),\n // Sørg for at vi ikke sender inn skjemaer ved klikk på knappen\n type: \"button\",\n ref,\n onBlur: handleBlur,\n \"aria-label\": ariaLabel,\n ...props,\n })}\n >\n {children}\n </button>\n );\n },\n);\n"],"names":["TooltipTrigger","forwardRef","children","className","props","forwardedRef","isOpen","setOpen","getReferenceProps","refs","triggerOn","useTooltipContext","childrenRef","ref","useMergeRefs","setReference","handleBlur","ariaLabel","_a","reference","current","textContent","_b","description","filter","Boolean","join","React","isValidElement","cloneElement","clsx","style","tabIndex","onBlur","jsx","type"],"mappings":"2OAKaA,EAAiBC,EAAAA,YAC1B,UAA0BC,SAAAA,EAAUC,UAAAA,KAAcC,GAASC,WACvD,MAAQC,OAAAA,EAAQC,QAAAA,EAASC,kBAAAA,EAAmBC,KAAAA,EAAMC,UAAAA,GAC9CC,EAAAA,oBACEC,EAAeV,EAAiBW,IAChCA,EAAMC,EAAAA,aAAa,CACrBF,EACAH,EAAKM,aACLV,IAGEW,EAAa,KACD,UAAAN,GAAWH,GAAQ,EAAK,
|
|
1
|
+
{"version":3,"file":"TooltipTrigger.cjs","sources":["../../../../src/components/tooltip/TooltipTrigger.tsx"],"sourcesContent":["import { useMergeRefs } from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport React, { forwardRef, type HTMLProps } from \"react\";\nimport { useTooltipContext } from \"./Tooltip.js\";\n\nexport const TooltipTrigger = forwardRef<HTMLElement, HTMLProps<HTMLElement>>(\n function TooltipTrigger({ children, className, ...props }, forwardedRef) {\n const { isOpen, setOpen, getReferenceProps, refs, triggerOn } =\n useTooltipContext();\n const childrenRef = (children as any).ref;\n const ref = useMergeRefs([\n childrenRef,\n refs.setReference,\n forwardedRef,\n ]);\n\n const handleBlur = () => {\n triggerOn === \"click\" && setOpen(false);\n };\n\n const filterMaterialSymbols = (\n maybeText: string | null | undefined,\n ) => {\n return maybeText?.replaceAll(/[\\ue003-\\uf8aa]/g, \"\");\n };\n\n const ariaLabel = [\n (refs.reference.current as HTMLElement | null)?.textContent,\n refs.description.current?.textContent,\n ]\n .map(filterMaterialSymbols)\n .filter(Boolean)\n .join(\". \");\n\n if (React.isValidElement(children)) {\n return React.cloneElement(\n children,\n getReferenceProps({\n ref,\n \"aria-label\": ariaLabel,\n ...children.props,\n ...props,\n className: clsx(children.props.className, className),\n \"data-tooltip-shown\": isOpen,\n style: { ...children.props.style },\n tabIndex: triggerOn === \"click\" ? 0 : undefined,\n onBlur: () => {\n children.props.onBlur && children.props.onBlur();\n handleBlur();\n },\n }),\n );\n }\n\n return (\n <button\n data-tooltip-shown={isOpen}\n {...getReferenceProps({\n className: clsx(className, \"jkl-tooltip-trigger\"),\n // Sørg for at vi ikke sender inn skjemaer ved klikk på knappen\n type: \"button\",\n ref,\n onBlur: handleBlur,\n \"aria-label\": ariaLabel,\n ...props,\n })}\n >\n {children}\n </button>\n );\n },\n);\n"],"names":["TooltipTrigger","forwardRef","children","className","props","forwardedRef","isOpen","setOpen","getReferenceProps","refs","triggerOn","useTooltipContext","childrenRef","ref","useMergeRefs","setReference","handleBlur","ariaLabel","_a","reference","current","textContent","_b","description","map","maybeText","replaceAll","filter","Boolean","join","React","isValidElement","cloneElement","clsx","style","tabIndex","onBlur","jsx","type"],"mappings":"2OAKaA,EAAiBC,EAAAA,YAC1B,UAA0BC,SAAAA,EAAUC,UAAAA,KAAcC,GAASC,WACvD,MAAQC,OAAAA,EAAQC,QAAAA,EAASC,kBAAAA,EAAmBC,KAAAA,EAAMC,UAAAA,GAC9CC,EAAAA,oBACEC,EAAeV,EAAiBW,IAChCA,EAAMC,EAAAA,aAAa,CACrBF,EACAH,EAAKM,aACLV,IAGEW,EAAa,KACD,UAAAN,GAAWH,GAAQ,EAAK,EASpCU,EAAY,CACb,OAAAC,EAAAT,EAAKU,UAAUC,cAAfF,EAAAA,EAA+CG,YAChD,OAAAC,EAAAb,EAAKc,YAAYH,cAAjBE,EAAAA,EAA0BD,aAEzBG,KATDC,GAEO,MAAAA,OAAA,EAAAA,EAAWC,WAAW,mBAAoB,MAQhDC,OAAOC,SACPC,KAAK,MAEN,OAAAC,EAAMC,eAAe7B,GACd4B,EAAME,aACT9B,EACAM,EAAkB,CACdK,IAAAA,EACA,aAAcI,KACXf,EAASE,SACTA,EACHD,UAAW8B,EAAAA,KAAK/B,EAASE,MAAMD,UAAWA,GAC1C,qBAAsBG,EACtB4B,MAAO,IAAKhC,EAASE,MAAM8B,OAC3BC,SAAwB,UAAdzB,EAAwB,OAAI,EACtC0B,OAAQ,KACJlC,EAASE,MAAMgC,QAAUlC,EAASE,MAAMgC,SAC7BpB,QAOvBqB,EAAAA,IAAC,SAAA,CACG,qBAAoB/B,KAChBE,EAAkB,CAClBL,UAAW8B,EAAAA,KAAK9B,EAAW,uBAE3BmC,KAAM,SACNzB,IAAAA,EACAuB,OAAQpB,EACR,aAAcC,KACXb,IAGNF,SAAAA,GAGb"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsxs as e,jsx as
|
|
1
|
+
import{jsxs as e,jsx as s}from"react/jsx-runtime";import{useFloatingTree as t,useFloatingNodeId as n,useFloatingParentNodeId as o,useFloating as a,offset as r,flip as i,shift as l,autoUpdate as u,useInteractions as d,useHover as c,safePolygon as m,useClick as p,useDismiss as f,useRole as g,useListNavigation as h,useMergeRefs as v,useTransitionStyles as y,FloatingNode as k,FloatingPortal as x,FloatingFocusManager as F,FloatingTree as P}from"@floating-ui/react";import{c as w}from"../../../clsx-BeLtu-UY.js";import j,{forwardRef as E,useRef as I,useState as M,useEffect as R}from"react";import*as C from"react-is";import{useBrowserPreferences as N}from"../../hooks/useBrowserPreferences/useBrowserPreferences.js";import"../../hooks/useScreen/useScreen.js";import{useId as b}from"../../hooks/useId/useId.js";import{getThemeAndDensity as O}from"../../utilities/getThemeAndDensity.js";import{useMenuWideEvents as T}from"./useMenuWideEvents.js";function D(e,s=0){switch(e){case"top":default:return`0 ${s}px`;case"left":return`${s}px 0`;case"bottom":return`0 ${-s}px`;case"right":return-s+"px 0"}}const S=E(((P,E)=>{const{children:S,className:A,initialPlacement:B,openOnHover:H=!1,keepOpenOnClickOutside:$=!1,triggerElement:K,isOpen:V,onToggle:W,...q}=P,L=b("jkl-menu"),{prefersReducedMotion:U}=N(),z=t(),G=n(),J=o(),Q=null!=J,X=I([]),[Y,Z]=M(null),{allowHover:_,isOpen:ee,setIsOpen:se}=T(z,G,J),te=void 0!==V?V:ee;R((()=>null==W?void 0:W(te)),[te,W]);const{refs:ne,placement:oe,context:ae,floatingStyles:re}=a({nodeId:G,open:te,onOpenChange:se,placement:B||(Q?"right-start":"bottom-start"),middleware:[r(2),i({fallbackAxisSideDirection:"end",crossAxis:!1}),l({padding:8})],whileElementsMounted:u}),{getReferenceProps:ie,getFloatingProps:le,getItemProps:ue}=d([c(ae,{enabled:H&&_,delay:{open:75},handleClose:m({requireIntent:!0,blockPointerEvents:!0})}),p(ae,{event:"mousedown"}),f(ae,{outsidePress:!$}),g(ae,{role:"menu"}),h(ae,{listRef:X,activeIndex:Y,nested:Q,onNavigate:Z})]),de=v([ne.setReference,E]),{theme:ce,density:me}=O(ne.reference.current),{isMounted:pe,styles:fe}=y(ae,{duration:{open:U?0:250,close:U?0:150},initial:({side:e})=>({opacity:0,translate:D(e,5)}),open:({side:e})=>({opacity:1,translate:D(e,0)}),close:({side:e})=>({opacity:0,translate:D(e,5)})});return e(k,{id:G,children:[j.isValidElement(K)&&("button"===K.type||C.isForwardRef(K))?j.cloneElement(K,{...ie({...q,ref:de,role:Q?"menuitem":void 0,"aria-controls":L,onClick(e){e.stopPropagation()}})}):K,pe&&s(x,{children:s(F,{context:ae,modal:!1,initialFocus:Q?-1:0,returnFocus:!Q,children:s("div",{className:w("jkl jkl-menu",A),"data-theme":ce,"data-layout-density":me,role:"menu","data-placement":oe,"aria-live":"assertive","aria-hidden":!te,ref:ne.setFloating,...le({id:L,style:{...re,...fe}}),children:j.Children.map(S,((e,s)=>j.isValidElement(e)&&C.isForwardRef(e)?j.cloneElement(e,ue({...e.props,tabIndex:Y===s?0:-1,role:"menuitem",ref(e){X.current[s]=e},onClick(s){var t,n;null==(n=(t=e.props).onClick)||n.call(t,s),!s.defaultPrevented&&(null==z||z.events.emit("click"))},onKeyDown(s){var t,n;null==(n=(t=e.props).onKeyDown)||n.call(t,s),!s.defaultPrevented&&(null==z||z.events.emit("keydown"),"menuitemcheckbox"===s.currentTarget.role&&"Enter"===s.key&&se(!1))},onMouseEnter(){_&&te&&Z(s)}})):e))})})})]})}));S.displayName="MenuComponent";const A=E(((e,t)=>null===o()?s(P,{children:s(S,{ref:t,...e})}):s(S,{ref:t,...e})));A.displayName="Menu";export{A as Menu};
|
|
2
2
|
//# sourceMappingURL=Menu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.js","sources":["../../../../src/components/menu/Menu.tsx"],"sourcesContent":["import {\n autoUpdate,\n flip,\n FloatingFocusManager,\n FloatingNode,\n FloatingPortal,\n FloatingTree,\n offset,\n type Placement,\n safePolygon,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListNavigation,\n useMergeRefs,\n useRole,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport React, {\n type ButtonHTMLAttributes,\n forwardRef,\n type ReactNode,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport * as ReactIs from \"react-is\";\nimport { DataTestAutoId, WithChildren } from \"../../core/types.js\";\nimport { useId } from \"../../hooks/useId/useId.js\";\nimport { getThemeAndDensity } from \"../../utilities/getThemeAndDensity.js\";\nimport { useMenuWideEvents } from \"./useMenuWideEvents.js\";\n\nexport interface MenuProps\n extends DataTestAutoId,\n WithChildren,\n Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"children\"> {\n className?: string;\n /**\n * Initiell plassering av menyen. Dersom det ikke er plass på skjermen der du\n * angir at den skal åpnes vil den slyttes automatisk.\n * @default \"bottom-start\" på toppnivå, \"right-start\" for undermenyer\n * */\n initialPlacement?: Placement;\n /**\n * Angir om menyen skal åpnes ved hover (uten å måtte klikke)\n * @default false\n */\n openOnHover?: boolean;\n /**\n * Angir om menyen skal holdes åpen når man klikker utenfor menyen\n * @default false\n */\n keepOpenOnClickOutside?: boolean;\n /**\n * Elementet som fungerer som trigger for menyen. Dersom elementet ikke er en `<button>`\n * eller en `forwardRef<HTMLButtonElement>` vil det bli lagt inne i en knapp\n * med forhåndsdefinert stil. For å komme raskt i gang kan du bruke komponenten\n * `MenuTriggerButton` fra denne pakken.\n */\n triggerElement: ReactNode;\n /**\n * Kan brukes til å styre utenfra om menyen skal være åpen eller ikke.\n * @default false\n */\n isOpen?: boolean;\n /**\n * Callback som kalles når menyen åpnes eller lukkes.\n */\n onToggle?: (isOpen: boolean) => void;\n}\n\nconst MenuComponent = forwardRef<HTMLButtonElement, MenuProps>(\n (props, forwardedRef) => {\n const {\n children,\n className,\n initialPlacement,\n openOnHover = false,\n keepOpenOnClickOutside = false,\n triggerElement,\n isOpen: isOpenOverride,\n onToggle,\n ...triggerProps\n } = props;\n\n const MenuId = useId(\"jkl-menu\");\n\n const tree = useFloatingTree();\n const nodeId = useFloatingNodeId();\n const parentId = useFloatingParentNodeId();\n const isNested = parentId != null;\n\n const listItemsRef = useRef<Array<HTMLButtonElement | null>>([]);\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const {\n allowHover,\n isOpen: isOpenDefault,\n setIsOpen,\n } = useMenuWideEvents(tree, nodeId, parentId);\n\n const isOpen =\n isOpenOverride !== undefined ? isOpenOverride : isOpenDefault;\n\n useEffect(() => onToggle?.(isOpen), [isOpen, onToggle]);\n\n const { x, y, refs, placement, strategy, context } = useFloating({\n nodeId,\n open: isOpen,\n onOpenChange: setIsOpen,\n placement:\n initialPlacement || (isNested ? \"right-start\" : \"bottom-start\"),\n middleware: [\n offset(2),\n flip({\n fallbackAxisSideDirection: \"end\", // Allow bottom placement in narrow viewports (https://floating-ui.com/docs/flip#fallbackaxissidedirection)\n crossAxis: false, // See https://floating-ui.com/docs/flip#combining-with-shift\n }),\n shift({ padding: 8 }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const { getReferenceProps, getFloatingProps, getItemProps } =\n useInteractions([\n useHover(context, {\n enabled: openOnHover && allowHover,\n delay: { open: 75 },\n handleClose: safePolygon({\n requireIntent: true,\n blockPointerEvents: true,\n }),\n }),\n useClick(context, {\n event: \"mousedown\",\n }),\n useDismiss(context, { outsidePress: !keepOpenOnClickOutside }),\n useRole(context, { role: \"menu\" }),\n useListNavigation(context, {\n listRef: listItemsRef,\n activeIndex,\n nested: isNested,\n onNavigate: setActiveIndex,\n }),\n ]);\n\n const referenceRef = useMergeRefs([refs.setReference, forwardedRef]);\n\n // Siden menyen rendres på rot må vi hente lokal dark/light-verdi fra triggeren\n // Vi må gjøre dette for å ta hensyn til at tema kan styres lokalt for deler av UIet\n const { theme, density } = getThemeAndDensity(\n refs.reference.current as HTMLElement,\n );\n\n return (\n <FloatingNode id={nodeId}>\n {React.isValidElement(triggerElement) &&\n (triggerElement.type === \"button\" ||\n ReactIs.isForwardRef(triggerElement))\n ? // Dersom trigger-elementet er en knapp, sett riktige egenskaper på det\n React.cloneElement(triggerElement, {\n ...getReferenceProps({\n ...triggerProps,\n ref: referenceRef,\n role: isNested ? \"menuitem\" : undefined,\n \"aria-controls\": MenuId,\n onClick(event) {\n event.stopPropagation();\n },\n }),\n })\n : // Ellers, rendre elementet as-is, uten interaktivitet. Krev en ferdig brukbar button for å åpne menyen.\n triggerElement}\n <AnimatePresence>\n {isOpen && (\n <FloatingPortal>\n <FloatingFocusManager\n context={context}\n // Prevent outside content interference.\n modal={false}\n // Only initially focus the root floating menu.\n initialFocus={isNested ? -1 : 0}\n // Only return focus to the root menu's reference when menus close.\n returnFocus={!isNested}\n >\n <motion.div\n className={clsx(\"jkl jkl-menu\", className)}\n data-theme={theme}\n data-layout-density={density}\n role=\"menu\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{\n ease: \"easeIn\",\n duration: 0.1,\n }}\n data-placement={placement}\n aria-live=\"assertive\"\n aria-hidden={!isOpen}\n ref={refs.setFloating}\n {...getFloatingProps({\n id: MenuId,\n style: {\n position: strategy,\n top: y ?? \"\",\n left: x ?? \"\",\n },\n })}\n >\n {React.Children.map(\n children,\n (child, index) => {\n if (\n React.isValidElement(child) &&\n ReactIs.isForwardRef(child)\n ) {\n return React.cloneElement(\n child,\n getItemProps({\n ...child.props,\n tabIndex:\n activeIndex ===\n index\n ? 0\n : -1,\n role: \"menuitem\",\n ref(\n node: HTMLButtonElement,\n ) {\n listItemsRef.current[\n index\n ] = node;\n },\n onClick(event) {\n child.props.onClick?.(\n event as React.MouseEvent<HTMLButtonElement>,\n );\n if (\n event.defaultPrevented\n ) {\n return;\n }\n tree?.events.emit(\n \"click\",\n );\n },\n onKeyDown(event) {\n child.props.onKeyDown?.(\n event,\n );\n if (\n event.defaultPrevented\n ) {\n return;\n }\n tree?.events.emit(\n \"keydown\",\n );\n if (\n event\n .currentTarget\n .role ===\n \"menuitemcheckbox\" &&\n event.key ===\n \"Enter\"\n ) {\n // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/menuitemcheckbox_role#keyboard_interactions\n setIsOpen(\n false,\n );\n }\n },\n onMouseEnter() {\n if (\n allowHover &&\n isOpen\n ) {\n setActiveIndex(\n index,\n );\n }\n },\n }),\n );\n }\n\n return child;\n },\n )}\n </motion.div>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </AnimatePresence>\n </FloatingNode>\n );\n },\n);\nMenuComponent.displayName = \"MenuComponent\";\n\nexport const Menu = forwardRef<HTMLButtonElement, MenuProps>((props, ref) => {\n const parentId = useFloatingParentNodeId();\n\n if (parentId === null) {\n return (\n <FloatingTree>\n <MenuComponent ref={ref} {...props} />\n </FloatingTree>\n );\n }\n\n return <MenuComponent ref={ref} {...props} />;\n});\nMenu.displayName = \"Menu\";\n"],"names":["MenuComponent","forwardRef","props","forwardedRef","children","className","initialPlacement","openOnHover","keepOpenOnClickOutside","triggerElement","isOpen","isOpenOverride","onToggle","triggerProps","MenuId","useId","tree","useFloatingTree","nodeId","useFloatingNodeId","parentId","useFloatingParentNodeId","isNested","listItemsRef","useRef","activeIndex","setActiveIndex","useState","allowHover","isOpenDefault","setIsOpen","useMenuWideEvents","useEffect","x","y","refs","placement","strategy","context","useFloating","open","onOpenChange","middleware","offset","flip","fallbackAxisSideDirection","crossAxis","shift","padding","whileElementsMounted","autoUpdate","getReferenceProps","getFloatingProps","getItemProps","useInteractions","useHover","enabled","delay","handleClose","safePolygon","requireIntent","blockPointerEvents","useClick","event","useDismiss","outsidePress","useRole","role","useListNavigation","listRef","nested","onNavigate","referenceRef","useMergeRefs","setReference","theme","density","getThemeAndDensity","reference","current","jsxs","FloatingNode","id","React","isValidElement","type","ReactIs","isForwardRef","cloneElement","ref","onClick","stopPropagation","jsx","AnimatePresence","FloatingPortal","FloatingFocusManager","modal","initialFocus","returnFocus","motion","div","clsx","initial","opacity","animate","exit","transition","ease","duration","setFloating","style","position","top","left","Children","map","child","index","tabIndex","node","_b","_a","call","defaultPrevented","events","emit","onKeyDown","currentTarget","key","onMouseEnter","displayName","Menu","FloatingTree"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Menu.js","sources":["../../../../src/components/menu/Menu.tsx"],"sourcesContent":["import {\n autoUpdate,\n flip,\n FloatingFocusManager,\n FloatingNode,\n FloatingPortal,\n FloatingTree,\n offset,\n type Placement,\n safePolygon,\n shift,\n Side,\n useClick,\n useDismiss,\n useFloating,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListNavigation,\n useMergeRefs,\n useRole,\n useTransitionStyles,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport React, {\n type ButtonHTMLAttributes,\n forwardRef,\n type ReactNode,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport * as ReactIs from \"react-is\";\nimport { DataTestAutoId, WithChildren } from \"../../core/types.js\";\nimport { useBrowserPreferences } from \"../../hooks/index.js\";\nimport { useId } from \"../../hooks/useId/useId.js\";\nimport { getThemeAndDensity } from \"../../utilities/getThemeAndDensity.js\";\nimport { useMenuWideEvents } from \"./useMenuWideEvents.js\";\n\nexport interface MenuProps\n extends DataTestAutoId,\n WithChildren,\n Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"children\"> {\n className?: string;\n /**\n * Initiell plassering av menyen. Dersom det ikke er plass på skjermen der du\n * angir at den skal åpnes vil den slyttes automatisk.\n * @default \"bottom-start\" på toppnivå, \"right-start\" for undermenyer\n * */\n initialPlacement?: Placement;\n /**\n * Angir om menyen skal åpnes ved hover (uten å måtte klikke)\n * @default false\n */\n openOnHover?: boolean;\n /**\n * Angir om menyen skal holdes åpen når man klikker utenfor menyen\n * @default false\n */\n keepOpenOnClickOutside?: boolean;\n /**\n * Elementet som fungerer som trigger for menyen. Dersom elementet ikke er en `<button>`\n * eller en `forwardRef<HTMLButtonElement>` vil det bli lagt inne i en knapp\n * med forhåndsdefinert stil. For å komme raskt i gang kan du bruke komponenten\n * `MenuTriggerButton` fra denne pakken.\n */\n triggerElement: ReactNode;\n /**\n * Kan brukes til å styre utenfra om menyen skal være åpen eller ikke.\n * @default false\n */\n isOpen?: boolean;\n /**\n * Callback som kalles når menyen åpnes eller lukkes.\n */\n onToggle?: (isOpen: boolean) => void;\n}\n\nfunction getTranslation(side: Side, value: number = 0) {\n switch (side) {\n case \"top\":\n return `0 ${value}px`;\n case \"left\":\n return `${value}px 0`;\n case \"bottom\":\n return `0 ${-value}px`;\n case \"right\":\n return `${-value}px 0`;\n\n default:\n return `0 ${value}px`;\n }\n}\n\nconst MenuComponent = forwardRef<HTMLButtonElement, MenuProps>(\n (props, forwardedRef) => {\n const {\n children,\n className,\n initialPlacement,\n openOnHover = false,\n keepOpenOnClickOutside = false,\n triggerElement,\n isOpen: isOpenOverride,\n onToggle,\n ...triggerProps\n } = props;\n\n const MenuId = useId(\"jkl-menu\");\n\n const { prefersReducedMotion } = useBrowserPreferences();\n\n const tree = useFloatingTree();\n const nodeId = useFloatingNodeId();\n const parentId = useFloatingParentNodeId();\n const isNested = parentId != null;\n\n const listItemsRef = useRef<Array<HTMLButtonElement | null>>([]);\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const {\n allowHover,\n isOpen: isOpenDefault,\n setIsOpen,\n } = useMenuWideEvents(tree, nodeId, parentId);\n\n const isOpen =\n isOpenOverride !== undefined ? isOpenOverride : isOpenDefault;\n\n useEffect(() => onToggle?.(isOpen), [isOpen, onToggle]);\n\n const { refs, placement, context, floatingStyles } = useFloating({\n nodeId,\n open: isOpen,\n onOpenChange: setIsOpen,\n placement:\n initialPlacement || (isNested ? \"right-start\" : \"bottom-start\"),\n middleware: [\n offset(2),\n flip({\n fallbackAxisSideDirection: \"end\", // Allow bottom placement in narrow viewports (https://floating-ui.com/docs/flip#fallbackaxissidedirection)\n crossAxis: false, // See https://floating-ui.com/docs/flip#combining-with-shift\n }),\n shift({ padding: 8 }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const { getReferenceProps, getFloatingProps, getItemProps } =\n useInteractions([\n useHover(context, {\n enabled: openOnHover && allowHover,\n delay: { open: 75 },\n handleClose: safePolygon({\n requireIntent: true,\n blockPointerEvents: true,\n }),\n }),\n useClick(context, {\n event: \"mousedown\",\n }),\n useDismiss(context, { outsidePress: !keepOpenOnClickOutside }),\n useRole(context, { role: \"menu\" }),\n useListNavigation(context, {\n listRef: listItemsRef,\n activeIndex,\n nested: isNested,\n onNavigate: setActiveIndex,\n }),\n ]);\n\n const referenceRef = useMergeRefs([refs.setReference, forwardedRef]);\n\n // Siden menyen rendres på rot må vi hente lokal dark/light-verdi fra triggeren\n // Vi må gjøre dette for å ta hensyn til at tema kan styres lokalt for deler av UIet\n const { theme, density } = getThemeAndDensity(\n refs.reference.current as HTMLElement,\n );\n\n const { isMounted, styles: animationStyles } = useTransitionStyles(\n context,\n {\n duration: {\n open: prefersReducedMotion ? 0 : 250,\n close: prefersReducedMotion ? 0 : 150,\n },\n initial: ({ side }) => ({\n opacity: 0,\n translate: getTranslation(side, 5),\n }),\n open: ({ side }) => ({\n opacity: 1,\n translate: getTranslation(side, 0),\n }),\n close: ({ side }) => ({\n opacity: 0,\n translate: getTranslation(side, 5),\n }),\n },\n );\n\n return (\n <FloatingNode id={nodeId}>\n {React.isValidElement(triggerElement) &&\n (triggerElement.type === \"button\" ||\n ReactIs.isForwardRef(triggerElement))\n ? // Dersom trigger-elementet er en knapp, sett riktige egenskaper på det\n React.cloneElement(triggerElement, {\n ...getReferenceProps({\n ...triggerProps,\n ref: referenceRef,\n role: isNested ? \"menuitem\" : undefined,\n \"aria-controls\": MenuId,\n onClick(event) {\n event.stopPropagation();\n },\n }),\n })\n : // Ellers, rendre elementet as-is, uten interaktivitet. Krev en ferdig brukbar button for å åpne menyen.\n triggerElement}\n {isMounted && (\n <FloatingPortal>\n <FloatingFocusManager\n context={context}\n // Prevent outside content interference.\n modal={false}\n // Only initially focus the root floating menu.\n initialFocus={isNested ? -1 : 0}\n // Only return focus to the root menu's reference when menus close.\n returnFocus={!isNested}\n >\n <div\n className={clsx(\"jkl jkl-menu\", className)}\n data-theme={theme}\n data-layout-density={density}\n role=\"menu\"\n data-placement={placement}\n aria-live=\"assertive\"\n aria-hidden={!isOpen}\n ref={refs.setFloating}\n {...getFloatingProps({\n id: MenuId,\n style: {\n ...floatingStyles,\n ...animationStyles,\n },\n })}\n >\n {React.Children.map(\n children,\n (child, index) => {\n if (\n React.isValidElement(child) &&\n ReactIs.isForwardRef(child)\n ) {\n return React.cloneElement(\n child,\n getItemProps({\n ...child.props,\n tabIndex:\n activeIndex === index\n ? 0\n : -1,\n role: \"menuitem\",\n ref(\n node: HTMLButtonElement,\n ) {\n listItemsRef.current[\n index\n ] = node;\n },\n onClick(event) {\n child.props.onClick?.(\n event as React.MouseEvent<HTMLButtonElement>,\n );\n if (\n event.defaultPrevented\n ) {\n return;\n }\n tree?.events.emit(\n \"click\",\n );\n },\n onKeyDown(event) {\n child.props.onKeyDown?.(\n event,\n );\n if (\n event.defaultPrevented\n ) {\n return;\n }\n tree?.events.emit(\n \"keydown\",\n );\n if (\n event.currentTarget\n .role ===\n \"menuitemcheckbox\" &&\n event.key ===\n \"Enter\"\n ) {\n // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/menuitemcheckbox_role#keyboard_interactions\n setIsOpen(false);\n }\n },\n onMouseEnter() {\n if (\n allowHover &&\n isOpen\n ) {\n setActiveIndex(\n index,\n );\n }\n },\n }),\n );\n }\n\n return child;\n },\n )}\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </FloatingNode>\n );\n },\n);\nMenuComponent.displayName = \"MenuComponent\";\n\nexport const Menu = forwardRef<HTMLButtonElement, MenuProps>((props, ref) => {\n const parentId = useFloatingParentNodeId();\n\n if (parentId === null) {\n return (\n <FloatingTree>\n <MenuComponent ref={ref} {...props} />\n </FloatingTree>\n );\n }\n\n return <MenuComponent ref={ref} {...props} />;\n});\nMenu.displayName = \"Menu\";\n"],"names":["getTranslation","side","value","MenuComponent","forwardRef","props","forwardedRef","children","className","initialPlacement","openOnHover","keepOpenOnClickOutside","triggerElement","isOpen","isOpenOverride","onToggle","triggerProps","MenuId","useId","prefersReducedMotion","useBrowserPreferences","tree","useFloatingTree","nodeId","useFloatingNodeId","parentId","useFloatingParentNodeId","isNested","listItemsRef","useRef","activeIndex","setActiveIndex","useState","allowHover","isOpenDefault","setIsOpen","useMenuWideEvents","useEffect","refs","placement","context","floatingStyles","useFloating","open","onOpenChange","middleware","offset","flip","fallbackAxisSideDirection","crossAxis","shift","padding","whileElementsMounted","autoUpdate","getReferenceProps","getFloatingProps","getItemProps","useInteractions","useHover","enabled","delay","handleClose","safePolygon","requireIntent","blockPointerEvents","useClick","event","useDismiss","outsidePress","useRole","role","useListNavigation","listRef","nested","onNavigate","referenceRef","useMergeRefs","setReference","theme","density","getThemeAndDensity","reference","current","isMounted","styles","animationStyles","useTransitionStyles","duration","close","initial","opacity","translate","jsxs","FloatingNode","id","React","isValidElement","type","ReactIs","isForwardRef","cloneElement","ref","onClick","stopPropagation","FloatingPortal","jsx","FloatingFocusManager","modal","initialFocus","returnFocus","clsx","setFloating","style","Children","map","child","index","tabIndex","node","_b","_a","call","defaultPrevented","events","emit","onKeyDown","currentTarget","key","onMouseEnter","displayName","Menu","FloatingTree"],"mappings":"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"}
|
|
@@ -29,7 +29,7 @@ type UseTooltipReturn = {
|
|
|
29
29
|
triggerOn: NonNullable<TooltipProps["triggerOn"]>;
|
|
30
30
|
isOpen: boolean;
|
|
31
31
|
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
|
32
|
-
arrowElement: React.RefObject<
|
|
32
|
+
arrowElement: React.RefObject<SVGSVGElement>;
|
|
33
33
|
refs: {
|
|
34
34
|
description: React.MutableRefObject<HTMLElement | null>;
|
|
35
35
|
setDescription: (element: HTMLElement | null) => void;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e}from"react/jsx-runtime";import{useFloating as t,autoUpdate as n,offset as o,flip as s,shift as r,arrow as a,useRole as i,useDismiss as l,useClick as c,useHover as u,useFocus as p,useInteractions as d}from"@floating-ui/react";import{createContext as m,useContext as f,useState as x,useRef as g}from"react";const h=m(null),k=h.Provider,v=()=>{const e=f(h);if(null===e)throw new Error("Tooltip-komponentene kan kun brukes inne i <Tooltip />");return e},w=({children:m,...f})=>{const h=(({initialOpen:e=!1,placement:m="top",delay:f=250,triggerOn:h="hover"})=>{const[k,v]=x(e),w=g(null),O=g(null),C=t({open:k,onOpenChange:v,placement:m,whileElementsMounted:n,middleware:[o(16),s(),r({padding:16}),a({element:w,padding:
|
|
1
|
+
import{jsx as e}from"react/jsx-runtime";import{useFloating as t,autoUpdate as n,offset as o,flip as s,shift as r,arrow as a,useRole as i,useDismiss as l,useClick as c,useHover as u,useFocus as p,useInteractions as d}from"@floating-ui/react";import{createContext as m,useContext as f,useState as x,useRef as g}from"react";const h=m(null),k=h.Provider,v=()=>{const e=f(h);if(null===e)throw new Error("Tooltip-komponentene kan kun brukes inne i <Tooltip />");return e},w=({children:m,...f})=>{const h=(({initialOpen:e=!1,placement:m="top",delay:f=250,triggerOn:h="hover"})=>{const[k,v]=x(e),w=g(null),O=g(null),C=t({open:k,onOpenChange:v,placement:m,whileElementsMounted:n,middleware:[o(16),s(),r({padding:16}),a({element:w,padding:8})]}),T=i(C.context,{role:"tooltip"}),b=l(C.context,{referencePress:!1}),E=c(C.context,{enabled:"click"===h&&!k}),P=u(C.context,{enabled:"hover"===h,delay:k?0:f}),j=p(C.context,{enabled:"click"!==h||k}),y=d([b,j,T,E,P]);return{triggerOn:h,isOpen:k,setOpen:v,arrowElement:w,...C,refs:{...C.refs,description:O,setDescription:e=>O.current=e},...y}})(f);return e(k,{value:h,children:m})};export{w as Tooltip,k as TooltipProvider,v as useTooltipContext};
|
|
2
2
|
//# sourceMappingURL=Tooltip.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.js","sources":["../../../../src/components/tooltip/Tooltip.tsx"],"sourcesContent":["import {\n type Placement,\n type UseFloatingReturn,\n arrow,\n autoUpdate,\n flip,\n offset,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFocus,\n useHover,\n useInteractions,\n useRole,\n} from \"@floating-ui/react\";\nimport React, { FC, createContext, useContext, useRef, useState } from \"react\";\nimport { type WithChildren } from \"../../core/types.js\";\n\nexport type TooltipPlacement = Extract<\n Placement,\n \"top-start\" | \"top-end\" | \"left\" | \"right\" | \"top\"\n>;\n\nexport interface TooltipProps {\n /**\n * Sett til true dersom du ønsker at tooltipen skal være åpen som default\n * @default false\n */\n initialOpen?: boolean;\n /**\n * Plassering av tooltipen i forhold til triggeren. Tooltipen vil automatisk\n * bytte posisjon dersom det ikke er plass.\n * @default \"top\"\n */\n placement?: TooltipPlacement;\n /**\n * Valgfri forsinkelse før tooltipen åpner. Ignoreres dersom triggerOn er satt til \"click\"\n * @default 250\n */\n delay?: number;\n /**\n * Angir om tooltipen skal åpnes ved klikk eller hover\n * @default \"hover\"\n */\n triggerOn?: \"click\" | \"hover\";\n}\n\ntype UseTooltipReturn = {\n triggerOn: NonNullable<TooltipProps[\"triggerOn\"]>;\n isOpen: boolean;\n setOpen: React.Dispatch<React.SetStateAction<boolean>>;\n arrowElement: React.RefObject<
|
|
1
|
+
{"version":3,"file":"Tooltip.js","sources":["../../../../src/components/tooltip/Tooltip.tsx"],"sourcesContent":["import {\n type Placement,\n type UseFloatingReturn,\n arrow,\n autoUpdate,\n flip,\n offset,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFocus,\n useHover,\n useInteractions,\n useRole,\n} from \"@floating-ui/react\";\nimport React, { FC, createContext, useContext, useRef, useState } from \"react\";\nimport { type WithChildren } from \"../../core/types.js\";\n\nexport type TooltipPlacement = Extract<\n Placement,\n \"top-start\" | \"top-end\" | \"left\" | \"right\" | \"top\"\n>;\n\nexport interface TooltipProps {\n /**\n * Sett til true dersom du ønsker at tooltipen skal være åpen som default\n * @default false\n */\n initialOpen?: boolean;\n /**\n * Plassering av tooltipen i forhold til triggeren. Tooltipen vil automatisk\n * bytte posisjon dersom det ikke er plass.\n * @default \"top\"\n */\n placement?: TooltipPlacement;\n /**\n * Valgfri forsinkelse før tooltipen åpner. Ignoreres dersom triggerOn er satt til \"click\"\n * @default 250\n */\n delay?: number;\n /**\n * Angir om tooltipen skal åpnes ved klikk eller hover\n * @default \"hover\"\n */\n triggerOn?: \"click\" | \"hover\";\n}\n\ntype UseTooltipReturn = {\n triggerOn: NonNullable<TooltipProps[\"triggerOn\"]>;\n isOpen: boolean;\n setOpen: React.Dispatch<React.SetStateAction<boolean>>;\n arrowElement: React.RefObject<SVGSVGElement>;\n refs: {\n description: React.MutableRefObject<HTMLElement | null>;\n setDescription: (element: HTMLElement | null) => void;\n } & UseFloatingReturn[\"refs\"];\n} & UseFloatingReturn &\n ReturnType<typeof useInteractions>;\n\nconst useTooltip = ({\n initialOpen = false,\n placement = \"top\",\n delay = 250,\n triggerOn = \"hover\",\n}: TooltipProps): UseTooltipReturn => {\n const [isOpen, setOpen] = useState(initialOpen);\n const arrowElement = useRef<SVGSVGElement>(null);\n const description = useRef<HTMLElement | null>(null);\n const setDescription = (element: HTMLElement | null) =>\n (description.current = element);\n\n const data = useFloating({\n open: isOpen,\n onOpenChange: setOpen,\n placement,\n whileElementsMounted: autoUpdate,\n middleware: [\n offset(16),\n flip(),\n shift({ padding: 16 }),\n arrow({ element: arrowElement, padding: 8 }),\n ],\n });\n\n const role = useRole(data.context, { role: \"tooltip\" });\n const dismiss = useDismiss(data.context, { referencePress: false });\n const click = useClick(data.context, {\n enabled: triggerOn === \"click\" && !isOpen,\n });\n const hover = useHover(data.context, {\n enabled: triggerOn === \"hover\",\n delay: isOpen ? 0 : delay,\n });\n const focus = useFocus(data.context, {\n enabled: triggerOn === \"click\" ? isOpen : true,\n });\n\n const interactions = useInteractions([dismiss, focus, role, click, hover]);\n\n return {\n triggerOn,\n isOpen,\n setOpen,\n arrowElement,\n ...data,\n refs: {\n ...data.refs,\n description,\n setDescription,\n },\n ...interactions,\n };\n};\n\nexport type TooltipContext = ReturnType<typeof useTooltip> | null;\n\nconst tooltipContext = createContext<TooltipContext>(null);\n\nexport const TooltipProvider = tooltipContext.Provider;\n\nexport const useTooltipContext = () => {\n const context = useContext(tooltipContext);\n\n if (context === null) {\n throw new Error(\n \"Tooltip-komponentene kan kun brukes inne i <Tooltip />\",\n );\n }\n\n return context;\n};\n\nexport const Tooltip: FC<TooltipProps & WithChildren> = ({\n children,\n ...options\n}) => {\n const tooltip = useTooltip(options);\n\n return <TooltipProvider value={tooltip}>{children}</TooltipProvider>;\n};\n"],"names":["tooltipContext","createContext","TooltipProvider","Provider","useTooltipContext","context","useContext","Error","Tooltip","children","options","tooltip","initialOpen","placement","delay","triggerOn","isOpen","setOpen","useState","arrowElement","useRef","description","data","useFloating","open","onOpenChange","whileElementsMounted","autoUpdate","middleware","offset","flip","shift","padding","arrow","element","role","useRole","dismiss","useDismiss","referencePress","click","useClick","enabled","hover","useHover","focus","useFocus","interactions","useInteractions","refs","setDescription","current","useTooltip","jsx","value"],"mappings":"iUA4DA,MAyDMA,EAAiBC,EAA8B,MAExCC,EAAkBF,EAAeG,SAEjCC,EAAoB,KACvBC,MAAAA,EAAUC,EAAWN,GAE3B,GAAgB,OAAZK,EACA,MAAM,IAAIE,MACN,0DAIDF,OAAAA,CAAAA,EAGEG,EAA2C,EACpDC,SAAAA,KACGC,MAEGC,MAAAA,EA7ES,GACfC,YAAAA,GAAc,EACdC,UAAAA,EAAY,MACZC,MAAAA,EAAQ,IACRC,UAAAA,EAAY,YAEN,MAACC,EAAQC,GAAWC,EAASN,GAC7BO,EAAeC,EAAsB,MACrCC,EAAcD,EAA2B,MAIzCE,EAAOC,EAAY,CACrBC,KAAMR,EACNS,aAAcR,EACdJ,UAAAA,EACAa,qBAAsBC,EACtBC,WAAY,CACRC,EAAO,IACPC,IACAC,EAAM,CAAEC,QAAS,KACjBC,EAAM,CAAEC,QAASf,EAAca,QAAS,OAI1CG,EAAOC,EAAQd,EAAKjB,QAAS,CAAE8B,KAAM,YACrCE,EAAUC,EAAWhB,EAAKjB,QAAS,CAAEkC,gBAAgB,IACrDC,EAAQC,EAASnB,EAAKjB,QAAS,CACjCqC,QAAuB,UAAd3B,IAA0BC,IAEjC2B,EAAQC,EAAStB,EAAKjB,QAAS,CACjCqC,QAAuB,UAAd3B,EACTD,MAAOE,EAAS,EAAIF,IAElB+B,EAAQC,EAASxB,EAAKjB,QAAS,CACjCqC,QAAuB,UAAd3B,GAAwBC,IAG/B+B,EAAeC,EAAgB,CAACX,EAASQ,EAAOV,EAAMK,EAAOG,IAE5D,MAAA,CACH5B,UAAAA,EACAC,OAAAA,EACAC,QAAAA,EACAE,aAAAA,KACGG,EACH2B,KAAM,IACC3B,EAAK2B,KACR5B,YAAAA,EACA6B,eAxCgBhB,GACnBb,EAAY8B,QAAUjB,MAyCpBa,EAAA,EA0BSK,CAAW1C,GAEnB,OAAA2C,EAAAnD,EAAA,CAAgBoD,MAAO3C,EAAUF,SAAAA,GAAS"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{jsxs as e,jsx as t}from"react/jsx-runtime";import{useMergeRefs as r,useTransitionStyles as s,FloatingPortal as o,FloatingArrow as a}from"@floating-ui/react";import{c as i}from"../../../clsx-BeLtu-UY.js";import{forwardRef as n}from"react";import{useBrowserPreferences as l}from"../../hooks/useBrowserPreferences/useBrowserPreferences.js";import{useId as c}from"../../hooks/useId/useId.js";import{getThemeAndDensity as p}from"../../utilities/getThemeAndDensity.js";import{useTooltipContext as d}from"./Tooltip.js";function m(e,t=0){switch(e){case"top":default:return`0 ${t}px`;case"left":return`${t}px 0`;case"bottom":return`0 ${-t}px`;case"right":return-t+"px 0"}}const f=n((function({className:n,children:f,...u},h){const{triggerOn:g,arrowElement:x,getFloatingProps:y,placement:j,floatingStyles:w,refs:k,context:T}=d(),v=r([h,k.setFloating]),P=c("jkl-tooltip-content"),{prefersReducedMotion:$}=l(),{isMounted:F,styles:A}=s(T,{duration:{open:$?0:250,close:$?0:150},initial:({side:e})=>({opacity:0,translate:m(e,5)}),open:({side:e})=>({opacity:1,translate:m(e,0)}),close:({side:e})=>({opacity:0,translate:m(e,-5)})}),{density:B,theme:D}=p(k.reference.current);return e(o,{children:["hover"===g&&t("span",{ref:k.setDescription,hidden:!0,children:f},`${P}-trigger`),F&&t("span",{className:"jkl",children:e("span",{ref:v,"data-placement":j,"aria-live":"click"===g?"assertive":void 0,"data-theme":D,"data-layout-density":B,className:i("jkl-tooltip-content",n),...y({...u,id:P}),style:{...w,...A},children:[f,t(a,{context:T,ref:x,width:24,height:12,fill:"var(--background-color)"})]},P)},`${P}-wrapper`)]})}));export{f as TooltipContent};
|
|
2
2
|
//# sourceMappingURL=TooltipContent.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TooltipContent.js","sources":["../../../../src/components/tooltip/TooltipContent.tsx"],"sourcesContent":["import {\n type
|
|
1
|
+
{"version":3,"file":"TooltipContent.js","sources":["../../../../src/components/tooltip/TooltipContent.tsx"],"sourcesContent":["import {\n FloatingArrow,\n FloatingPortal,\n type Side,\n useMergeRefs,\n useTransitionStyles,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport React, { HTMLProps, forwardRef } from \"react\";\nimport { useBrowserPreferences } from \"../../hooks/useBrowserPreferences/useBrowserPreferences.js\";\nimport { useId } from \"../../hooks/useId/useId.js\";\nimport { getThemeAndDensity } from \"../../utilities/getThemeAndDensity.js\";\nimport { useTooltipContext } from \"./Tooltip.js\";\n\nfunction getTranslation(side: Side, value: number = 0) {\n switch (side) {\n case \"top\":\n return `0 ${value}px`;\n case \"left\":\n return `${value}px 0`;\n case \"bottom\":\n return `0 ${-value}px`;\n case \"right\":\n return `${-value}px 0`;\n\n default:\n return `0 ${value}px`;\n }\n}\n\nexport const TooltipContent = forwardRef<\n HTMLDivElement,\n HTMLProps<HTMLDivElement>\n>(function TooltipContent({ className, children, ...props }, forwardedRef) {\n const {\n triggerOn,\n arrowElement,\n getFloatingProps,\n placement,\n floatingStyles,\n refs,\n context,\n } = useTooltipContext();\n const ref = useMergeRefs([forwardedRef, refs.setFloating]);\n const contentId = useId(\"jkl-tooltip-content\");\n const { prefersReducedMotion } = useBrowserPreferences();\n const { isMounted, styles: animationStyles } = useTransitionStyles(\n context,\n {\n duration: {\n open: prefersReducedMotion ? 0 : 250,\n close: prefersReducedMotion ? 0 : 150,\n },\n initial: ({ side }) => ({\n opacity: 0,\n translate: getTranslation(side, 5),\n }),\n open: ({ side }) => ({\n opacity: 1,\n translate: getTranslation(side, 0),\n }),\n close: ({ side }) => ({\n opacity: 0,\n translate: getTranslation(side, -5),\n }),\n },\n );\n\n // Siden tooltipet rendres på rot må vi hente lokal dark/light-verdi fra triggeren\n // Vi må gjøre dette for å ta hensyn til at tema kan styres lokalt for deler av UIet\n const { density, theme } = getThemeAndDensity(\n refs.reference.current as HTMLElement,\n );\n\n return (\n <FloatingPortal>\n {/* For å kunne bruke tekstinnholdet i tooltip som beskrivende tekst, selv når ikke\n tooltip er synlig, må vi rendre et skjult element å referere til for å hente innholdet. */}\n {triggerOn === \"hover\" && (\n <span\n ref={refs.setDescription}\n hidden\n key={`${contentId}-trigger`}\n >\n {children}\n </span>\n )}\n {isMounted && (\n <span className=\"jkl\" key={`${contentId}-wrapper`}>\n <span\n key={contentId}\n ref={ref}\n data-placement={placement}\n aria-live={\n triggerOn === \"click\" ? \"assertive\" : undefined\n }\n data-theme={theme}\n data-layout-density={density}\n className={clsx(\"jkl-tooltip-content\", className)}\n {...getFloatingProps({\n ...props,\n id: contentId,\n })}\n style={{ ...floatingStyles, ...animationStyles }}\n >\n {children}\n <FloatingArrow\n context={context}\n ref={arrowElement}\n width={24}\n height={12}\n fill=\"var(--background-color)\"\n />\n </span>\n </span>\n )}\n </FloatingPortal>\n );\n});\n"],"names":["getTranslation","side","value","TooltipContent","forwardRef","className","children","props","forwardedRef","triggerOn","arrowElement","getFloatingProps","placement","floatingStyles","refs","context","useTooltipContext","ref","useMergeRefs","setFloating","contentId","useId","prefersReducedMotion","useBrowserPreferences","isMounted","styles","animationStyles","useTransitionStyles","duration","open","close","initial","opacity","translate","density","theme","getThemeAndDensity","reference","current","FloatingPortal","jsx","setDescription","hidden","jsxs","clsx","id","style","FloatingArrow","width","height","fill"],"mappings":"ugBAcA,SAASA,EAAeC,EAAYC,EAAgB,GAChD,OAAQD,GACJ,IAAK,MASL,QACI,MAAO,KAAKC,MARhB,IAAK,OACD,MAAO,GAAGA,QACd,IAAK,SACM,MAAA,MAAMA,MACjB,IAAK,QACM,OAAIA,EAAJ,OAKnB,CAEa,MAAAC,EAAiBC,GAG5B,UAA0BC,UAAAA,EAAWC,SAAAA,KAAaC,GAASC,GACnD,MACFC,UAAAA,EACAC,aAAAA,EACAC,iBAAAA,EACAC,UAAAA,EACAC,eAAAA,EACAC,KAAAA,EACAC,QAAAA,GACAC,IACEC,EAAMC,EAAa,CAACV,EAAcM,EAAKK,cACvCC,EAAYC,EAAM,wBAChBC,qBAAAA,GAAyBC,KACzBC,UAAAA,EAAWC,OAAQC,GAAoBC,EAC3CZ,EACA,CACIa,SAAU,CACNC,KAAMP,EAAuB,EAAI,IACjCQ,MAAOR,EAAuB,EAAI,KAEtCS,QAAS,EAAG9B,KAAAA,MAAY,CACpB+B,QAAS,EACTC,UAAWjC,EAAeC,EAAM,KAEpC4B,KAAM,EAAG5B,KAAAA,MAAY,CACjB+B,QAAS,EACTC,UAAWjC,EAAeC,EAAM,KAEpC6B,MAAO,EAAG7B,KAAAA,MAAY,CAClB+B,QAAS,EACTC,UAAWjC,EAAeC,GAAQ,QAOtCiC,QAAAA,EAASC,MAAAA,GAAUC,EACvBtB,EAAKuB,UAAUC,SAGnB,SACKC,EAGI,CAAAjC,SAAA,CAAc,UAAdG,GACG+B,EAAC,OAAA,CACGvB,IAAKH,EAAK2B,eACVC,QAAM,EAGLpC,SAAAA,GAFI,GAAGc,aAKfI,GACGgB,EAAC,OAAK,CAAAnC,UAAU,MACZC,SAAAqC,EAAC,OAAA,CAEG1B,IAAAA,EACA,iBAAgBL,EAChB,YACkB,UAAdH,EAAwB,iBAAc,EAE1C,aAAY0B,EACZ,sBAAqBD,EACrB7B,UAAWuC,EAAK,sBAAuBvC,MACnCM,EAAiB,IACdJ,EACHsC,GAAIzB,IAER0B,MAAO,IAAKjC,KAAmBa,GAE9BpB,SAAA,CAAAA,EACDkC,EAACO,EAAA,CACGhC,QAAAA,EACAE,IAAKP,EACLsC,MAAO,GACPC,OAAQ,GACRC,KAAK,8BArBJ9B,IAFc,GAAGA,eA8B9C"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e}from"react/jsx-runtime";import{useMergeRefs as r}from"@floating-ui/react";import{c as t}from"../../../clsx-BeLtu-UY.js";import o,{forwardRef as
|
|
1
|
+
import{jsx as e}from"react/jsx-runtime";import{useMergeRefs as r}from"@floating-ui/react";import{c as t}from"../../../clsx-BeLtu-UY.js";import o,{forwardRef as l}from"react";import{useTooltipContext as n}from"./Tooltip.js";const s=l((function({children:l,className:s,...a},i){var p,c;const{isOpen:f,setOpen:u,getReferenceProps:m,refs:d,triggerOn:g}=n(),x=l.ref,j=r([x,d.setReference,i]),b=()=>{"click"===g&&u(!1)},v=[null==(p=d.reference.current)?void 0:p.textContent,null==(c=d.description.current)?void 0:c.textContent].map((e=>null==e?void 0:e.replaceAll(/[\ue003-\uf8aa]/g,""))).filter(Boolean).join(". ");return o.isValidElement(l)?o.cloneElement(l,m({ref:j,"aria-label":v,...l.props,...a,className:t(l.props.className,s),"data-tooltip-shown":f,style:{...l.props.style},tabIndex:"click"===g?0:void 0,onBlur:()=>{l.props.onBlur&&l.props.onBlur(),b()}})):e("button",{"data-tooltip-shown":f,...m({className:t(s,"jkl-tooltip-trigger"),type:"button",ref:j,onBlur:b,"aria-label":v,...a}),children:l})}));export{s as TooltipTrigger};
|
|
2
2
|
//# sourceMappingURL=TooltipTrigger.js.map
|