@postenbring/hedwig-react 0.0.74 → 0.0.75

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.
Files changed (69) hide show
  1. package/dist/_tsup-dts-rollup.d.mts +25 -8
  2. package/dist/_tsup-dts-rollup.d.ts +25 -8
  3. package/dist/accordion/index.mjs +5 -5
  4. package/dist/{chunk-QYSLVQ4F.mjs → chunk-4GSNPCNT.mjs} +2 -2
  5. package/dist/{chunk-G2SOAFGS.mjs → chunk-5YMUST7H.mjs} +2 -2
  6. package/dist/{chunk-CU56G5WS.mjs → chunk-CSAEHQ4R.mjs} +2 -2
  7. package/dist/{chunk-CSFSJGLY.mjs → chunk-E2AG5TUR.mjs} +2 -2
  8. package/dist/{chunk-ZL56N4UK.mjs → chunk-JXA3B33M.mjs} +34 -2
  9. package/dist/chunk-JXA3B33M.mjs.map +1 -0
  10. package/dist/{chunk-VM345XBI.mjs → chunk-MF2AREPQ.mjs} +2 -2
  11. package/dist/{chunk-2FXMUF6K.mjs → chunk-MKC7HZCM.mjs} +2 -2
  12. package/dist/{chunk-3KZOKDKP.mjs → chunk-PYR6QEIS.mjs} +17 -23
  13. package/dist/chunk-PYR6QEIS.mjs.map +1 -0
  14. package/dist/{chunk-BFNITN5E.mjs → chunk-S3BGPCLK.mjs} +2 -2
  15. package/dist/{chunk-B56JZJOS.mjs → chunk-SRLRTLHS.mjs} +2 -2
  16. package/dist/{chunk-HSIL53A5.mjs → chunk-UXJIK76H.mjs} +2 -2
  17. package/dist/{chunk-3FRCJ3RH.mjs → chunk-XYIY6FHW.mjs} +7 -7
  18. package/dist/footer/footer.mjs +4 -4
  19. package/dist/footer/index.mjs +5 -5
  20. package/dist/form/date-picker/date-picker.js.map +1 -1
  21. package/dist/form/date-picker/date-picker.mjs +2 -2
  22. package/dist/form/date-picker/index.js.map +1 -1
  23. package/dist/form/date-picker/index.mjs +2 -2
  24. package/dist/form/index.js.map +1 -1
  25. package/dist/form/index.mjs +2 -2
  26. package/dist/index-no-css.js +44 -20
  27. package/dist/index-no-css.js.map +1 -1
  28. package/dist/index-no-css.mjs +24 -24
  29. package/dist/index.js +44 -20
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +24 -24
  32. package/dist/modal/index.js.map +1 -1
  33. package/dist/modal/index.mjs +3 -3
  34. package/dist/modal/modal.js.map +1 -1
  35. package/dist/modal/modal.mjs +2 -2
  36. package/dist/navbar/index.js +40 -27
  37. package/dist/navbar/index.js.map +1 -1
  38. package/dist/navbar/index.mjs +3 -3
  39. package/dist/navbar/navbar-expandable-menu.js +40 -27
  40. package/dist/navbar/navbar-expandable-menu.js.map +1 -1
  41. package/dist/navbar/navbar-expandable-menu.mjs +2 -2
  42. package/dist/show-more/index.js.map +1 -1
  43. package/dist/show-more/index.mjs +2 -2
  44. package/dist/tabs/index.js.map +1 -1
  45. package/dist/tabs/index.mjs +3 -3
  46. package/dist/tabs/tabs-list.js.map +1 -1
  47. package/dist/tabs/tabs-list.mjs +2 -2
  48. package/dist/utilities/auto-animate-height.js.map +1 -1
  49. package/dist/utilities/auto-animate-height.mjs +2 -2
  50. package/dist/utilities/index.js.map +1 -1
  51. package/dist/utilities/index.mjs +2 -2
  52. package/dist/utils.d.mts +2 -0
  53. package/dist/utils.d.ts +2 -0
  54. package/dist/utils.js +34 -0
  55. package/dist/utils.js.map +1 -1
  56. package/dist/utils.mjs +5 -1
  57. package/package.json +2 -3
  58. package/dist/chunk-3KZOKDKP.mjs.map +0 -1
  59. package/dist/chunk-ZL56N4UK.mjs.map +0 -1
  60. /package/dist/{chunk-QYSLVQ4F.mjs.map → chunk-4GSNPCNT.mjs.map} +0 -0
  61. /package/dist/{chunk-G2SOAFGS.mjs.map → chunk-5YMUST7H.mjs.map} +0 -0
  62. /package/dist/{chunk-CU56G5WS.mjs.map → chunk-CSAEHQ4R.mjs.map} +0 -0
  63. /package/dist/{chunk-CSFSJGLY.mjs.map → chunk-E2AG5TUR.mjs.map} +0 -0
  64. /package/dist/{chunk-VM345XBI.mjs.map → chunk-MF2AREPQ.mjs.map} +0 -0
  65. /package/dist/{chunk-2FXMUF6K.mjs.map → chunk-MKC7HZCM.mjs.map} +0 -0
  66. /package/dist/{chunk-BFNITN5E.mjs.map → chunk-S3BGPCLK.mjs.map} +0 -0
  67. /package/dist/{chunk-B56JZJOS.mjs.map → chunk-SRLRTLHS.mjs.map} +0 -0
  68. /package/dist/{chunk-HSIL53A5.mjs.map → chunk-UXJIK76H.mjs.map} +0 -0
  69. /package/dist/{chunk-3FRCJ3RH.mjs.map → chunk-XYIY6FHW.mjs.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/navbar/navbar-expandable-menu.tsx","../../src/utils.ts","../../src/navbar/icons.tsx"],"sourcesContent":["import React, { createContext, useContext, forwardRef, useState, useRef, useEffect } from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport type { ClassValue } from \"@postenbring/hedwig-css/typed-classname/index.mjs\";\nimport { clsx } from \"@postenbring/hedwig-css/typed-classname\";\nimport FocusTrap from \"focus-trap-react\";\nimport { useHydrated, type OverridableComponent } from \"../utils\";\nimport { CloseIcon, MenuIcon } from \"./icons\";\n\nconst expandableMenuContext = createContext([\n false as boolean,\n () => {\n // Empty\n },\n] as const);\nexport const useNavbarExpendableMenuContext = () => useContext(expandableMenuContext);\n\n/**\n * Root\n */\nexport interface NavbarExpandableMenuProps {\n children: React.ReactNode;\n}\nexport function NavbarExpandableMenu({ children }: NavbarExpandableMenuProps) {\n const [open, setOpen] = useState(false);\n const isClientSide = useHydrated();\n const toggleOpen = () => {\n const nextOpenState = !open;\n setOpen(nextOpenState);\n if (nextOpenState) {\n window.scrollTo(0, 0);\n document.body.classList.add(clsx(\"hds-navbar-scroll-lock\"));\n } else {\n document.body.classList.remove(clsx(\"hds-navbar-scroll-lock\"));\n }\n };\n return (\n <expandableMenuContext.Provider value={[open, toggleOpen]}>\n {open && isClientSide ? (\n <FocusTrap\n containerElements={[\n document.getElementsByClassName(clsx(\"hds-navbar\"))[0] as HTMLElement,\n ]}\n />\n ) : null}\n {children}\n </expandableMenuContext.Provider>\n );\n}\nNavbarExpandableMenu.displayName = \"NavbarExpandableMenu\";\n\ninterface ButtonInterface {\n className?: ClassValue;\n open?: boolean;\n innerRef?: React.RefObject<HTMLButtonElement>;\n ref?: React.ForwardedRef<HTMLButtonElement>;\n text: React.ReactNode;\n title?: string;\n toggleOpen?: () => void;\n width?: number;\n}\n\nfunction RenderButton({\n className,\n innerRef,\n open = false,\n ref,\n text,\n title,\n toggleOpen,\n width,\n ...rest\n}: ButtonInterface) {\n const icon = open ? <CloseIcon /> : <MenuIcon />;\n const style = width ? { width } : {};\n return (\n <button\n className={clsx(\"hds-navbar__button\", className)}\n onClick={toggleOpen}\n ref={ref ?? innerRef}\n style={style}\n title={title}\n type=\"button\"\n {...rest}\n >\n <span className={clsx(\"hds-navbar__button-responsive-text\")}>{text}</span> {icon}\n </button>\n );\n}\n\n/**\n * Trigger\n *\n * ## TODO\n * - [x] Hide text when on mobile\n * - [X] Open / Close icon\n * - [X] Make button have consistant width\n */\n\nexport interface NavbarExpandableMenuTriggerProps\n extends Omit<React.HTMLAttributes<HTMLButtonElement>, \"children\"> {\n whenClosedText: React.ReactNode;\n whenClosedHelperTitle?: string;\n\n whenOpenText: React.ReactNode;\n whenOpenHelperTitle?: string;\n}\nexport const NavbarExpandableMenuTrigger = forwardRef<\n HTMLButtonElement,\n NavbarExpandableMenuTriggerProps\n>(\n (\n {\n whenClosedText,\n whenClosedHelperTitle,\n\n whenOpenText,\n whenOpenHelperTitle,\n\n className,\n ...rest\n },\n ref,\n ) => {\n const [open, toggleOpen] = useNavbarExpendableMenuContext();\n const [width, setWidth] = useState(0);\n const measureButtonRef = useRef<HTMLButtonElement>(null);\n\n const text: React.ReactNode = open ? whenOpenText : whenClosedText;\n const title = open ? whenOpenHelperTitle : whenClosedHelperTitle;\n\n /**\n *\n * @param element - Button to measure\n * @param callback - report the width back\n */\n const measureButton = (element: React.ReactNode, callback: (width: number) => void) => {\n // Create an empty div to render the Button in\n const container = document.createElement(\"div\");\n container.style.cssText = \"display: inline-block; position: absolute; visibility: hidden\";\n\n // Attach the empty div inside the navigation section\n const c = document.getElementsByClassName(\"hds-navbar__navigation\")[0];\n c.appendChild(container);\n\n // Render the Button here\n const root = createRoot(container as HTMLElement);\n root.render(element);\n\n /**\n * Get the offsetWidth now that it is rendered\n * Also clean up after us\n */\n const getWidth = () => {\n callback(measureButtonRef.current?.offsetWidth ?? 0);\n root.unmount();\n c.removeChild(container);\n };\n // This is instead of the callback that used to be on ReactDOM.render()\n setTimeout(getWidth, 0);\n };\n\n useEffect(() => {\n measureButton(\n <RenderButton\n className={(className ? className : \"\") as ClassValue}\n innerRef={measureButtonRef}\n text={whenClosedText}\n title={title}\n {...rest}\n />,\n (closedWidth: number) => {\n measureButton(\n <RenderButton\n className={(className ? className : \"\") as ClassValue}\n innerRef={measureButtonRef}\n open\n text={whenOpenText}\n title={title}\n {...rest}\n />,\n (openWidth: number) => {\n setWidth(Math.max(openWidth, closedWidth));\n },\n );\n },\n );\n }, [className, rest, title, whenClosedText, whenOpenText]);\n\n return (\n <RenderButton\n className={(className ? className : \"\") as ClassValue}\n open={open}\n ref={ref}\n text={text as string}\n title={title}\n toggleOpen={toggleOpen}\n width={width}\n {...rest}\n />\n );\n },\n);\nNavbarExpandableMenuTrigger.displayName = \"Navbar.ExpandableMenu.Trigger\";\n\n/**\n * Content\n */\nexport interface NavbarExpandableMenuContentProps {\n children: React.ReactNode;\n className?: string;\n}\nexport const NavbarExpandableMenuContent: OverridableComponent<\n NavbarExpandableMenuContentProps,\n HTMLDivElement\n> = forwardRef(({ as: Component = \"section\", children, className, ...rest }, ref) => {\n const [open] = useNavbarExpendableMenuContext();\n return (\n <Component\n {...rest}\n className={clsx(\"hds-navbar__expandable-menu-content\", className as undefined)}\n data-state={open ? \"open\" : \"closed\"}\n inert={open ? undefined : \"true\"}\n ref={ref}\n >\n <div className={clsx(\"hds-navbar__expandable-menu-content-inner\")}>{children}</div>\n </Component>\n );\n});\nNavbarExpandableMenuContent.displayName = \"Navbar.ExpandableMenu.Content\";\n","import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n","function CloseIcon() {\n return (\n <svg aria-hidden viewBox=\"0 0 384 512\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M345 137c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-119 119L73 103c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l119 119L39 375c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l119-119L311 409c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-119-119L345 137z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n\nfunction MenuIcon() {\n return (\n <svg role=\"img\" viewBox=\"0 0 448 512\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M0 88C0 74.7 10.7 64 24 64H424c13.3 0 24 10.7 24 24s-10.7 24-24 24H24C10.7 112 0 101.3 0 88zM0 248c0-13.3 10.7-24 24-24H424c13.3 0 24 10.7 24 24s-10.7 24-24 24H24c-13.3 0-24-10.7-24-24zM448 408c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24s10.7-24 24-24H424c13.3 0 24 10.7 24 24z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n\nexport { CloseIcon, MenuIcon };\n"],"mappings":"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","names":["import_react","import_jsx_runtime","FocusTrap","_a","_b"]}
1
+ {"version":3,"sources":["../../src/navbar/navbar-expandable-menu.tsx","../../src/utils.ts","../../src/navbar/icons.tsx"],"sourcesContent":["import React, { createContext, useContext, forwardRef, useState, useRef, useEffect } from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport type { ClassValue } from \"@postenbring/hedwig-css/typed-classname/index.mjs\";\nimport { clsx } from \"@postenbring/hedwig-css/typed-classname\";\nimport { focusTrap, type OverridableComponent } from \"../utils\";\nimport { CloseIcon, MenuIcon } from \"./icons\";\n\nconst expandableMenuContext = createContext([\n false as boolean,\n () => {\n // Empty\n },\n] as const);\nexport const useNavbarExpendableMenuContext = () => useContext(expandableMenuContext);\n\nexport interface NavbarExpandableMenuProps {\n children: React.ReactNode;\n}\n\n/**\n * Expandable Menu Provider\n * Handles scroll and focus locking,\n * as well as scrolling the user to the top of the page.\n *\n * If we want a sticky header in the future the scrolling should be configurable\n */\nexport function NavbarExpandableMenu({ children }: NavbarExpandableMenuProps) {\n const [open, setOpen] = useState(false);\n function toggleOpen() {\n setOpen((prev) => !prev);\n }\n\n useEffect(() => {\n if (open) {\n window.scrollTo(0, 0);\n document.body.classList.add(clsx(\"hds-navbar-scroll-lock\"));\n const releaseFocusTrap = focusTrap(\n document.getElementsByClassName(clsx(\"hds-navbar\"))[0] as HTMLElement,\n );\n\n return () => {\n document.body.classList.remove(clsx(\"hds-navbar-scroll-lock\"));\n releaseFocusTrap();\n };\n }\n }, [open]);\n\n return (\n <expandableMenuContext.Provider value={[open, toggleOpen]}>\n {children}\n </expandableMenuContext.Provider>\n );\n}\nNavbarExpandableMenu.displayName = \"NavbarExpandableMenu\";\n\ninterface ButtonInterface {\n className?: ClassValue;\n open?: boolean;\n innerRef?: React.RefObject<HTMLButtonElement>;\n ref?: React.ForwardedRef<HTMLButtonElement>;\n text: React.ReactNode;\n title?: string;\n toggleOpen?: () => void;\n width?: number;\n}\n\nfunction RenderButton({\n className,\n innerRef,\n open = false,\n ref,\n text,\n title,\n toggleOpen,\n width,\n ...rest\n}: ButtonInterface) {\n const icon = open ? <CloseIcon /> : <MenuIcon />;\n const style = width ? { width } : {};\n return (\n <button\n className={clsx(\"hds-navbar__button\", className)}\n onClick={toggleOpen}\n ref={ref ?? innerRef}\n style={style}\n title={title}\n type=\"button\"\n {...rest}\n >\n <span className={clsx(\"hds-navbar__button-responsive-text\")}>{text}</span> {icon}\n </button>\n );\n}\n\n/**\n * Trigger\n */\nexport interface NavbarExpandableMenuTriggerProps\n extends Omit<React.HTMLAttributes<HTMLButtonElement>, \"children\"> {\n whenClosedText: React.ReactNode;\n whenClosedHelperTitle?: string;\n\n whenOpenText: React.ReactNode;\n whenOpenHelperTitle?: string;\n}\nexport const NavbarExpandableMenuTrigger = forwardRef<\n HTMLButtonElement,\n NavbarExpandableMenuTriggerProps\n>(\n (\n {\n whenClosedText,\n whenClosedHelperTitle,\n\n whenOpenText,\n whenOpenHelperTitle,\n\n className,\n ...rest\n },\n ref,\n ) => {\n const [open, toggleOpen] = useNavbarExpendableMenuContext();\n const [width, setWidth] = useState(0);\n const measureButtonRef = useRef<HTMLButtonElement>(null);\n\n const text: React.ReactNode = open ? whenOpenText : whenClosedText;\n const title = open ? whenOpenHelperTitle : whenClosedHelperTitle;\n\n /**\n *\n * @param element - Button to measure\n * @param callback - report the width back\n */\n const measureButton = (element: React.ReactNode, callback: (width: number) => void) => {\n // Create an empty div to render the Button in\n const container = document.createElement(\"div\");\n container.style.cssText = \"display: inline-block; position: absolute; visibility: hidden\";\n\n // Attach the empty div inside the navigation section\n const c = document.getElementsByClassName(\"hds-navbar__navigation\")[0];\n c.appendChild(container);\n\n // Render the Button here\n const root = createRoot(container as HTMLElement);\n root.render(element);\n\n /**\n * Get the offsetWidth now that it is rendered\n * Also clean up after us\n */\n const getWidth = () => {\n callback(measureButtonRef.current?.offsetWidth ?? 0);\n root.unmount();\n c.removeChild(container);\n };\n // This is instead of the callback that used to be on ReactDOM.render()\n setTimeout(getWidth, 0);\n };\n\n useEffect(() => {\n measureButton(\n <RenderButton\n className={(className ? className : \"\") as ClassValue}\n innerRef={measureButtonRef}\n text={whenClosedText}\n title={title}\n {...rest}\n />,\n (closedWidth: number) => {\n measureButton(\n <RenderButton\n className={(className ? className : \"\") as ClassValue}\n innerRef={measureButtonRef}\n open\n text={whenOpenText}\n title={title}\n {...rest}\n />,\n (openWidth: number) => {\n setWidth(Math.max(openWidth, closedWidth));\n },\n );\n },\n );\n }, [className, rest, title, whenClosedText, whenOpenText]);\n\n return (\n <RenderButton\n className={(className ? className : \"\") as ClassValue}\n open={open}\n ref={ref}\n text={text as string}\n title={title}\n toggleOpen={toggleOpen}\n width={width}\n {...rest}\n />\n );\n },\n);\nNavbarExpandableMenuTrigger.displayName = \"Navbar.ExpandableMenu.Trigger\";\n\n/**\n * Content\n */\nexport interface NavbarExpandableMenuContentProps {\n children: React.ReactNode;\n className?: string;\n}\nexport const NavbarExpandableMenuContent: OverridableComponent<\n NavbarExpandableMenuContentProps,\n HTMLDivElement\n> = forwardRef(({ as: Component = \"section\", children, className, ...rest }, ref) => {\n const [open] = useNavbarExpendableMenuContext();\n return (\n <Component\n {...rest}\n className={clsx(\"hds-navbar__expandable-menu-content\", className as undefined)}\n data-state={open ? \"open\" : \"closed\"}\n inert={open ? undefined : \"true\"}\n ref={ref}\n >\n <div className={clsx(\"hds-navbar__expandable-menu-content-inner\")}>{children}</div>\n </Component>\n );\n});\nNavbarExpandableMenuContent.displayName = \"Navbar.ExpandableMenu.Content\";\n","import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n\n/**\n * Trap focus inside an element using the `inert` attribute.\n *\n * Adds `inert` to all siblings of the given element, and all their ancestors up to the body.\n * Returns a cleanup function which removes the `inert` property from the elements, effectively giving focus back to rest of the document.\n *\n * NOTE: Does not support portals, i.e. elements outside the DOM hierarchy of the given element.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert\n * @see https://web.dev/articles/inert\n */\nexport function focusTrap(element: HTMLElement) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- NOP on focus trapping the body element\n if (element === document.body) return () => {};\n\n let inertElements: HTMLElement[] = [];\n for (let el: HTMLElement | null = element; el; el = el.parentElement) {\n if (el === document.body) break;\n\n for (const sibling of el.parentElement?.children ?? []) {\n if (sibling === el) continue;\n if (!(sibling instanceof HTMLElement)) continue;\n if (sibling.hasAttribute(\"inert\")) continue;\n\n sibling.setAttribute(\"inert\", \"true\");\n inertElements.push(sibling);\n }\n }\n\n return () => {\n releaseFocusTrap(inertElements);\n inertElements = [];\n };\n}\n\n/**\n * Unset the `inert` attribute on all elements given\n */\nexport function releaseFocusTrap(inertElements: Iterable<HTMLElement>) {\n for (const el of inertElements) {\n el.removeAttribute(\"inert\");\n }\n}\n","function CloseIcon() {\n return (\n <svg aria-hidden viewBox=\"0 0 384 512\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M345 137c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-119 119L73 103c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l119 119L39 375c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l119-119L311 409c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-119-119L345 137z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n\nfunction MenuIcon() {\n return (\n <svg role=\"img\" viewBox=\"0 0 448 512\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M0 88C0 74.7 10.7 64 24 64H424c13.3 0 24 10.7 24 24s-10.7 24-24 24H24C10.7 112 0 101.3 0 88zM0 248c0-13.3 10.7-24 24-24H424c13.3 0 24 10.7 24 24s-10.7 24-24 24H24c-13.3 0-24-10.7-24-24zM448 408c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24s10.7-24 24-24H424c13.3 0 24 10.7 24 24z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n\nexport { CloseIcon, MenuIcon };\n"],"mappings":"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","names":["import_react","import_jsx_runtime","releaseFocusTrap","_a","_b"]}
@@ -3,9 +3,9 @@ import {
3
3
  NavbarExpandableMenuContent,
4
4
  NavbarExpandableMenuTrigger,
5
5
  useNavbarExpendableMenuContext
6
- } from "../chunk-3KZOKDKP.mjs";
6
+ } from "../chunk-PYR6QEIS.mjs";
7
7
  import "../chunk-MGUYIOP2.mjs";
8
- import "../chunk-ZL56N4UK.mjs";
8
+ import "../chunk-JXA3B33M.mjs";
9
9
  import "../chunk-R4SQKVDQ.mjs";
10
10
  export {
11
11
  NavbarExpandableMenu,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/show-more/index.ts","../../src/utilities/auto-animate-height.tsx","../../src/utils.ts","../../src/show-more/show-more.tsx"],"sourcesContent":["export { AutoAnimateHeight } from \"../utilities/auto-animate-height\";\nexport type * from \"../utilities/auto-animate-height\";\n\nexport { ShowMoreButton } from \"./show-more\";\nexport type * from \"./show-more\";\n","import { cloneElement, forwardRef, useEffect, useRef, useState } from \"react\";\nimport { useMergeRefs, type OverridableComponent } from \"../utils\";\n\nexport interface AutoAnimateHeightProps {\n /**\n * Time of the animation, using the hedwig animation tokens\n * quick: 0.1s\n * normal: 0.3s\n * slow: 0.7s\n *\n * default is \"quick\"\n */\n animationDuration?: \"quick\" | \"normal\" | \"slow\";\n\n /**\n * Callback fired when animiation transition ends\n * Use this to do effects after resizing is done, e.g. scrolling to the element\n * using `element.scrollIntoView()`\n */\n onTransitionEnd?: () => void;\n\n /**\n * Which hedwig easing function to use, default is \"normal\"\n */\n animationEasing?: \"in\" | \"out\" | \"normal\";\n children: React.ReactNode;\n style?: React.CSSProperties;\n}\n\n/**\n * Helper component to animate the height of the children when they change\n * It's done by rendering two versions of the passed children,\n * one hidden to measure the height and one visible to only changes after the height is measured.\n *\n * **IMPORTANT** Do not pass any components with effects (like data fetching), as they will trigger twice.\n */\nexport const AutoAnimateHeight: OverridableComponent<AutoAnimateHeightProps, HTMLDivElement> =\n forwardRef(\n (\n {\n as: Component = \"div\",\n children,\n style,\n animationDuration = \"quick\",\n animationEasing = \"normal\",\n onTransitionEnd,\n ...rest\n },\n ref,\n ) => {\n const rootRef = useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs([rootRef, ref]);\n const measurementRef = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<{ height: number; shouldAnimate: boolean } | undefined>(\n undefined,\n );\n const [clonedChildren, setClonedChildren] = useState<React.ReactNode>(() =>\n cloneElement(<>{children}</>, {}),\n );\n\n useEffect(() => {\n if (!rootRef.current) return;\n if (!measurementRef.current) return;\n if (document.body.scrollHeight === 0) return;\n const currentMeasurement = measurementRef.current;\n const { height: newHeight } = currentMeasurement.getBoundingClientRect();\n\n // Listen for resize events on the measurement element\n // Keep the children in sync with the height\n // But don't animate it.\n let previouslyObservedHeight = newHeight;\n const resizeObserver = new ResizeObserver(() => {\n const { height: resizedHeight } = currentMeasurement.getBoundingClientRect();\n if (resizedHeight === previouslyObservedHeight) return;\n previouslyObservedHeight = resizedHeight;\n setHeight({ height: resizedHeight, shouldAnimate: false });\n });\n resizeObserver.observe(currentMeasurement); // This is cleaned up down below in the return functions\n\n // Set the new height when children changes\n setHeight({ height: newHeight, shouldAnimate: true });\n\n // Update children\n const nextClonedChildren = cloneElement(<>{children}</>, {});\n\n // When increasing in height update immediately so the new content is shown during the animation\n if (newHeight >= (height?.height ?? 0)) {\n setClonedChildren(nextClonedChildren);\n return () => {\n resizeObserver.disconnect();\n };\n }\n\n // When decreasing in height, wait until the animation is done so that we don't get a sudden flash of empty content\n const currentRoot = rootRef.current;\n function onTransitionEndHandler(e: TransitionEvent) {\n if (e.propertyName !== \"height\") return;\n setClonedChildren(nextClonedChildren);\n }\n currentRoot.addEventListener(\"transitionend\", onTransitionEndHandler);\n return () => {\n resizeObserver.disconnect();\n currentRoot.removeEventListener(\"transitionend\", onTransitionEndHandler);\n };\n\n // eslint-disable-next-line react-hooks/exhaustive-deps -- I know better\n }, [children]);\n\n return (\n <Component\n ref={mergedRef}\n onTransitionEnd={onTransitionEnd}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n height: height?.height ?? measurementRef.current?.getBoundingClientRect().height,\n transitionProperty: height?.shouldAnimate ? \"height\" : \"none\",\n transitionDuration: `var(--hds-micro-animation-duration-${animationDuration})`,\n transitionTimingFunction: `var(--hds-micro-animation-easing-${animationEasing})`,\n willChange: \"height\",\n ...style,\n }}\n {...rest}\n >\n <div\n aria-hidden\n ref={measurementRef}\n style={{\n position: \"absolute\",\n visibility: \"hidden\",\n }}\n >\n {children}\n </div>\n {clonedChildren}\n </Component>\n );\n },\n );\nAutoAnimateHeight.displayName = \"AutoAnimateHeight\";\n","import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n","import { clsx } from \"@postenbring/hedwig-css/typed-classname\";\nimport { forwardRef } from \"react\";\n\ntype Variant =\n | {\n variant?: \"show-more\";\n expanded?: never;\n }\n | {\n variant: \"show-more-show-less\";\n expanded: boolean;\n };\n\nexport type ShowMoreProps = React.HTMLAttributes<HTMLButtonElement> & {\n text: React.ReactNode;\n} & Variant;\n\n/**\n * Simple button for triggering more content.\n *\n * You have to add the logic for what happens when the button is clicked yourself.\n *\n * **Example**\n *\n * ```tsx\n * function Content() {\n * const [items, fetchMoreItems, moreItemsAvailable] = useYourData();\n * function onShowMoreItems() {\n * fetchMoreItems();\n * }\n * return (\n * <>\n * <ul>\n * {items.map((item) => (\n * <li key={item.id}>{item.text}</li>\n * ))}\n * </ul>\n * {moreItemsAvailable ?\n * <ShowMoreButton className=\"mt-8\" onClick={onShowMoreItems} lang=\"en\" /> :\n * null\n * }\n * </>\n * )\n * }\n * ```\n */\nexport const ShowMoreButton = forwardRef<HTMLButtonElement, ShowMoreProps>(\n ({ text, variant, expanded, className, ...rest }, ref) => {\n return (\n <button\n ref={ref}\n className={clsx(\n \"hds-show-more\",\n variant === \"show-more-show-less\" && \"hds-show-more--show-less\",\n className as undefined,\n )}\n data-state={expanded ? \"expanded\" : undefined}\n type=\"button\"\n {...rest}\n >\n {text}\n <span className={clsx(\"hds-show-more__icon\")} />\n </button>\n );\n },\n);\nShowMoreButton.displayName = \"ShowMoreButton\";\n"],"mappings":"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","names":["import_react","_a","_b","import_react","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../../src/show-more/index.ts","../../src/utilities/auto-animate-height.tsx","../../src/utils.ts","../../src/show-more/show-more.tsx"],"sourcesContent":["export { AutoAnimateHeight } from \"../utilities/auto-animate-height\";\nexport type * from \"../utilities/auto-animate-height\";\n\nexport { ShowMoreButton } from \"./show-more\";\nexport type * from \"./show-more\";\n","import { cloneElement, forwardRef, useEffect, useRef, useState } from \"react\";\nimport { useMergeRefs, type OverridableComponent } from \"../utils\";\n\nexport interface AutoAnimateHeightProps {\n /**\n * Time of the animation, using the hedwig animation tokens\n * quick: 0.1s\n * normal: 0.3s\n * slow: 0.7s\n *\n * default is \"quick\"\n */\n animationDuration?: \"quick\" | \"normal\" | \"slow\";\n\n /**\n * Callback fired when animiation transition ends\n * Use this to do effects after resizing is done, e.g. scrolling to the element\n * using `element.scrollIntoView()`\n */\n onTransitionEnd?: () => void;\n\n /**\n * Which hedwig easing function to use, default is \"normal\"\n */\n animationEasing?: \"in\" | \"out\" | \"normal\";\n children: React.ReactNode;\n style?: React.CSSProperties;\n}\n\n/**\n * Helper component to animate the height of the children when they change\n * It's done by rendering two versions of the passed children,\n * one hidden to measure the height and one visible to only changes after the height is measured.\n *\n * **IMPORTANT** Do not pass any components with effects (like data fetching), as they will trigger twice.\n */\nexport const AutoAnimateHeight: OverridableComponent<AutoAnimateHeightProps, HTMLDivElement> =\n forwardRef(\n (\n {\n as: Component = \"div\",\n children,\n style,\n animationDuration = \"quick\",\n animationEasing = \"normal\",\n onTransitionEnd,\n ...rest\n },\n ref,\n ) => {\n const rootRef = useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs([rootRef, ref]);\n const measurementRef = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<{ height: number; shouldAnimate: boolean } | undefined>(\n undefined,\n );\n const [clonedChildren, setClonedChildren] = useState<React.ReactNode>(() =>\n cloneElement(<>{children}</>, {}),\n );\n\n useEffect(() => {\n if (!rootRef.current) return;\n if (!measurementRef.current) return;\n if (document.body.scrollHeight === 0) return;\n const currentMeasurement = measurementRef.current;\n const { height: newHeight } = currentMeasurement.getBoundingClientRect();\n\n // Listen for resize events on the measurement element\n // Keep the children in sync with the height\n // But don't animate it.\n let previouslyObservedHeight = newHeight;\n const resizeObserver = new ResizeObserver(() => {\n const { height: resizedHeight } = currentMeasurement.getBoundingClientRect();\n if (resizedHeight === previouslyObservedHeight) return;\n previouslyObservedHeight = resizedHeight;\n setHeight({ height: resizedHeight, shouldAnimate: false });\n });\n resizeObserver.observe(currentMeasurement); // This is cleaned up down below in the return functions\n\n // Set the new height when children changes\n setHeight({ height: newHeight, shouldAnimate: true });\n\n // Update children\n const nextClonedChildren = cloneElement(<>{children}</>, {});\n\n // When increasing in height update immediately so the new content is shown during the animation\n if (newHeight >= (height?.height ?? 0)) {\n setClonedChildren(nextClonedChildren);\n return () => {\n resizeObserver.disconnect();\n };\n }\n\n // When decreasing in height, wait until the animation is done so that we don't get a sudden flash of empty content\n const currentRoot = rootRef.current;\n function onTransitionEndHandler(e: TransitionEvent) {\n if (e.propertyName !== \"height\") return;\n setClonedChildren(nextClonedChildren);\n }\n currentRoot.addEventListener(\"transitionend\", onTransitionEndHandler);\n return () => {\n resizeObserver.disconnect();\n currentRoot.removeEventListener(\"transitionend\", onTransitionEndHandler);\n };\n\n // eslint-disable-next-line react-hooks/exhaustive-deps -- I know better\n }, [children]);\n\n return (\n <Component\n ref={mergedRef}\n onTransitionEnd={onTransitionEnd}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n height: height?.height ?? measurementRef.current?.getBoundingClientRect().height,\n transitionProperty: height?.shouldAnimate ? \"height\" : \"none\",\n transitionDuration: `var(--hds-micro-animation-duration-${animationDuration})`,\n transitionTimingFunction: `var(--hds-micro-animation-easing-${animationEasing})`,\n willChange: \"height\",\n ...style,\n }}\n {...rest}\n >\n <div\n aria-hidden\n ref={measurementRef}\n style={{\n position: \"absolute\",\n visibility: \"hidden\",\n }}\n >\n {children}\n </div>\n {clonedChildren}\n </Component>\n );\n },\n );\nAutoAnimateHeight.displayName = \"AutoAnimateHeight\";\n","import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n\n/**\n * Trap focus inside an element using the `inert` attribute.\n *\n * Adds `inert` to all siblings of the given element, and all their ancestors up to the body.\n * Returns a cleanup function which removes the `inert` property from the elements, effectively giving focus back to rest of the document.\n *\n * NOTE: Does not support portals, i.e. elements outside the DOM hierarchy of the given element.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert\n * @see https://web.dev/articles/inert\n */\nexport function focusTrap(element: HTMLElement) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- NOP on focus trapping the body element\n if (element === document.body) return () => {};\n\n let inertElements: HTMLElement[] = [];\n for (let el: HTMLElement | null = element; el; el = el.parentElement) {\n if (el === document.body) break;\n\n for (const sibling of el.parentElement?.children ?? []) {\n if (sibling === el) continue;\n if (!(sibling instanceof HTMLElement)) continue;\n if (sibling.hasAttribute(\"inert\")) continue;\n\n sibling.setAttribute(\"inert\", \"true\");\n inertElements.push(sibling);\n }\n }\n\n return () => {\n releaseFocusTrap(inertElements);\n inertElements = [];\n };\n}\n\n/**\n * Unset the `inert` attribute on all elements given\n */\nexport function releaseFocusTrap(inertElements: Iterable<HTMLElement>) {\n for (const el of inertElements) {\n el.removeAttribute(\"inert\");\n }\n}\n","import { clsx } from \"@postenbring/hedwig-css/typed-classname\";\nimport { forwardRef } from \"react\";\n\ntype Variant =\n | {\n variant?: \"show-more\";\n expanded?: never;\n }\n | {\n variant: \"show-more-show-less\";\n expanded: boolean;\n };\n\nexport type ShowMoreProps = React.HTMLAttributes<HTMLButtonElement> & {\n text: React.ReactNode;\n} & Variant;\n\n/**\n * Simple button for triggering more content.\n *\n * You have to add the logic for what happens when the button is clicked yourself.\n *\n * **Example**\n *\n * ```tsx\n * function Content() {\n * const [items, fetchMoreItems, moreItemsAvailable] = useYourData();\n * function onShowMoreItems() {\n * fetchMoreItems();\n * }\n * return (\n * <>\n * <ul>\n * {items.map((item) => (\n * <li key={item.id}>{item.text}</li>\n * ))}\n * </ul>\n * {moreItemsAvailable ?\n * <ShowMoreButton className=\"mt-8\" onClick={onShowMoreItems} lang=\"en\" /> :\n * null\n * }\n * </>\n * )\n * }\n * ```\n */\nexport const ShowMoreButton = forwardRef<HTMLButtonElement, ShowMoreProps>(\n ({ text, variant, expanded, className, ...rest }, ref) => {\n return (\n <button\n ref={ref}\n className={clsx(\n \"hds-show-more\",\n variant === \"show-more-show-less\" && \"hds-show-more--show-less\",\n className as undefined,\n )}\n data-state={expanded ? \"expanded\" : undefined}\n type=\"button\"\n {...rest}\n >\n {text}\n <span className={clsx(\"hds-show-more__icon\")} />\n </button>\n );\n },\n);\nShowMoreButton.displayName = \"ShowMoreButton\";\n"],"mappings":"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","names":["import_react","_a","_b","import_react","import_jsx_runtime"]}
@@ -4,8 +4,8 @@ import {
4
4
  } from "../chunk-ZDPU3N54.mjs";
5
5
  import {
6
6
  AutoAnimateHeight
7
- } from "../chunk-HSIL53A5.mjs";
8
- import "../chunk-ZL56N4UK.mjs";
7
+ } from "../chunk-UXJIK76H.mjs";
8
+ import "../chunk-JXA3B33M.mjs";
9
9
  import "../chunk-R4SQKVDQ.mjs";
10
10
  export {
11
11
  AutoAnimateHeight,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tabs/index.tsx","../../src/tabs/tabs.tsx","../../src/tabs/context.ts","../../src/tabs/tabs-list.tsx","../../src/utils.ts","../../src/tabs/tabs-content.tsx"],"sourcesContent":["import { Tabs } from \"./tabs\";\nimport { TabsList, TabsTab } from \"./tabs-list\";\nimport { TabsContents, TabsContent } from \"./tabs-content\";\n\nconst TabsComponent = Tabs as typeof Tabs & {\n List: typeof TabsList;\n Tab: typeof TabsTab;\n Contents: typeof TabsContents;\n Content: typeof TabsContent;\n};\nTabsComponent.List = TabsList;\nTabsComponent.Tab = TabsTab;\nTabsComponent.Contents = TabsContents;\nTabsComponent.Content = TabsContent;\n\nexport { TabsComponent as Tabs, TabsList, TabsTab, TabsContents, TabsContent };\n\nexport type * from \"./tabs\";\nexport type * from \"./tabs-list\";\nexport type * from \"./tabs-content\";\n","import type { HTMLAttributes, ReactElement } from \"react\";\nimport { forwardRef, useState } from \"react\";\nimport { clsx } from \"@postenbring/hedwig-css/typed-classname\";\nimport type { OverridableComponent } from \"../utils\";\nimport { TabsContext } from \"./context\";\nimport type { TabContentsProps } from \"./tabs-content\";\nimport type { TabListProps } from \"./tabs-list\";\n\nexport interface TabsProps extends HTMLAttributes<HTMLElement> {\n children: ReactElement<TabListProps | TabContentsProps>[] | ReactElement;\n\n /**\n * Define which tab to use as default. Must be one of the <Tab/>s identifier.\n */\n defaultTab: string;\n}\n\nexport const Tabs: OverridableComponent<TabsProps, HTMLDivElement> = forwardRef(\n ({ as: Component = \"div\", defaultTab, children, ...rest }, ref) => {\n const [activeTabId, setActiveTabId] = useState<string>(defaultTab);\n return (\n <Component className={clsx(\"hds-tabs\")} ref={ref} {...rest}>\n <TabsContext.Provider value={{ activeTabId, toggleActiveTabId: setActiveTabId }}>\n {children}\n </TabsContext.Provider>\n </Component>\n );\n },\n);\n\nTabs.displayName = \"Tabs\";\n","import { createContext, useContext } from \"react\";\n\nexport interface TabsContextProps {\n activeTabId: string;\n toggleActiveTabId: (tabId: string) => void;\n}\n\nexport const TabsContext = createContext<TabsContextProps | null>(null);\n\nexport function useTabsContext() {\n const context = useContext(TabsContext);\n if (!context) {\n throw new Error(\n \"Tabs context required. Did you use `<Tabs.List />`, `<Tabs.Tab />`, or `<Tabs.Content />` outside of <Tabs/>?\",\n );\n }\n return context;\n}\n","import type { HTMLAttributes, ReactElement, MouseEvent } from \"react\";\nimport { forwardRef, useEffect, useRef } from \"react\";\nimport { clsx } from \"@postenbring/hedwig-css/typed-classname\";\nimport { type OverridableComponent, useResize, useHydrated } from \"../utils\";\nimport { useTabsContext } from \"./context\";\n\nexport interface TabListProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactElement<TabsTabProps> | ReactElement<TabsTabProps>[];\n\n /**\n * Direction of the tabs. Can either be vertical or horizontal.\n * Horizontal breaks on window width with fallback back to vertical\n */\n direction?: \"vertical\" | \"horizontal\";\n}\n\nexport function TabsList({ children, direction = \"horizontal\", className, ...rest }: TabListProps) {\n const { activeTabId } = useTabsContext();\n const tabsListRef = useRef<HTMLDivElement>(null);\n const { width: tabsWidth } = useResize(tabsListRef);\n\n const isClientSide = useHydrated();\n const { innerWidth } = isClientSide ? window : { innerWidth: 1000 };\n const wideEnough = innerWidth >= tabsWidth;\n\n const previousTabId = useRef(activeTabId);\n\n // Marker animation\n useEffect(() => {\n const tabList = tabsListRef.current;\n const activeTab = tabList?.querySelector(`[data-tabid=\"${activeTabId}\"]`);\n if (!activeTab || !tabList) return;\n\n const { offsetHeight: containerHeight, offsetWidth: containerWidth } = tabList;\n const { offsetHeight, offsetWidth, offsetTop, offsetLeft } = activeTab as HTMLElement;\n\n // Calculate the height and width of the marker relative to the container\n const height = offsetHeight / containerHeight;\n const width = offsetWidth / containerWidth;\n\n // NOTE: Doing a DOM manipulation here to set the CSS variables for the marker\n // Not really the react idomatic way, but as long as it works we are able to skip some intermidiate `useState`\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-height\", String(height));\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-width\", String(width));\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-top\", `${offsetTop}px`);\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-left\", `${offsetLeft}px`);\n\n // Start with border fallback, then switch to the animated marker when the user changes tabs\n // This way the marker is placed immediately to the default tab, then animates smoothly to the next when selected\n if (previousTabId.current !== activeTabId) {\n tabsListRef.current.style.setProperty(\n \"--_hds-tabs-marker-animated-color\",\n \"var(--_hds-tabs-marker-color)\",\n );\n tabsListRef.current.style.setProperty(\n \"--_hds-tabs-marker-border-fallback-color\",\n \"transparent\",\n );\n }\n previousTabId.current = activeTabId;\n }, [activeTabId, innerWidth]);\n\n return (\n <div\n className={clsx(\n \"hds-tabs__list\",\n direction === \"horizontal\"\n ? {\n \"hds-tabs__list--horizontal\": wideEnough,\n \"hds-tabs__list--vertical\": !wideEnough,\n }\n : {\n \"hds-tabs__list--vertical\": true,\n },\n className as undefined,\n )}\n ref={tabsListRef}\n role=\"tablist\"\n {...rest}\n >\n {children}\n </div>\n );\n}\n\nTabsList.displayName = \"Tabs.List\";\n\nexport interface TabsTabProps extends HTMLAttributes<HTMLButtonElement> {\n children: ReactElement<HTMLElement> | string;\n\n /**\n * Identifier for the tab\n */\n tabId: string;\n}\n\nexport const TabsTab: OverridableComponent<TabsTabProps, HTMLButtonElement> = forwardRef(\n ({ as: Component = \"button\", children, tabId, className, onClick, ...rest }, ref) => {\n const context = useTabsContext();\n\n const toggleTab = (e: MouseEvent<HTMLButtonElement>) => {\n e.preventDefault();\n context.toggleActiveTabId(tabId);\n onClick && onClick(e);\n };\n return (\n <Component\n className={clsx(\n \"hds-tabs__tab\",\n { \"hds-tabs__tab--active\": context.activeTabId === tabId },\n className as undefined,\n )}\n data-tabid={tabId}\n onClick={toggleTab}\n ref={ref}\n role=\"tab\"\n {...rest}\n >\n {children}\n </Component>\n );\n },\n);\n\nTabsTab.displayName = \"Tabs.Tab\";\n","import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n","import type { HTMLAttributes, ReactElement } from \"react\";\nimport { forwardRef } from \"react\";\nimport { clsx } from \"@postenbring/hedwig-css/typed-classname\";\nimport type { OverridableComponent } from \"../utils\";\nimport { useTabsContext } from \"./context\";\n\nexport interface TabContentsProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactElement<TabsContentProps> | ReactElement<TabsContentProps>[];\n}\n\nexport function TabsContents({ children, ...rest }: TabContentsProps) {\n return (\n <div className={clsx(\"hds-tabs__contents\")} {...rest}>\n {children}\n </div>\n );\n}\nTabsContents.displayName = \"Tabs.Contents\";\n\nexport interface TabsContentProps extends HTMLAttributes<HTMLElement> {\n children: ReactElement<HTMLElement> | ReactElement<HTMLElement>[] | string;\n\n /**\n * Content for the referenced tabId\n */\n forTabId: string;\n}\n\nexport const TabsContent: OverridableComponent<TabsContentProps, HTMLElement> = forwardRef(\n ({ as: Component = \"div\", forTabId, children, ...rest }, ref) => {\n const context = useTabsContext();\n\n if (context.activeTabId === forTabId) {\n return (\n <Component {...rest} ref={ref}>\n {children}\n </Component>\n );\n }\n return null;\n },\n);\n\nTabsContent.displayName = \"Tabs.Content\";\n"],"mappings":"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","names":["import_react","import_react","import_typed_classname","import_react","import_jsx_runtime","import_react","import_typed_classname","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../../src/tabs/index.tsx","../../src/tabs/tabs.tsx","../../src/tabs/context.ts","../../src/tabs/tabs-list.tsx","../../src/utils.ts","../../src/tabs/tabs-content.tsx"],"sourcesContent":["import { Tabs } from \"./tabs\";\nimport { TabsList, TabsTab } from \"./tabs-list\";\nimport { TabsContents, TabsContent } from \"./tabs-content\";\n\nconst TabsComponent = Tabs as typeof Tabs & {\n List: typeof TabsList;\n Tab: typeof TabsTab;\n Contents: typeof TabsContents;\n Content: typeof TabsContent;\n};\nTabsComponent.List = TabsList;\nTabsComponent.Tab = TabsTab;\nTabsComponent.Contents = TabsContents;\nTabsComponent.Content = TabsContent;\n\nexport { TabsComponent as Tabs, TabsList, TabsTab, TabsContents, TabsContent };\n\nexport type * from \"./tabs\";\nexport type * from \"./tabs-list\";\nexport type * from \"./tabs-content\";\n","import type { HTMLAttributes, ReactElement } from \"react\";\nimport { forwardRef, useState } from \"react\";\nimport { clsx } from \"@postenbring/hedwig-css/typed-classname\";\nimport type { OverridableComponent } from \"../utils\";\nimport { TabsContext } from \"./context\";\nimport type { TabContentsProps } from \"./tabs-content\";\nimport type { TabListProps } from \"./tabs-list\";\n\nexport interface TabsProps extends HTMLAttributes<HTMLElement> {\n children: ReactElement<TabListProps | TabContentsProps>[] | ReactElement;\n\n /**\n * Define which tab to use as default. Must be one of the <Tab/>s identifier.\n */\n defaultTab: string;\n}\n\nexport const Tabs: OverridableComponent<TabsProps, HTMLDivElement> = forwardRef(\n ({ as: Component = \"div\", defaultTab, children, ...rest }, ref) => {\n const [activeTabId, setActiveTabId] = useState<string>(defaultTab);\n return (\n <Component className={clsx(\"hds-tabs\")} ref={ref} {...rest}>\n <TabsContext.Provider value={{ activeTabId, toggleActiveTabId: setActiveTabId }}>\n {children}\n </TabsContext.Provider>\n </Component>\n );\n },\n);\n\nTabs.displayName = \"Tabs\";\n","import { createContext, useContext } from \"react\";\n\nexport interface TabsContextProps {\n activeTabId: string;\n toggleActiveTabId: (tabId: string) => void;\n}\n\nexport const TabsContext = createContext<TabsContextProps | null>(null);\n\nexport function useTabsContext() {\n const context = useContext(TabsContext);\n if (!context) {\n throw new Error(\n \"Tabs context required. Did you use `<Tabs.List />`, `<Tabs.Tab />`, or `<Tabs.Content />` outside of <Tabs/>?\",\n );\n }\n return context;\n}\n","import type { HTMLAttributes, ReactElement, MouseEvent } from \"react\";\nimport { forwardRef, useEffect, useRef } from \"react\";\nimport { clsx } from \"@postenbring/hedwig-css/typed-classname\";\nimport { type OverridableComponent, useResize, useHydrated } from \"../utils\";\nimport { useTabsContext } from \"./context\";\n\nexport interface TabListProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactElement<TabsTabProps> | ReactElement<TabsTabProps>[];\n\n /**\n * Direction of the tabs. Can either be vertical or horizontal.\n * Horizontal breaks on window width with fallback back to vertical\n */\n direction?: \"vertical\" | \"horizontal\";\n}\n\nexport function TabsList({ children, direction = \"horizontal\", className, ...rest }: TabListProps) {\n const { activeTabId } = useTabsContext();\n const tabsListRef = useRef<HTMLDivElement>(null);\n const { width: tabsWidth } = useResize(tabsListRef);\n\n const isClientSide = useHydrated();\n const { innerWidth } = isClientSide ? window : { innerWidth: 1000 };\n const wideEnough = innerWidth >= tabsWidth;\n\n const previousTabId = useRef(activeTabId);\n\n // Marker animation\n useEffect(() => {\n const tabList = tabsListRef.current;\n const activeTab = tabList?.querySelector(`[data-tabid=\"${activeTabId}\"]`);\n if (!activeTab || !tabList) return;\n\n const { offsetHeight: containerHeight, offsetWidth: containerWidth } = tabList;\n const { offsetHeight, offsetWidth, offsetTop, offsetLeft } = activeTab as HTMLElement;\n\n // Calculate the height and width of the marker relative to the container\n const height = offsetHeight / containerHeight;\n const width = offsetWidth / containerWidth;\n\n // NOTE: Doing a DOM manipulation here to set the CSS variables for the marker\n // Not really the react idomatic way, but as long as it works we are able to skip some intermidiate `useState`\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-height\", String(height));\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-width\", String(width));\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-top\", `${offsetTop}px`);\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-left\", `${offsetLeft}px`);\n\n // Start with border fallback, then switch to the animated marker when the user changes tabs\n // This way the marker is placed immediately to the default tab, then animates smoothly to the next when selected\n if (previousTabId.current !== activeTabId) {\n tabsListRef.current.style.setProperty(\n \"--_hds-tabs-marker-animated-color\",\n \"var(--_hds-tabs-marker-color)\",\n );\n tabsListRef.current.style.setProperty(\n \"--_hds-tabs-marker-border-fallback-color\",\n \"transparent\",\n );\n }\n previousTabId.current = activeTabId;\n }, [activeTabId, innerWidth]);\n\n return (\n <div\n className={clsx(\n \"hds-tabs__list\",\n direction === \"horizontal\"\n ? {\n \"hds-tabs__list--horizontal\": wideEnough,\n \"hds-tabs__list--vertical\": !wideEnough,\n }\n : {\n \"hds-tabs__list--vertical\": true,\n },\n className as undefined,\n )}\n ref={tabsListRef}\n role=\"tablist\"\n {...rest}\n >\n {children}\n </div>\n );\n}\n\nTabsList.displayName = \"Tabs.List\";\n\nexport interface TabsTabProps extends HTMLAttributes<HTMLButtonElement> {\n children: ReactElement<HTMLElement> | string;\n\n /**\n * Identifier for the tab\n */\n tabId: string;\n}\n\nexport const TabsTab: OverridableComponent<TabsTabProps, HTMLButtonElement> = forwardRef(\n ({ as: Component = \"button\", children, tabId, className, onClick, ...rest }, ref) => {\n const context = useTabsContext();\n\n const toggleTab = (e: MouseEvent<HTMLButtonElement>) => {\n e.preventDefault();\n context.toggleActiveTabId(tabId);\n onClick && onClick(e);\n };\n return (\n <Component\n className={clsx(\n \"hds-tabs__tab\",\n { \"hds-tabs__tab--active\": context.activeTabId === tabId },\n className as undefined,\n )}\n data-tabid={tabId}\n onClick={toggleTab}\n ref={ref}\n role=\"tab\"\n {...rest}\n >\n {children}\n </Component>\n );\n },\n);\n\nTabsTab.displayName = \"Tabs.Tab\";\n","import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n\n/**\n * Trap focus inside an element using the `inert` attribute.\n *\n * Adds `inert` to all siblings of the given element, and all their ancestors up to the body.\n * Returns a cleanup function which removes the `inert` property from the elements, effectively giving focus back to rest of the document.\n *\n * NOTE: Does not support portals, i.e. elements outside the DOM hierarchy of the given element.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert\n * @see https://web.dev/articles/inert\n */\nexport function focusTrap(element: HTMLElement) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- NOP on focus trapping the body element\n if (element === document.body) return () => {};\n\n let inertElements: HTMLElement[] = [];\n for (let el: HTMLElement | null = element; el; el = el.parentElement) {\n if (el === document.body) break;\n\n for (const sibling of el.parentElement?.children ?? []) {\n if (sibling === el) continue;\n if (!(sibling instanceof HTMLElement)) continue;\n if (sibling.hasAttribute(\"inert\")) continue;\n\n sibling.setAttribute(\"inert\", \"true\");\n inertElements.push(sibling);\n }\n }\n\n return () => {\n releaseFocusTrap(inertElements);\n inertElements = [];\n };\n}\n\n/**\n * Unset the `inert` attribute on all elements given\n */\nexport function releaseFocusTrap(inertElements: Iterable<HTMLElement>) {\n for (const el of inertElements) {\n el.removeAttribute(\"inert\");\n }\n}\n","import type { HTMLAttributes, ReactElement } from \"react\";\nimport { forwardRef } from \"react\";\nimport { clsx } from \"@postenbring/hedwig-css/typed-classname\";\nimport type { OverridableComponent } from \"../utils\";\nimport { useTabsContext } from \"./context\";\n\nexport interface TabContentsProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactElement<TabsContentProps> | ReactElement<TabsContentProps>[];\n}\n\nexport function TabsContents({ children, ...rest }: TabContentsProps) {\n return (\n <div className={clsx(\"hds-tabs__contents\")} {...rest}>\n {children}\n </div>\n );\n}\nTabsContents.displayName = \"Tabs.Contents\";\n\nexport interface TabsContentProps extends HTMLAttributes<HTMLElement> {\n children: ReactElement<HTMLElement> | ReactElement<HTMLElement>[] | string;\n\n /**\n * Content for the referenced tabId\n */\n forTabId: string;\n}\n\nexport const TabsContent: OverridableComponent<TabsContentProps, HTMLElement> = forwardRef(\n ({ as: Component = \"div\", forTabId, children, ...rest }, ref) => {\n const context = useTabsContext();\n\n if (context.activeTabId === forTabId) {\n return (\n <Component {...rest} ref={ref}>\n {children}\n </Component>\n );\n }\n return null;\n },\n);\n\nTabsContent.displayName = \"Tabs.Content\";\n"],"mappings":"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","names":["import_react","import_react","import_typed_classname","import_react","import_jsx_runtime","import_react","import_typed_classname","import_jsx_runtime"]}
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  TabsComponent
3
- } from "../chunk-CSFSJGLY.mjs";
3
+ } from "../chunk-E2AG5TUR.mjs";
4
4
  import {
5
5
  TabsList,
6
6
  TabsTab
7
- } from "../chunk-B56JZJOS.mjs";
7
+ } from "../chunk-SRLRTLHS.mjs";
8
8
  import "../chunk-XVFQWVHO.mjs";
9
9
  import {
10
10
  TabsContent,
11
11
  TabsContents
12
12
  } from "../chunk-UWTGHSWT.mjs";
13
13
  import "../chunk-KQITCS3U.mjs";
14
- import "../chunk-ZL56N4UK.mjs";
14
+ import "../chunk-JXA3B33M.mjs";
15
15
  import "../chunk-R4SQKVDQ.mjs";
16
16
  export {
17
17
  TabsComponent as Tabs,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tabs/tabs-list.tsx","../../src/utils.ts","../../src/tabs/context.ts"],"sourcesContent":["import type { HTMLAttributes, ReactElement, MouseEvent } from \"react\";\nimport { forwardRef, useEffect, useRef } from \"react\";\nimport { clsx } from \"@postenbring/hedwig-css/typed-classname\";\nimport { type OverridableComponent, useResize, useHydrated } from \"../utils\";\nimport { useTabsContext } from \"./context\";\n\nexport interface TabListProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactElement<TabsTabProps> | ReactElement<TabsTabProps>[];\n\n /**\n * Direction of the tabs. Can either be vertical or horizontal.\n * Horizontal breaks on window width with fallback back to vertical\n */\n direction?: \"vertical\" | \"horizontal\";\n}\n\nexport function TabsList({ children, direction = \"horizontal\", className, ...rest }: TabListProps) {\n const { activeTabId } = useTabsContext();\n const tabsListRef = useRef<HTMLDivElement>(null);\n const { width: tabsWidth } = useResize(tabsListRef);\n\n const isClientSide = useHydrated();\n const { innerWidth } = isClientSide ? window : { innerWidth: 1000 };\n const wideEnough = innerWidth >= tabsWidth;\n\n const previousTabId = useRef(activeTabId);\n\n // Marker animation\n useEffect(() => {\n const tabList = tabsListRef.current;\n const activeTab = tabList?.querySelector(`[data-tabid=\"${activeTabId}\"]`);\n if (!activeTab || !tabList) return;\n\n const { offsetHeight: containerHeight, offsetWidth: containerWidth } = tabList;\n const { offsetHeight, offsetWidth, offsetTop, offsetLeft } = activeTab as HTMLElement;\n\n // Calculate the height and width of the marker relative to the container\n const height = offsetHeight / containerHeight;\n const width = offsetWidth / containerWidth;\n\n // NOTE: Doing a DOM manipulation here to set the CSS variables for the marker\n // Not really the react idomatic way, but as long as it works we are able to skip some intermidiate `useState`\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-height\", String(height));\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-width\", String(width));\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-top\", `${offsetTop}px`);\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-left\", `${offsetLeft}px`);\n\n // Start with border fallback, then switch to the animated marker when the user changes tabs\n // This way the marker is placed immediately to the default tab, then animates smoothly to the next when selected\n if (previousTabId.current !== activeTabId) {\n tabsListRef.current.style.setProperty(\n \"--_hds-tabs-marker-animated-color\",\n \"var(--_hds-tabs-marker-color)\",\n );\n tabsListRef.current.style.setProperty(\n \"--_hds-tabs-marker-border-fallback-color\",\n \"transparent\",\n );\n }\n previousTabId.current = activeTabId;\n }, [activeTabId, innerWidth]);\n\n return (\n <div\n className={clsx(\n \"hds-tabs__list\",\n direction === \"horizontal\"\n ? {\n \"hds-tabs__list--horizontal\": wideEnough,\n \"hds-tabs__list--vertical\": !wideEnough,\n }\n : {\n \"hds-tabs__list--vertical\": true,\n },\n className as undefined,\n )}\n ref={tabsListRef}\n role=\"tablist\"\n {...rest}\n >\n {children}\n </div>\n );\n}\n\nTabsList.displayName = \"Tabs.List\";\n\nexport interface TabsTabProps extends HTMLAttributes<HTMLButtonElement> {\n children: ReactElement<HTMLElement> | string;\n\n /**\n * Identifier for the tab\n */\n tabId: string;\n}\n\nexport const TabsTab: OverridableComponent<TabsTabProps, HTMLButtonElement> = forwardRef(\n ({ as: Component = \"button\", children, tabId, className, onClick, ...rest }, ref) => {\n const context = useTabsContext();\n\n const toggleTab = (e: MouseEvent<HTMLButtonElement>) => {\n e.preventDefault();\n context.toggleActiveTabId(tabId);\n onClick && onClick(e);\n };\n return (\n <Component\n className={clsx(\n \"hds-tabs__tab\",\n { \"hds-tabs__tab--active\": context.activeTabId === tabId },\n className as undefined,\n )}\n data-tabid={tabId}\n onClick={toggleTab}\n ref={ref}\n role=\"tab\"\n {...rest}\n >\n {children}\n </Component>\n );\n },\n);\n\nTabsTab.displayName = \"Tabs.Tab\";\n","import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n","import { createContext, useContext } from \"react\";\n\nexport interface TabsContextProps {\n activeTabId: string;\n toggleActiveTabId: (tabId: string) => void;\n}\n\nexport const TabsContext = createContext<TabsContextProps | null>(null);\n\nexport function useTabsContext() {\n const context = useContext(TabsContext);\n if (!context) {\n throw new Error(\n \"Tabs context required. Did you use `<Tabs.List />`, `<Tabs.Tab />`, or `<Tabs.Content />` outside of <Tabs/>?\",\n );\n }\n return context;\n}\n"],"mappings":"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","names":["import_react","import_react"]}
1
+ {"version":3,"sources":["../../src/tabs/tabs-list.tsx","../../src/utils.ts","../../src/tabs/context.ts"],"sourcesContent":["import type { HTMLAttributes, ReactElement, MouseEvent } from \"react\";\nimport { forwardRef, useEffect, useRef } from \"react\";\nimport { clsx } from \"@postenbring/hedwig-css/typed-classname\";\nimport { type OverridableComponent, useResize, useHydrated } from \"../utils\";\nimport { useTabsContext } from \"./context\";\n\nexport interface TabListProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactElement<TabsTabProps> | ReactElement<TabsTabProps>[];\n\n /**\n * Direction of the tabs. Can either be vertical or horizontal.\n * Horizontal breaks on window width with fallback back to vertical\n */\n direction?: \"vertical\" | \"horizontal\";\n}\n\nexport function TabsList({ children, direction = \"horizontal\", className, ...rest }: TabListProps) {\n const { activeTabId } = useTabsContext();\n const tabsListRef = useRef<HTMLDivElement>(null);\n const { width: tabsWidth } = useResize(tabsListRef);\n\n const isClientSide = useHydrated();\n const { innerWidth } = isClientSide ? window : { innerWidth: 1000 };\n const wideEnough = innerWidth >= tabsWidth;\n\n const previousTabId = useRef(activeTabId);\n\n // Marker animation\n useEffect(() => {\n const tabList = tabsListRef.current;\n const activeTab = tabList?.querySelector(`[data-tabid=\"${activeTabId}\"]`);\n if (!activeTab || !tabList) return;\n\n const { offsetHeight: containerHeight, offsetWidth: containerWidth } = tabList;\n const { offsetHeight, offsetWidth, offsetTop, offsetLeft } = activeTab as HTMLElement;\n\n // Calculate the height and width of the marker relative to the container\n const height = offsetHeight / containerHeight;\n const width = offsetWidth / containerWidth;\n\n // NOTE: Doing a DOM manipulation here to set the CSS variables for the marker\n // Not really the react idomatic way, but as long as it works we are able to skip some intermidiate `useState`\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-height\", String(height));\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-width\", String(width));\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-top\", `${offsetTop}px`);\n tabsListRef.current.style.setProperty(\"--_hds-tabs-marker-left\", `${offsetLeft}px`);\n\n // Start with border fallback, then switch to the animated marker when the user changes tabs\n // This way the marker is placed immediately to the default tab, then animates smoothly to the next when selected\n if (previousTabId.current !== activeTabId) {\n tabsListRef.current.style.setProperty(\n \"--_hds-tabs-marker-animated-color\",\n \"var(--_hds-tabs-marker-color)\",\n );\n tabsListRef.current.style.setProperty(\n \"--_hds-tabs-marker-border-fallback-color\",\n \"transparent\",\n );\n }\n previousTabId.current = activeTabId;\n }, [activeTabId, innerWidth]);\n\n return (\n <div\n className={clsx(\n \"hds-tabs__list\",\n direction === \"horizontal\"\n ? {\n \"hds-tabs__list--horizontal\": wideEnough,\n \"hds-tabs__list--vertical\": !wideEnough,\n }\n : {\n \"hds-tabs__list--vertical\": true,\n },\n className as undefined,\n )}\n ref={tabsListRef}\n role=\"tablist\"\n {...rest}\n >\n {children}\n </div>\n );\n}\n\nTabsList.displayName = \"Tabs.List\";\n\nexport interface TabsTabProps extends HTMLAttributes<HTMLButtonElement> {\n children: ReactElement<HTMLElement> | string;\n\n /**\n * Identifier for the tab\n */\n tabId: string;\n}\n\nexport const TabsTab: OverridableComponent<TabsTabProps, HTMLButtonElement> = forwardRef(\n ({ as: Component = \"button\", children, tabId, className, onClick, ...rest }, ref) => {\n const context = useTabsContext();\n\n const toggleTab = (e: MouseEvent<HTMLButtonElement>) => {\n e.preventDefault();\n context.toggleActiveTabId(tabId);\n onClick && onClick(e);\n };\n return (\n <Component\n className={clsx(\n \"hds-tabs__tab\",\n { \"hds-tabs__tab--active\": context.activeTabId === tabId },\n className as undefined,\n )}\n data-tabid={tabId}\n onClick={toggleTab}\n ref={ref}\n role=\"tab\"\n {...rest}\n >\n {children}\n </Component>\n );\n },\n);\n\nTabsTab.displayName = \"Tabs.Tab\";\n","import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n\n/**\n * Trap focus inside an element using the `inert` attribute.\n *\n * Adds `inert` to all siblings of the given element, and all their ancestors up to the body.\n * Returns a cleanup function which removes the `inert` property from the elements, effectively giving focus back to rest of the document.\n *\n * NOTE: Does not support portals, i.e. elements outside the DOM hierarchy of the given element.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert\n * @see https://web.dev/articles/inert\n */\nexport function focusTrap(element: HTMLElement) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- NOP on focus trapping the body element\n if (element === document.body) return () => {};\n\n let inertElements: HTMLElement[] = [];\n for (let el: HTMLElement | null = element; el; el = el.parentElement) {\n if (el === document.body) break;\n\n for (const sibling of el.parentElement?.children ?? []) {\n if (sibling === el) continue;\n if (!(sibling instanceof HTMLElement)) continue;\n if (sibling.hasAttribute(\"inert\")) continue;\n\n sibling.setAttribute(\"inert\", \"true\");\n inertElements.push(sibling);\n }\n }\n\n return () => {\n releaseFocusTrap(inertElements);\n inertElements = [];\n };\n}\n\n/**\n * Unset the `inert` attribute on all elements given\n */\nexport function releaseFocusTrap(inertElements: Iterable<HTMLElement>) {\n for (const el of inertElements) {\n el.removeAttribute(\"inert\");\n }\n}\n","import { createContext, useContext } from \"react\";\n\nexport interface TabsContextProps {\n activeTabId: string;\n toggleActiveTabId: (tabId: string) => void;\n}\n\nexport const TabsContext = createContext<TabsContextProps | null>(null);\n\nexport function useTabsContext() {\n const context = useContext(TabsContext);\n if (!context) {\n throw new Error(\n \"Tabs context required. Did you use `<Tabs.List />`, `<Tabs.Tab />`, or `<Tabs.Content />` outside of <Tabs/>?\",\n );\n }\n return context;\n}\n"],"mappings":"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","names":["import_react","import_react"]}
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  TabsList,
3
3
  TabsTab
4
- } from "../chunk-B56JZJOS.mjs";
4
+ } from "../chunk-SRLRTLHS.mjs";
5
5
  import "../chunk-KQITCS3U.mjs";
6
- import "../chunk-ZL56N4UK.mjs";
6
+ import "../chunk-JXA3B33M.mjs";
7
7
  import "../chunk-R4SQKVDQ.mjs";
8
8
  export {
9
9
  TabsList,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/auto-animate-height.tsx","../../src/utils.ts"],"sourcesContent":["import { cloneElement, forwardRef, useEffect, useRef, useState } from \"react\";\nimport { useMergeRefs, type OverridableComponent } from \"../utils\";\n\nexport interface AutoAnimateHeightProps {\n /**\n * Time of the animation, using the hedwig animation tokens\n * quick: 0.1s\n * normal: 0.3s\n * slow: 0.7s\n *\n * default is \"quick\"\n */\n animationDuration?: \"quick\" | \"normal\" | \"slow\";\n\n /**\n * Callback fired when animiation transition ends\n * Use this to do effects after resizing is done, e.g. scrolling to the element\n * using `element.scrollIntoView()`\n */\n onTransitionEnd?: () => void;\n\n /**\n * Which hedwig easing function to use, default is \"normal\"\n */\n animationEasing?: \"in\" | \"out\" | \"normal\";\n children: React.ReactNode;\n style?: React.CSSProperties;\n}\n\n/**\n * Helper component to animate the height of the children when they change\n * It's done by rendering two versions of the passed children,\n * one hidden to measure the height and one visible to only changes after the height is measured.\n *\n * **IMPORTANT** Do not pass any components with effects (like data fetching), as they will trigger twice.\n */\nexport const AutoAnimateHeight: OverridableComponent<AutoAnimateHeightProps, HTMLDivElement> =\n forwardRef(\n (\n {\n as: Component = \"div\",\n children,\n style,\n animationDuration = \"quick\",\n animationEasing = \"normal\",\n onTransitionEnd,\n ...rest\n },\n ref,\n ) => {\n const rootRef = useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs([rootRef, ref]);\n const measurementRef = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<{ height: number; shouldAnimate: boolean } | undefined>(\n undefined,\n );\n const [clonedChildren, setClonedChildren] = useState<React.ReactNode>(() =>\n cloneElement(<>{children}</>, {}),\n );\n\n useEffect(() => {\n if (!rootRef.current) return;\n if (!measurementRef.current) return;\n if (document.body.scrollHeight === 0) return;\n const currentMeasurement = measurementRef.current;\n const { height: newHeight } = currentMeasurement.getBoundingClientRect();\n\n // Listen for resize events on the measurement element\n // Keep the children in sync with the height\n // But don't animate it.\n let previouslyObservedHeight = newHeight;\n const resizeObserver = new ResizeObserver(() => {\n const { height: resizedHeight } = currentMeasurement.getBoundingClientRect();\n if (resizedHeight === previouslyObservedHeight) return;\n previouslyObservedHeight = resizedHeight;\n setHeight({ height: resizedHeight, shouldAnimate: false });\n });\n resizeObserver.observe(currentMeasurement); // This is cleaned up down below in the return functions\n\n // Set the new height when children changes\n setHeight({ height: newHeight, shouldAnimate: true });\n\n // Update children\n const nextClonedChildren = cloneElement(<>{children}</>, {});\n\n // When increasing in height update immediately so the new content is shown during the animation\n if (newHeight >= (height?.height ?? 0)) {\n setClonedChildren(nextClonedChildren);\n return () => {\n resizeObserver.disconnect();\n };\n }\n\n // When decreasing in height, wait until the animation is done so that we don't get a sudden flash of empty content\n const currentRoot = rootRef.current;\n function onTransitionEndHandler(e: TransitionEvent) {\n if (e.propertyName !== \"height\") return;\n setClonedChildren(nextClonedChildren);\n }\n currentRoot.addEventListener(\"transitionend\", onTransitionEndHandler);\n return () => {\n resizeObserver.disconnect();\n currentRoot.removeEventListener(\"transitionend\", onTransitionEndHandler);\n };\n\n // eslint-disable-next-line react-hooks/exhaustive-deps -- I know better\n }, [children]);\n\n return (\n <Component\n ref={mergedRef}\n onTransitionEnd={onTransitionEnd}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n height: height?.height ?? measurementRef.current?.getBoundingClientRect().height,\n transitionProperty: height?.shouldAnimate ? \"height\" : \"none\",\n transitionDuration: `var(--hds-micro-animation-duration-${animationDuration})`,\n transitionTimingFunction: `var(--hds-micro-animation-easing-${animationEasing})`,\n willChange: \"height\",\n ...style,\n }}\n {...rest}\n >\n <div\n aria-hidden\n ref={measurementRef}\n style={{\n position: \"absolute\",\n visibility: \"hidden\",\n }}\n >\n {children}\n </div>\n {clonedChildren}\n </Component>\n );\n },\n );\nAutoAnimateHeight.displayName = \"AutoAnimateHeight\";\n","import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n"],"mappings":"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","names":["import_react","_a","_b"]}
1
+ {"version":3,"sources":["../../src/utilities/auto-animate-height.tsx","../../src/utils.ts"],"sourcesContent":["import { cloneElement, forwardRef, useEffect, useRef, useState } from \"react\";\nimport { useMergeRefs, type OverridableComponent } from \"../utils\";\n\nexport interface AutoAnimateHeightProps {\n /**\n * Time of the animation, using the hedwig animation tokens\n * quick: 0.1s\n * normal: 0.3s\n * slow: 0.7s\n *\n * default is \"quick\"\n */\n animationDuration?: \"quick\" | \"normal\" | \"slow\";\n\n /**\n * Callback fired when animiation transition ends\n * Use this to do effects after resizing is done, e.g. scrolling to the element\n * using `element.scrollIntoView()`\n */\n onTransitionEnd?: () => void;\n\n /**\n * Which hedwig easing function to use, default is \"normal\"\n */\n animationEasing?: \"in\" | \"out\" | \"normal\";\n children: React.ReactNode;\n style?: React.CSSProperties;\n}\n\n/**\n * Helper component to animate the height of the children when they change\n * It's done by rendering two versions of the passed children,\n * one hidden to measure the height and one visible to only changes after the height is measured.\n *\n * **IMPORTANT** Do not pass any components with effects (like data fetching), as they will trigger twice.\n */\nexport const AutoAnimateHeight: OverridableComponent<AutoAnimateHeightProps, HTMLDivElement> =\n forwardRef(\n (\n {\n as: Component = \"div\",\n children,\n style,\n animationDuration = \"quick\",\n animationEasing = \"normal\",\n onTransitionEnd,\n ...rest\n },\n ref,\n ) => {\n const rootRef = useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs([rootRef, ref]);\n const measurementRef = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<{ height: number; shouldAnimate: boolean } | undefined>(\n undefined,\n );\n const [clonedChildren, setClonedChildren] = useState<React.ReactNode>(() =>\n cloneElement(<>{children}</>, {}),\n );\n\n useEffect(() => {\n if (!rootRef.current) return;\n if (!measurementRef.current) return;\n if (document.body.scrollHeight === 0) return;\n const currentMeasurement = measurementRef.current;\n const { height: newHeight } = currentMeasurement.getBoundingClientRect();\n\n // Listen for resize events on the measurement element\n // Keep the children in sync with the height\n // But don't animate it.\n let previouslyObservedHeight = newHeight;\n const resizeObserver = new ResizeObserver(() => {\n const { height: resizedHeight } = currentMeasurement.getBoundingClientRect();\n if (resizedHeight === previouslyObservedHeight) return;\n previouslyObservedHeight = resizedHeight;\n setHeight({ height: resizedHeight, shouldAnimate: false });\n });\n resizeObserver.observe(currentMeasurement); // This is cleaned up down below in the return functions\n\n // Set the new height when children changes\n setHeight({ height: newHeight, shouldAnimate: true });\n\n // Update children\n const nextClonedChildren = cloneElement(<>{children}</>, {});\n\n // When increasing in height update immediately so the new content is shown during the animation\n if (newHeight >= (height?.height ?? 0)) {\n setClonedChildren(nextClonedChildren);\n return () => {\n resizeObserver.disconnect();\n };\n }\n\n // When decreasing in height, wait until the animation is done so that we don't get a sudden flash of empty content\n const currentRoot = rootRef.current;\n function onTransitionEndHandler(e: TransitionEvent) {\n if (e.propertyName !== \"height\") return;\n setClonedChildren(nextClonedChildren);\n }\n currentRoot.addEventListener(\"transitionend\", onTransitionEndHandler);\n return () => {\n resizeObserver.disconnect();\n currentRoot.removeEventListener(\"transitionend\", onTransitionEndHandler);\n };\n\n // eslint-disable-next-line react-hooks/exhaustive-deps -- I know better\n }, [children]);\n\n return (\n <Component\n ref={mergedRef}\n onTransitionEnd={onTransitionEnd}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n height: height?.height ?? measurementRef.current?.getBoundingClientRect().height,\n transitionProperty: height?.shouldAnimate ? \"height\" : \"none\",\n transitionDuration: `var(--hds-micro-animation-duration-${animationDuration})`,\n transitionTimingFunction: `var(--hds-micro-animation-easing-${animationEasing})`,\n willChange: \"height\",\n ...style,\n }}\n {...rest}\n >\n <div\n aria-hidden\n ref={measurementRef}\n style={{\n position: \"absolute\",\n visibility: \"hidden\",\n }}\n >\n {children}\n </div>\n {clonedChildren}\n </Component>\n );\n },\n );\nAutoAnimateHeight.displayName = \"AutoAnimateHeight\";\n","import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n\n/**\n * Trap focus inside an element using the `inert` attribute.\n *\n * Adds `inert` to all siblings of the given element, and all their ancestors up to the body.\n * Returns a cleanup function which removes the `inert` property from the elements, effectively giving focus back to rest of the document.\n *\n * NOTE: Does not support portals, i.e. elements outside the DOM hierarchy of the given element.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert\n * @see https://web.dev/articles/inert\n */\nexport function focusTrap(element: HTMLElement) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- NOP on focus trapping the body element\n if (element === document.body) return () => {};\n\n let inertElements: HTMLElement[] = [];\n for (let el: HTMLElement | null = element; el; el = el.parentElement) {\n if (el === document.body) break;\n\n for (const sibling of el.parentElement?.children ?? []) {\n if (sibling === el) continue;\n if (!(sibling instanceof HTMLElement)) continue;\n if (sibling.hasAttribute(\"inert\")) continue;\n\n sibling.setAttribute(\"inert\", \"true\");\n inertElements.push(sibling);\n }\n }\n\n return () => {\n releaseFocusTrap(inertElements);\n inertElements = [];\n };\n}\n\n/**\n * Unset the `inert` attribute on all elements given\n */\nexport function releaseFocusTrap(inertElements: Iterable<HTMLElement>) {\n for (const el of inertElements) {\n el.removeAttribute(\"inert\");\n }\n}\n"],"mappings":"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","names":["import_react","_a","_b"]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  AutoAnimateHeight
3
- } from "../chunk-HSIL53A5.mjs";
4
- import "../chunk-ZL56N4UK.mjs";
3
+ } from "../chunk-UXJIK76H.mjs";
4
+ import "../chunk-JXA3B33M.mjs";
5
5
  import "../chunk-R4SQKVDQ.mjs";
6
6
  export {
7
7
  AutoAnimateHeight
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/index.ts","../../src/utilities/auto-animate-height.tsx","../../src/utils.ts"],"sourcesContent":["export { AutoAnimateHeight } from \"./auto-animate-height\";\nexport type * from \"./auto-animate-height\";\n","import { cloneElement, forwardRef, useEffect, useRef, useState } from \"react\";\nimport { useMergeRefs, type OverridableComponent } from \"../utils\";\n\nexport interface AutoAnimateHeightProps {\n /**\n * Time of the animation, using the hedwig animation tokens\n * quick: 0.1s\n * normal: 0.3s\n * slow: 0.7s\n *\n * default is \"quick\"\n */\n animationDuration?: \"quick\" | \"normal\" | \"slow\";\n\n /**\n * Callback fired when animiation transition ends\n * Use this to do effects after resizing is done, e.g. scrolling to the element\n * using `element.scrollIntoView()`\n */\n onTransitionEnd?: () => void;\n\n /**\n * Which hedwig easing function to use, default is \"normal\"\n */\n animationEasing?: \"in\" | \"out\" | \"normal\";\n children: React.ReactNode;\n style?: React.CSSProperties;\n}\n\n/**\n * Helper component to animate the height of the children when they change\n * It's done by rendering two versions of the passed children,\n * one hidden to measure the height and one visible to only changes after the height is measured.\n *\n * **IMPORTANT** Do not pass any components with effects (like data fetching), as they will trigger twice.\n */\nexport const AutoAnimateHeight: OverridableComponent<AutoAnimateHeightProps, HTMLDivElement> =\n forwardRef(\n (\n {\n as: Component = \"div\",\n children,\n style,\n animationDuration = \"quick\",\n animationEasing = \"normal\",\n onTransitionEnd,\n ...rest\n },\n ref,\n ) => {\n const rootRef = useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs([rootRef, ref]);\n const measurementRef = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<{ height: number; shouldAnimate: boolean } | undefined>(\n undefined,\n );\n const [clonedChildren, setClonedChildren] = useState<React.ReactNode>(() =>\n cloneElement(<>{children}</>, {}),\n );\n\n useEffect(() => {\n if (!rootRef.current) return;\n if (!measurementRef.current) return;\n if (document.body.scrollHeight === 0) return;\n const currentMeasurement = measurementRef.current;\n const { height: newHeight } = currentMeasurement.getBoundingClientRect();\n\n // Listen for resize events on the measurement element\n // Keep the children in sync with the height\n // But don't animate it.\n let previouslyObservedHeight = newHeight;\n const resizeObserver = new ResizeObserver(() => {\n const { height: resizedHeight } = currentMeasurement.getBoundingClientRect();\n if (resizedHeight === previouslyObservedHeight) return;\n previouslyObservedHeight = resizedHeight;\n setHeight({ height: resizedHeight, shouldAnimate: false });\n });\n resizeObserver.observe(currentMeasurement); // This is cleaned up down below in the return functions\n\n // Set the new height when children changes\n setHeight({ height: newHeight, shouldAnimate: true });\n\n // Update children\n const nextClonedChildren = cloneElement(<>{children}</>, {});\n\n // When increasing in height update immediately so the new content is shown during the animation\n if (newHeight >= (height?.height ?? 0)) {\n setClonedChildren(nextClonedChildren);\n return () => {\n resizeObserver.disconnect();\n };\n }\n\n // When decreasing in height, wait until the animation is done so that we don't get a sudden flash of empty content\n const currentRoot = rootRef.current;\n function onTransitionEndHandler(e: TransitionEvent) {\n if (e.propertyName !== \"height\") return;\n setClonedChildren(nextClonedChildren);\n }\n currentRoot.addEventListener(\"transitionend\", onTransitionEndHandler);\n return () => {\n resizeObserver.disconnect();\n currentRoot.removeEventListener(\"transitionend\", onTransitionEndHandler);\n };\n\n // eslint-disable-next-line react-hooks/exhaustive-deps -- I know better\n }, [children]);\n\n return (\n <Component\n ref={mergedRef}\n onTransitionEnd={onTransitionEnd}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n height: height?.height ?? measurementRef.current?.getBoundingClientRect().height,\n transitionProperty: height?.shouldAnimate ? \"height\" : \"none\",\n transitionDuration: `var(--hds-micro-animation-duration-${animationDuration})`,\n transitionTimingFunction: `var(--hds-micro-animation-easing-${animationEasing})`,\n willChange: \"height\",\n ...style,\n }}\n {...rest}\n >\n <div\n aria-hidden\n ref={measurementRef}\n style={{\n position: \"absolute\",\n visibility: \"hidden\",\n }}\n >\n {children}\n </div>\n {clonedChildren}\n </Component>\n );\n },\n );\nAutoAnimateHeight.displayName = \"AutoAnimateHeight\";\n","import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n"],"mappings":"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","names":["import_react","_a","_b"]}
1
+ {"version":3,"sources":["../../src/utilities/index.ts","../../src/utilities/auto-animate-height.tsx","../../src/utils.ts"],"sourcesContent":["export { AutoAnimateHeight } from \"./auto-animate-height\";\nexport type * from \"./auto-animate-height\";\n","import { cloneElement, forwardRef, useEffect, useRef, useState } from \"react\";\nimport { useMergeRefs, type OverridableComponent } from \"../utils\";\n\nexport interface AutoAnimateHeightProps {\n /**\n * Time of the animation, using the hedwig animation tokens\n * quick: 0.1s\n * normal: 0.3s\n * slow: 0.7s\n *\n * default is \"quick\"\n */\n animationDuration?: \"quick\" | \"normal\" | \"slow\";\n\n /**\n * Callback fired when animiation transition ends\n * Use this to do effects after resizing is done, e.g. scrolling to the element\n * using `element.scrollIntoView()`\n */\n onTransitionEnd?: () => void;\n\n /**\n * Which hedwig easing function to use, default is \"normal\"\n */\n animationEasing?: \"in\" | \"out\" | \"normal\";\n children: React.ReactNode;\n style?: React.CSSProperties;\n}\n\n/**\n * Helper component to animate the height of the children when they change\n * It's done by rendering two versions of the passed children,\n * one hidden to measure the height and one visible to only changes after the height is measured.\n *\n * **IMPORTANT** Do not pass any components with effects (like data fetching), as they will trigger twice.\n */\nexport const AutoAnimateHeight: OverridableComponent<AutoAnimateHeightProps, HTMLDivElement> =\n forwardRef(\n (\n {\n as: Component = \"div\",\n children,\n style,\n animationDuration = \"quick\",\n animationEasing = \"normal\",\n onTransitionEnd,\n ...rest\n },\n ref,\n ) => {\n const rootRef = useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs([rootRef, ref]);\n const measurementRef = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<{ height: number; shouldAnimate: boolean } | undefined>(\n undefined,\n );\n const [clonedChildren, setClonedChildren] = useState<React.ReactNode>(() =>\n cloneElement(<>{children}</>, {}),\n );\n\n useEffect(() => {\n if (!rootRef.current) return;\n if (!measurementRef.current) return;\n if (document.body.scrollHeight === 0) return;\n const currentMeasurement = measurementRef.current;\n const { height: newHeight } = currentMeasurement.getBoundingClientRect();\n\n // Listen for resize events on the measurement element\n // Keep the children in sync with the height\n // But don't animate it.\n let previouslyObservedHeight = newHeight;\n const resizeObserver = new ResizeObserver(() => {\n const { height: resizedHeight } = currentMeasurement.getBoundingClientRect();\n if (resizedHeight === previouslyObservedHeight) return;\n previouslyObservedHeight = resizedHeight;\n setHeight({ height: resizedHeight, shouldAnimate: false });\n });\n resizeObserver.observe(currentMeasurement); // This is cleaned up down below in the return functions\n\n // Set the new height when children changes\n setHeight({ height: newHeight, shouldAnimate: true });\n\n // Update children\n const nextClonedChildren = cloneElement(<>{children}</>, {});\n\n // When increasing in height update immediately so the new content is shown during the animation\n if (newHeight >= (height?.height ?? 0)) {\n setClonedChildren(nextClonedChildren);\n return () => {\n resizeObserver.disconnect();\n };\n }\n\n // When decreasing in height, wait until the animation is done so that we don't get a sudden flash of empty content\n const currentRoot = rootRef.current;\n function onTransitionEndHandler(e: TransitionEvent) {\n if (e.propertyName !== \"height\") return;\n setClonedChildren(nextClonedChildren);\n }\n currentRoot.addEventListener(\"transitionend\", onTransitionEndHandler);\n return () => {\n resizeObserver.disconnect();\n currentRoot.removeEventListener(\"transitionend\", onTransitionEndHandler);\n };\n\n // eslint-disable-next-line react-hooks/exhaustive-deps -- I know better\n }, [children]);\n\n return (\n <Component\n ref={mergedRef}\n onTransitionEnd={onTransitionEnd}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n height: height?.height ?? measurementRef.current?.getBoundingClientRect().height,\n transitionProperty: height?.shouldAnimate ? \"height\" : \"none\",\n transitionDuration: `var(--hds-micro-animation-duration-${animationDuration})`,\n transitionTimingFunction: `var(--hds-micro-animation-easing-${animationEasing})`,\n willChange: \"height\",\n ...style,\n }}\n {...rest}\n >\n <div\n aria-hidden\n ref={measurementRef}\n style={{\n position: \"absolute\",\n visibility: \"hidden\",\n }}\n >\n {children}\n </div>\n {clonedChildren}\n </Component>\n );\n },\n );\nAutoAnimateHeight.displayName = \"AutoAnimateHeight\";\n","import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n\n/**\n * Trap focus inside an element using the `inert` attribute.\n *\n * Adds `inert` to all siblings of the given element, and all their ancestors up to the body.\n * Returns a cleanup function which removes the `inert` property from the elements, effectively giving focus back to rest of the document.\n *\n * NOTE: Does not support portals, i.e. elements outside the DOM hierarchy of the given element.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert\n * @see https://web.dev/articles/inert\n */\nexport function focusTrap(element: HTMLElement) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- NOP on focus trapping the body element\n if (element === document.body) return () => {};\n\n let inertElements: HTMLElement[] = [];\n for (let el: HTMLElement | null = element; el; el = el.parentElement) {\n if (el === document.body) break;\n\n for (const sibling of el.parentElement?.children ?? []) {\n if (sibling === el) continue;\n if (!(sibling instanceof HTMLElement)) continue;\n if (sibling.hasAttribute(\"inert\")) continue;\n\n sibling.setAttribute(\"inert\", \"true\");\n inertElements.push(sibling);\n }\n }\n\n return () => {\n releaseFocusTrap(inertElements);\n inertElements = [];\n };\n}\n\n/**\n * Unset the `inert` attribute on all elements given\n */\nexport function releaseFocusTrap(inertElements: Iterable<HTMLElement>) {\n for (const el of inertElements) {\n el.removeAttribute(\"inert\");\n }\n}\n"],"mappings":"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","names":["import_react","_a","_b"]}
@@ -1,8 +1,8 @@
1
1
  import "../chunk-DZNH5JHY.mjs";
2
2
  import {
3
3
  AutoAnimateHeight
4
- } from "../chunk-HSIL53A5.mjs";
5
- import "../chunk-ZL56N4UK.mjs";
4
+ } from "../chunk-UXJIK76H.mjs";
5
+ import "../chunk-JXA3B33M.mjs";
6
6
  import "../chunk-R4SQKVDQ.mjs";
7
7
  export {
8
8
  AutoAnimateHeight
package/dist/utils.d.mts CHANGED
@@ -1,4 +1,6 @@
1
1
  export { useMergeRefs } from './_tsup-dts-rollup';
2
2
  export { useResize } from './_tsup-dts-rollup';
3
3
  export { useHydrated } from './_tsup-dts-rollup';
4
+ export { focusTrap } from './_tsup-dts-rollup';
5
+ export { releaseFocusTrap } from './_tsup-dts-rollup';
4
6
  export { OverridableComponent } from './_tsup-dts-rollup';
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export { useMergeRefs } from './_tsup-dts-rollup';
2
2
  export { useResize } from './_tsup-dts-rollup';
3
3
  export { useHydrated } from './_tsup-dts-rollup';
4
+ export { focusTrap } from './_tsup-dts-rollup';
5
+ export { releaseFocusTrap } from './_tsup-dts-rollup';
4
6
  export { OverridableComponent } from './_tsup-dts-rollup';
package/dist/utils.js CHANGED
@@ -30,6 +30,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/utils.ts
31
31
  var utils_exports = {};
32
32
  __export(utils_exports, {
33
+ focusTrap: () => focusTrap,
34
+ releaseFocusTrap: () => releaseFocusTrap,
33
35
  useHydrated: () => useHydrated,
34
36
  useMergeRefs: () => useMergeRefs,
35
37
  useResize: () => useResize
@@ -87,8 +89,40 @@ function useHydrated() {
87
89
  () => false
88
90
  );
89
91
  }
92
+ function focusTrap(element) {
93
+ var _a, _b;
94
+ if (element === document.body)
95
+ return () => {
96
+ };
97
+ let inertElements = [];
98
+ for (let el = element; el; el = el.parentElement) {
99
+ if (el === document.body)
100
+ break;
101
+ for (const sibling of (_b = (_a = el.parentElement) == null ? void 0 : _a.children) != null ? _b : []) {
102
+ if (sibling === el)
103
+ continue;
104
+ if (!(sibling instanceof HTMLElement))
105
+ continue;
106
+ if (sibling.hasAttribute("inert"))
107
+ continue;
108
+ sibling.setAttribute("inert", "true");
109
+ inertElements.push(sibling);
110
+ }
111
+ }
112
+ return () => {
113
+ releaseFocusTrap(inertElements);
114
+ inertElements = [];
115
+ };
116
+ }
117
+ function releaseFocusTrap(inertElements) {
118
+ for (const el of inertElements) {
119
+ el.removeAttribute("inert");
120
+ }
121
+ }
90
122
  // Annotate the CommonJS export names for ESM import in node:
91
123
  0 && (module.exports = {
124
+ focusTrap,
125
+ releaseFocusTrap,
92
126
  useHydrated,
93
127
  useMergeRefs,
94
128
  useResize
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts"],"sourcesContent":["import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,mBAAiD;AAwB1C,SAAS,aACd,MACoC;AACpC,SAAa,cAAQ,MAAM;AACzB,QAAI,KAAK,MAAM,CAAC,QAAQ,QAAQ,IAAI,GAAG;AACrC,aAAO;AAAA,IACT;AAEA,WAAO,CAAC,UAAU;AAChB,WAAK,QAAQ,CAAC,QAAQ;AACpB,YAAI,OAAO,QAAQ,YAAY;AAC7B,cAAI,KAAK;AAAA,QACX,WAAW,QAAQ,MAAM;AACvB,UAAC,IAAgD,UAAU;AAAA,QAC7D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EAEF,GAAG,IAAI;AACT;AAEO,SAAS,UACd,KACmC;AACnC,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAiB,CAAC;AAC5C,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAAiB,CAAC;AAC9C,QAAM,mBAAe,0BAAY,MAAM;AApDzC;AAqDI,SAAI,2BAAK,aAAY,MAAM;AACzB,gBAAS,sCAAK,YAAL,mBAAc,gBAAd,YAA6B,CAAC;AACvC,iBAAU,sCAAK,YAAL,mBAAc,iBAAd,YAA8B,CAAC;AAAA,IAC3C;AAAA,EACF,GAAG,CAAC,GAAG,CAAC;AACR,8BAAU,MAAM;AACd,WAAO,iBAAiB,QAAQ,YAAY;AAC5C,WAAO,iBAAiB,UAAU,YAAY;AAC9C,WAAO,MAAM;AACX,aAAO,oBAAoB,QAAQ,YAAY;AAC/C,aAAO,oBAAoB,UAAU,YAAY;AAAA,IACnD;AAAA,EACF,GAAG,CAAC,KAAK,YAAY,CAAC;AACtB,8BAAU,MAAM;AACd,iBAAa;AAAA,EAEf,GAAG,CAAC,CAAC;AACL,SAAO,EAAE,OAAO,OAAO;AACzB;AAEA,SAAS,YAAY;AAEnB,SAAO,MAAM;AAAA,EAAC;AAChB;AAEO,SAAS,cAAc;AAC5B,SAAa;AAAA,IACX;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/utils.ts"],"sourcesContent":["import type { ComponentPropsWithRef, ElementType, FC, RefAttributes } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\n/**\n * OverridableComponent makes the `as` prop available,\n * to be used to override the html element being used for a component\n *\n * Taken from digdir design system: https://github.com/digdir/designsystem/blob/main/packages/react/src/types/OverridableComponent.ts\n */\nexport type OverridableComponent<ComponentProps, Element extends HTMLElement> = {\n (props: ComponentProps & RefAttributes<Element>): ReturnType<FC>;\n\n <As extends ElementType>(\n props: {\n /** Override html element */\n as?: As;\n } & ComponentProps &\n Omit<ComponentPropsWithRef<As>, keyof ComponentProps>,\n ): ReturnType<FC>;\n} & Pick<FC, \"displayName\">;\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/useMergeRefs\n */\nexport function useMergeRefs<Instance>(\n refs: (React.Ref<Instance> | undefined)[],\n): React.RefCallback<Instance> | null {\n return React.useMemo(() => {\n if (refs.every((ref) => ref === null)) {\n return null;\n }\n\n return (value) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref !== null) {\n (ref as React.MutableRefObject<Instance | null>).current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, refs);\n}\n\nexport function useResize<Instance extends HTMLElement>(\n ref: React.RefObject<Instance> | undefined | null,\n): { width: number; height: number } {\n const [width, setWidth] = useState<number>(0);\n const [height, setHeight] = useState<number>(0);\n const handleResize = useCallback(() => {\n if (ref?.current !== null) {\n setWidth(ref?.current?.offsetWidth ?? 0);\n setHeight(ref?.current?.offsetHeight ?? 0);\n }\n }, [ref]);\n useEffect(() => {\n window.addEventListener(\"load\", handleResize);\n window.addEventListener(\"resize\", handleResize);\n return () => {\n window.removeEventListener(\"load\", handleResize);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [ref, handleResize]);\n useEffect(() => {\n handleResize();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- It's ok\n }, []);\n return { width, height };\n}\n\nfunction subscribe() {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- It's ok\n return () => {};\n}\n\nexport function useHydrated() {\n return React.useSyncExternalStore(\n subscribe,\n () => true,\n () => false,\n );\n}\n\n/**\n * Trap focus inside an element using the `inert` attribute.\n *\n * Adds `inert` to all siblings of the given element, and all their ancestors up to the body.\n * Returns a cleanup function which removes the `inert` property from the elements, effectively giving focus back to rest of the document.\n *\n * NOTE: Does not support portals, i.e. elements outside the DOM hierarchy of the given element.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert\n * @see https://web.dev/articles/inert\n */\nexport function focusTrap(element: HTMLElement) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function -- NOP on focus trapping the body element\n if (element === document.body) return () => {};\n\n let inertElements: HTMLElement[] = [];\n for (let el: HTMLElement | null = element; el; el = el.parentElement) {\n if (el === document.body) break;\n\n for (const sibling of el.parentElement?.children ?? []) {\n if (sibling === el) continue;\n if (!(sibling instanceof HTMLElement)) continue;\n if (sibling.hasAttribute(\"inert\")) continue;\n\n sibling.setAttribute(\"inert\", \"true\");\n inertElements.push(sibling);\n }\n }\n\n return () => {\n releaseFocusTrap(inertElements);\n inertElements = [];\n };\n}\n\n/**\n * Unset the `inert` attribute on all elements given\n */\nexport function releaseFocusTrap(inertElements: Iterable<HTMLElement>) {\n for (const el of inertElements) {\n el.removeAttribute(\"inert\");\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,mBAAiD;AAwB1C,SAAS,aACd,MACoC;AACpC,SAAa,cAAQ,MAAM;AACzB,QAAI,KAAK,MAAM,CAAC,QAAQ,QAAQ,IAAI,GAAG;AACrC,aAAO;AAAA,IACT;AAEA,WAAO,CAAC,UAAU;AAChB,WAAK,QAAQ,CAAC,QAAQ;AACpB,YAAI,OAAO,QAAQ,YAAY;AAC7B,cAAI,KAAK;AAAA,QACX,WAAW,QAAQ,MAAM;AACvB,UAAC,IAAgD,UAAU;AAAA,QAC7D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EAEF,GAAG,IAAI;AACT;AAEO,SAAS,UACd,KACmC;AACnC,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAiB,CAAC;AAC5C,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAAiB,CAAC;AAC9C,QAAM,mBAAe,0BAAY,MAAM;AApDzC;AAqDI,SAAI,2BAAK,aAAY,MAAM;AACzB,gBAAS,sCAAK,YAAL,mBAAc,gBAAd,YAA6B,CAAC;AACvC,iBAAU,sCAAK,YAAL,mBAAc,iBAAd,YAA8B,CAAC;AAAA,IAC3C;AAAA,EACF,GAAG,CAAC,GAAG,CAAC;AACR,8BAAU,MAAM;AACd,WAAO,iBAAiB,QAAQ,YAAY;AAC5C,WAAO,iBAAiB,UAAU,YAAY;AAC9C,WAAO,MAAM;AACX,aAAO,oBAAoB,QAAQ,YAAY;AAC/C,aAAO,oBAAoB,UAAU,YAAY;AAAA,IACnD;AAAA,EACF,GAAG,CAAC,KAAK,YAAY,CAAC;AACtB,8BAAU,MAAM;AACd,iBAAa;AAAA,EAEf,GAAG,CAAC,CAAC;AACL,SAAO,EAAE,OAAO,OAAO;AACzB;AAEA,SAAS,YAAY;AAEnB,SAAO,MAAM;AAAA,EAAC;AAChB;AAEO,SAAS,cAAc;AAC5B,SAAa;AAAA,IACX;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAaO,SAAS,UAAU,SAAsB;AAjGhD;AAmGE,MAAI,YAAY,SAAS;AAAM,WAAO,MAAM;AAAA,IAAC;AAE7C,MAAI,gBAA+B,CAAC;AACpC,WAAS,KAAyB,SAAS,IAAI,KAAK,GAAG,eAAe;AACpE,QAAI,OAAO,SAAS;AAAM;AAE1B,eAAW,YAAW,cAAG,kBAAH,mBAAkB,aAAlB,YAA8B,CAAC,GAAG;AACtD,UAAI,YAAY;AAAI;AACpB,UAAI,EAAE,mBAAmB;AAAc;AACvC,UAAI,QAAQ,aAAa,OAAO;AAAG;AAEnC,cAAQ,aAAa,SAAS,MAAM;AACpC,oBAAc,KAAK,OAAO;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO,MAAM;AACX,qBAAiB,aAAa;AAC9B,oBAAgB,CAAC;AAAA,EACnB;AACF;AAKO,SAAS,iBAAiB,eAAsC;AACrE,aAAW,MAAM,eAAe;AAC9B,OAAG,gBAAgB,OAAO;AAAA,EAC5B;AACF;","names":[]}