@fremtind/jokul 5.0.0-next.9 → 5.0.0

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 (238) hide show
  1. package/build/build-stats.html +1 -1
  2. package/build/cjs/components/autosuggest/BaseAutosuggest.cjs +1 -1
  3. package/build/cjs/components/autosuggest/BaseAutosuggest.cjs.map +1 -1
  4. package/build/cjs/components/expander/Accordion.cjs +2 -0
  5. package/build/cjs/components/expander/Accordion.cjs.map +1 -0
  6. package/build/cjs/components/expander/Accordion.d.cts +2 -0
  7. package/build/cjs/components/expander/ExpandablePanel.cjs +1 -1
  8. package/build/cjs/components/expander/ExpandablePanel.cjs.map +1 -1
  9. package/build/cjs/components/expander/ExpandablePanelContent.cjs +1 -1
  10. package/build/cjs/components/expander/ExpandablePanelContent.cjs.map +1 -1
  11. package/build/cjs/components/expander/Expander.cjs +1 -1
  12. package/build/cjs/components/expander/Expander.cjs.map +1 -1
  13. package/build/cjs/components/expander/index.d.cts +1 -1
  14. package/build/cjs/components/expander/types.d.cts +5 -2
  15. package/build/cjs/components/icon/Icon.cjs +1 -1
  16. package/build/cjs/components/icon/Icon.cjs.map +1 -1
  17. package/build/cjs/components/icon/Icon.d.cts +2 -2
  18. package/build/cjs/components/icon/icons/GreenCheckIcon.cjs +1 -1
  19. package/build/cjs/components/icon/icons/GreenCheckIcon.cjs.map +1 -1
  20. package/build/cjs/components/icon/icons/GreenCheckIcon.d.cts +2 -3
  21. package/build/cjs/components/icon/icons/RedCrossIcon.cjs +1 -1
  22. package/build/cjs/components/icon/icons/RedCrossIcon.cjs.map +1 -1
  23. package/build/cjs/components/icon/icons/RedCrossIcon.d.cts +2 -3
  24. package/build/cjs/components/link-list/LinkList.cjs +1 -1
  25. package/build/cjs/components/link-list/LinkList.cjs.map +1 -1
  26. package/build/cjs/components/link-list/LinkList.d.cts +1 -1
  27. package/build/cjs/components/link-list/types.d.cts +1 -0
  28. package/build/cjs/components/number-input/NumberInput.cjs +2 -0
  29. package/build/cjs/components/number-input/NumberInput.cjs.map +1 -0
  30. package/build/cjs/components/number-input/NumberInput.d.cts +7 -0
  31. package/build/cjs/components/number-input/index.cjs +2 -0
  32. package/build/cjs/components/number-input/index.cjs.map +1 -0
  33. package/build/cjs/components/number-input/index.d.cts +2 -0
  34. package/build/cjs/components/number-input/types.cjs +2 -0
  35. package/build/cjs/components/number-input/types.cjs.map +1 -0
  36. package/build/cjs/components/number-input/types.d.cts +20 -0
  37. package/build/cjs/components/popover/Popover.cjs +1 -1
  38. package/build/cjs/components/popover/Popover.cjs.map +1 -1
  39. package/build/cjs/components/popover/types.d.cts +8 -1
  40. package/build/cjs/components/select/Select.cjs +1 -1
  41. package/build/cjs/components/select/Select.cjs.map +1 -1
  42. package/build/cjs/components/system-message/types.d.cts +7 -2
  43. package/build/cjs/hooks/useListNavigation/useListNavigation.cjs +1 -1
  44. package/build/cjs/hooks/useListNavigation/useListNavigation.cjs.map +1 -1
  45. package/build/cjs/hooks/useListNavigation/useListNavigation.d.cts +11 -2
  46. package/build/cjs/tokens.cjs +1 -1
  47. package/build/cjs/tokens.cjs.map +1 -1
  48. package/build/cjs/utilities/index.cjs +1 -1
  49. package/build/cjs/utilities/types.cjs +1 -1
  50. package/build/cjs/utilities/types.cjs.map +1 -1
  51. package/build/cjs/utilities/types.d.cts +2 -0
  52. package/build/es/components/autosuggest/BaseAutosuggest.js +1 -1
  53. package/build/es/components/autosuggest/BaseAutosuggest.js.map +1 -1
  54. package/build/es/components/datepicker/DatePicker.js +1 -1
  55. package/build/es/components/datepicker/internal/Calendar.js +1 -1
  56. package/build/es/components/datepicker/internal/useCalendar.js +1 -1
  57. package/build/es/components/datepicker/internal/utils.js +1 -1
  58. package/build/es/components/expander/Accordion.d.ts +2 -0
  59. package/build/es/components/expander/Accordion.js +2 -0
  60. package/build/es/components/expander/Accordion.js.map +1 -0
  61. package/build/es/components/expander/ExpandablePanel.js +1 -1
  62. package/build/es/components/expander/ExpandablePanel.js.map +1 -1
  63. package/build/es/components/expander/ExpandablePanelContent.js +1 -1
  64. package/build/es/components/expander/ExpandablePanelContent.js.map +1 -1
  65. package/build/es/components/expander/Expander.js +1 -1
  66. package/build/es/components/expander/Expander.js.map +1 -1
  67. package/build/es/components/expander/index.d.ts +1 -1
  68. package/build/es/components/expander/types.d.ts +5 -2
  69. package/build/es/components/icon/Icon.d.ts +2 -2
  70. package/build/es/components/icon/Icon.js +1 -1
  71. package/build/es/components/icon/Icon.js.map +1 -1
  72. package/build/es/components/icon/icons/GreenCheckIcon.d.ts +2 -3
  73. package/build/es/components/icon/icons/GreenCheckIcon.js +1 -1
  74. package/build/es/components/icon/icons/GreenCheckIcon.js.map +1 -1
  75. package/build/es/components/icon/icons/RedCrossIcon.d.ts +2 -3
  76. package/build/es/components/icon/icons/RedCrossIcon.js +1 -1
  77. package/build/es/components/icon/icons/RedCrossIcon.js.map +1 -1
  78. package/build/es/components/link-list/LinkList.d.ts +1 -1
  79. package/build/es/components/link-list/LinkList.js +1 -1
  80. package/build/es/components/link-list/LinkList.js.map +1 -1
  81. package/build/es/components/link-list/types.d.ts +1 -0
  82. package/build/es/components/menu/Menu.js +1 -1
  83. package/build/es/components/number-input/NumberInput.d.ts +7 -0
  84. package/build/es/components/number-input/NumberInput.js +2 -0
  85. package/build/es/components/number-input/NumberInput.js.map +1 -0
  86. package/build/es/components/number-input/index.d.ts +2 -0
  87. package/build/es/components/number-input/index.js +2 -0
  88. package/build/es/components/number-input/index.js.map +1 -0
  89. package/build/es/components/number-input/types.d.ts +20 -0
  90. package/build/es/components/number-input/types.js +2 -0
  91. package/build/es/components/number-input/types.js.map +1 -0
  92. package/build/es/components/popover/Popover.js +1 -1
  93. package/build/es/components/popover/Popover.js.map +1 -1
  94. package/build/es/components/popover/types.d.ts +8 -1
  95. package/build/es/components/select/Select.js +1 -1
  96. package/build/es/components/select/Select.js.map +1 -1
  97. package/build/es/components/system-message/types.d.ts +7 -2
  98. package/build/es/components/toast/toastContext.js +1 -1
  99. package/build/es/components/tooltip/Tooltip.js +1 -1
  100. package/build/es/hooks/stories/content.js +1 -1
  101. package/build/es/hooks/useListNavigation/useListNavigation.d.ts +11 -2
  102. package/build/es/hooks/useListNavigation/useListNavigation.js +1 -1
  103. package/build/es/hooks/useListNavigation/useListNavigation.js.map +1 -1
  104. package/build/es/tokens.js +1 -1
  105. package/build/es/tokens.js.map +1 -1
  106. package/build/es/utilities/constants/index.js +1 -1
  107. package/build/es/utilities/constants/unicode.js +1 -1
  108. package/build/es/utilities/formatters/bytes/formatBytes.js +1 -1
  109. package/build/es/utilities/formatters/fodselsnummer/formatFodselsnummer.js +1 -1
  110. package/build/es/utilities/formatters/kontonummer/formatKontonummer.js +1 -1
  111. package/build/es/utilities/formatters/kortnummer/formatKortnummer.js +1 -1
  112. package/build/es/utilities/formatters/organisasjonsnummer/formatOrganisasjonsnummer.js +1 -1
  113. package/build/es/utilities/formatters/telefonnummer/formatTelefonnummer.js +1 -1
  114. package/build/es/utilities/formatters/valuta/formatValuta.js +1 -1
  115. package/build/es/utilities/index.js +1 -1
  116. package/build/es/utilities/types.d.ts +2 -0
  117. package/build/es/utilities/types.js +1 -1
  118. package/build/es/utilities/types.js.map +1 -1
  119. package/build/{index-CWRMnfcx.js → index-C1iqmqvT.js} +2 -2
  120. package/build/{index-CWRMnfcx.js.map → index-C1iqmqvT.js.map} +1 -1
  121. package/build/{utils-CcE6HjQp.js → utils-CtwpNW4I.js} +2 -2
  122. package/build/{utils-CcE6HjQp.js.map → utils-CtwpNW4I.js.map} +1 -1
  123. package/codemods/CODEMODS.md +133 -0
  124. package/codemods/__tests__/import-paths.test.mjs +568 -94
  125. package/codemods/import-paths.mjs +34 -339
  126. package/codemods/transforms/color-tokens.mjs +102 -0
  127. package/codemods/transforms/expandable-panel.mjs +41 -0
  128. package/codemods/transforms/font-family.mjs +23 -0
  129. package/codemods/transforms/import-specifiers.mjs +226 -0
  130. package/codemods/transforms/warnings.mjs +41 -0
  131. package/codemods/utils.mjs +35 -0
  132. package/package.json +8 -4
  133. package/styles/base.css +180 -805
  134. package/styles/base.min.css +1 -1
  135. package/styles/components/autosuggest/autosuggest.css +4 -3
  136. package/styles/components/autosuggest/autosuggest.min.css +1 -1
  137. package/styles/components/autosuggest/autosuggest.scss +4 -3
  138. package/styles/components/button/button.css +9 -3
  139. package/styles/components/button/button.min.css +1 -1
  140. package/styles/components/button/button.scss +10 -3
  141. package/styles/components/checkbox/checkbox.css +1 -1
  142. package/styles/components/checkbox/checkbox.min.css +1 -1
  143. package/styles/components/checkbox/checkbox.scss +1 -1
  144. package/styles/components/checkbox-panel/checkbox-panel.css +1 -1
  145. package/styles/components/checkbox-panel/checkbox-panel.min.css +1 -1
  146. package/styles/components/combobox/combobox.css +4 -4
  147. package/styles/components/combobox/combobox.min.css +1 -1
  148. package/styles/components/combobox/combobox.scss +4 -4
  149. package/styles/components/countdown/countdown.css +2 -2
  150. package/styles/components/countdown/countdown.min.css +1 -1
  151. package/styles/components/expander/_index.scss +1 -0
  152. package/styles/components/expander/accordion.css +21 -0
  153. package/styles/components/expander/accordion.min.css +1 -0
  154. package/styles/components/expander/accordion.scss +24 -0
  155. package/styles/components/expander/expandable.css +32 -37
  156. package/styles/components/expander/expandable.min.css +1 -1
  157. package/styles/components/expander/expandable.scss +27 -36
  158. package/styles/components/feedback/feedback.css +2 -2
  159. package/styles/components/feedback/feedback.min.css +1 -1
  160. package/styles/components/feedback/feedback.scss +0 -1
  161. package/styles/components/file/file.css +1 -1
  162. package/styles/components/file/file.min.css +1 -1
  163. package/styles/components/file/file.scss +1 -1
  164. package/styles/components/file-input/file-input.css +19 -13
  165. package/styles/components/file-input/file-input.min.css +1 -1
  166. package/styles/components/icon/icon.scss +1 -1
  167. package/styles/components/input-group/input-group.css +2 -2
  168. package/styles/components/input-group/input-group.min.css +1 -1
  169. package/styles/components/link-list/link-list.css +7 -2
  170. package/styles/components/link-list/link-list.min.css +1 -1
  171. package/styles/components/link-list/link-list.scss +10 -3
  172. package/styles/components/list/list.css +33 -21
  173. package/styles/components/list/list.min.css +1 -1
  174. package/styles/components/list/list.scss +24 -24
  175. package/styles/components/loader/loader.css +6 -6
  176. package/styles/components/loader/loader.min.css +1 -1
  177. package/styles/components/loader/skeleton-loader.css +3 -3
  178. package/styles/components/loader/skeleton-loader.min.css +1 -1
  179. package/styles/components/menu/_menu-item.scss +1 -1
  180. package/styles/components/menu/menu.css +1 -1
  181. package/styles/components/menu/menu.min.css +1 -1
  182. package/styles/components/message/message.css +9 -9
  183. package/styles/components/message/message.min.css +1 -1
  184. package/styles/components/message/message.scss +7 -7
  185. package/styles/components/modal/_index.scss +7 -0
  186. package/styles/components/modal/_overlay.scss +4 -0
  187. package/styles/components/modal/modal.css +32 -116
  188. package/styles/components/modal/modal.min.css +1 -1
  189. package/styles/components/modal/modal.scss +96 -6
  190. package/styles/components/number-input/_index.scss +2 -0
  191. package/styles/components/number-input/number-input.css +214 -0
  192. package/styles/components/number-input/number-input.min.css +1 -0
  193. package/styles/components/number-input/number-input.scss +115 -0
  194. package/styles/components/progress-bar/progress-bar.css +1 -1
  195. package/styles/components/progress-bar/progress-bar.min.css +1 -1
  196. package/styles/components/radio-button/radio-button.css +1 -5
  197. package/styles/components/radio-button/radio-button.min.css +1 -1
  198. package/styles/components/radio-button/radio-button.scss +2 -7
  199. package/styles/components/segmented-control/segmented-control.css +3 -7
  200. package/styles/components/segmented-control/segmented-control.min.css +1 -1
  201. package/styles/components/select/select.css +65 -7
  202. package/styles/components/select/select.min.css +1 -1
  203. package/styles/components/select/select.scss +129 -18
  204. package/styles/components/system-message/system-message.css +9 -13
  205. package/styles/components/system-message/system-message.min.css +1 -1
  206. package/styles/components/system-message/system-message.scss +116 -123
  207. package/styles/components/tag/tag.css +4 -4
  208. package/styles/components/tag/tag.min.css +1 -1
  209. package/styles/components/tag/tag.scss +4 -4
  210. package/styles/components/toast/toast.css +4 -4
  211. package/styles/components/toast/toast.min.css +1 -1
  212. package/styles/components/typography/text.scss +2 -2
  213. package/styles/components/typography/title.scss +1 -1
  214. package/styles/components.css +524 -130
  215. package/styles/components.min.css +1 -1
  216. package/styles/components.scss +2 -1
  217. package/styles/jkl/_convert.scss +15 -6
  218. package/styles/jkl/_tokens.scss +4 -4
  219. package/styles/tailwind.css +97 -97
  220. package/styles/theme/_color-scheme.scss +95 -95
  221. package/styles/theme/_dynamic-spacing.scss +21 -15
  222. package/styles/theme/_fonts.scss +3 -12
  223. package/styles/theme/_index.scss +0 -4
  224. package/styles/theme/_size.scss +20 -20
  225. package/styles/theme/_tokens.scss +11 -11
  226. package/styles/core/utility/_paragraphs.scss +0 -39
  227. package/styles/theme/brands/dnb/_color-scheme.scss +0 -121
  228. package/styles/theme/brands/dnb/_fonts.scss +0 -46
  229. package/styles/theme/brands/dnb/_index.scss +0 -2
  230. package/styles/theme/brands/eika/_color-scheme.scss +0 -121
  231. package/styles/theme/brands/eika/_fonts.scss +0 -46
  232. package/styles/theme/brands/eika/_index.scss +0 -2
  233. package/styles/theme/brands/fremtind/_color-scheme.scss +0 -121
  234. package/styles/theme/brands/fremtind/_fonts.scss +0 -30
  235. package/styles/theme/brands/fremtind/_index.scss +0 -2
  236. package/styles/theme/brands/sparebank1/_color-scheme.scss +0 -121
  237. package/styles/theme/brands/sparebank1/_fonts.scss +0 -38
  238. package/styles/theme/brands/sparebank1/_index.scss +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"Popover.js","sources":["../../../../src/components/popover/Popover.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n FloatingPortal,\n type ReferenceElement,\n type VirtualElement,\n autoUpdate,\n flip,\n offset,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFocus,\n useHover,\n useInteractions,\n useMergeRefs,\n useRole,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport * as React from \"react\";\nimport { getThemeAndSize } from \"../../utilities/getThemeAndSize.js\";\nimport type { PopoverOptions } from \"./types.js\";\n\nconst usePopover = ({\n open: _open,\n onOpenChange: _onOpenChange,\n placement = \"bottom-start\",\n strategy = \"absolute\",\n modal = true,\n offset: _offset = 4,\n positionReference,\n hoverOptions,\n focusOptions,\n clickOptions,\n roleOptions,\n dismissOptions,\n}: PopoverOptions) => {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(_open);\n\n const open = _open ?? uncontrolledOpen;\n const onOpenChange = _onOpenChange ?? setUncontrolledOpen;\n\n const data = useFloating({\n open,\n onOpenChange,\n placement,\n strategy,\n middleware: [\n offset(_offset),\n flip({ padding: 5, fallbackPlacements: [\"bottom\", \"top\"] }),\n shift({ padding: 12 }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const context = data.context;\n\n const click = useClick(context, {\n enabled: false,\n ...clickOptions,\n });\n const hover = useHover(context, { enabled: false, ...hoverOptions });\n const focus = useFocus(context, { enabled: false, ...focusOptions });\n const dismiss = useDismiss(context, dismissOptions);\n const role = useRole(context, roleOptions);\n\n const interactions = useInteractions([click, dismiss, focus, hover, role]);\n\n React.useLayoutEffect(() => {\n if (positionReference) {\n data.refs.setPositionReference(positionReference?.current);\n }\n }, [positionReference, data.refs]);\n\n return React.useMemo(\n () => ({\n open,\n onOpenChange,\n modal,\n ...interactions,\n ...data,\n }),\n [open, onOpenChange, modal, interactions, data],\n );\n};\n\ntype PopoverContextType = ReturnType<typeof usePopover> | null;\n\nconst PopoverContext = React.createContext<PopoverContextType>(null);\n\nconst usePopoverContext = () => {\n const context = React.useContext(PopoverContext);\n\n if (context == null) {\n throw new Error(\n \"Popover komponenter må brukes innenfor en <Popover /> komponent\",\n );\n }\n\n return context;\n};\n\nexport const Popover = ({\n children,\n ...restOptions\n}: {\n children: React.ReactNode;\n} & PopoverOptions) => {\n const popover = usePopover({ ...restOptions });\n return (\n <PopoverContext.Provider value={popover}>\n {children}\n </PopoverContext.Provider>\n );\n};\n\ninterface PopoverTriggerProps {\n children: React.ReactNode;\n /**\n * Rendrer komponenten som child-elementet sitt, og slår sammen egenskaper og props.\n *\n * Default er `false`.\n *\n * @example\n * ```tsx\n * <Component asChild foo=\"bar\">\n * <Child baz=\"qux\" />\n * </Component>\n *\n * // Rendrer følgende:\n * <Child foo=\"bar\" baz=\"qux\" />\n * ```\n */\n asChild?: boolean;\n}\n\nconst PopoverTrigger = React.forwardRef<\n HTMLElement,\n React.HTMLProps<HTMLElement> & PopoverTriggerProps\n>(function PopoverTrigger({ children, asChild = false, ...props }, propRef) {\n const { refs, getReferenceProps, open, onOpenChange } = usePopoverContext();\n const childrenRef = (children as any).ref;\n const ref = useMergeRefs([refs.setReference, propRef, childrenRef]);\n\n if (asChild && React.isValidElement(children)) {\n return React.cloneElement(\n children,\n getReferenceProps({\n ref,\n ...props,\n ...children.props,\n }),\n );\n }\n\n return (\n <button\n ref={ref}\n onClick={() => onOpenChange?.(!open)}\n aria-expanded={open}\n {...getReferenceProps({\n ...props,\n className: clsx(\"jkl-popover-trigger\", props.className),\n })}\n >\n {children}\n </button>\n );\n});\n\ninterface PopoverContentProps {\n /**\n * Padding rundt innholdet i popoveren.\n *\n * Default er `0`.\n */\n padding?: 0 | 8 | 16 | 24;\n /**\n *\n * Angir hvilket element som skal motta fokus ved åpning.\n * Kan være en tabbar index eller en referanse til et element.\"\n *\n * Default er `0`, som betyr at det første fokuserbare elementet i popoveren får fokus.\n * @see https://floating-ui.com/docs/FloatingFocusManager#initialfocus\n */\n initialFocus?: number | React.RefObject<HTMLElement>;\n /**\n * Angir om fokus skal returneres til triggeren når popoveren lukkes.\n *\n * Default er `true`.\n * @see https://floating-ui.com/docs/FloatingFocusManager#returnfocus\n */\n returnFocus?: boolean;\n}\n\n// Er popover-elementet posisjonert i forhold til et annet element enn triggeren?\nconst isCustomPositioned = (\n referenceElement: ReferenceElement,\n): referenceElement is VirtualElement => {\n if (!referenceElement) return false;\n\n return \"contextElement\" in referenceElement;\n};\n\nconst PopoverContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLProps<HTMLDivElement> & PopoverContentProps\n>(function PopoverContent(\n {\n style,\n className,\n padding = 0,\n initialFocus = 0,\n returnFocus = true,\n ...props\n },\n propRef,\n) {\n const { context, modal, refs, open, floatingStyles, getFloatingProps } =\n usePopoverContext();\n const ref = useMergeRefs([refs.setFloating, propRef]);\n\n const referenceElement = refs.reference.current as ReferenceElement;\n\n const { theme, size } = isCustomPositioned(referenceElement)\n ? getThemeAndSize(referenceElement.contextElement)\n : getThemeAndSize(referenceElement);\n\n const floatingPortalRef = React.useRef<HTMLElement | null>(null);\n\n // TODO: Løser et problem hvor nestede portaler ikke \"fester\" seg til det nærmeste portal-elementet. Fjernes når alle komponenter som rendres i en portal tar i bruk popover komponenten da den håndterer dette internt. Issue: https://github.com/fremtind/jokul/issues/4356\n React.useEffect(() => {\n floatingPortalRef.current =\n context.elements.domReference?.closest<HTMLElement>(\n \"[data-portal]\",\n ) || document.body;\n }, [context.elements.domReference]);\n\n if (!open) return null;\n\n return (\n <FloatingPortal root={floatingPortalRef.current}>\n <FloatingFocusManager\n context={context}\n modal={modal}\n initialFocus={initialFocus}\n returnFocus={returnFocus}\n >\n <div\n data-theme={theme}\n data-size={size}\n className={clsx(\"jkl jkl-popover\", className)}\n ref={ref}\n style={\n {\n ...style,\n ...floatingStyles,\n \"--popover-padding\": `var(--jkl-spacing-${padding})`,\n } as React.CSSProperties\n }\n {...getFloatingProps(props)}\n >\n {props.children}\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n );\n});\n\nPopover.Trigger = PopoverTrigger;\nPopover.Content = PopoverContent;\n\nexport default Popover;\n"],"names":["PopoverContext","React","createContext","usePopoverContext","context","useContext","Error","Popover","children","restOptions","popover","open","_open","onOpenChange","_onOpenChange","placement","strategy","modal","offset","_offset","positionReference","hoverOptions","focusOptions","clickOptions","roleOptions","dismissOptions","uncontrolledOpen","setUncontrolledOpen","useState","data","useFloating","middleware","flip","padding","fallbackPlacements","shift","whileElementsMounted","autoUpdate","click","useClick","enabled","hover","useHover","focus","useFocus","dismiss","useDismiss","role","useRole","interactions","useInteractions","useLayoutEffect","refs","setPositionReference","current","useMemo","usePopover","Provider","value","PopoverTrigger","forwardRef","asChild","props","propRef","getReferenceProps","childrenRef","ref","useMergeRefs","setReference","isValidElement","cloneElement","jsx","onClick","className","clsx","PopoverContent","style","initialFocus","returnFocus","floatingStyles","getFloatingProps","setFloating","referenceElement","reference","theme","size","getThemeAndSize","contextElement","floatingPortalRef","useRef","useEffect","elements","domReference","closest","document","body","FloatingPortal","root","FloatingFocusManager","Trigger","Content"],"mappings":"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"}
1
+ {"version":3,"file":"Popover.js","sources":["../../../../src/components/popover/Popover.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n FloatingPortal,\n type ReferenceElement,\n type VirtualElement,\n autoUpdate,\n flip,\n offset,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFocus,\n useHover,\n useInteractions,\n useMergeRefs,\n useRole,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport * as React from \"react\";\nimport { getThemeAndSize } from \"../../utilities/getThemeAndSize.js\";\nimport type { PopoverOptions } from \"./types.js\";\n\nconst usePopover = ({\n open: _open,\n onOpenChange: _onOpenChange,\n placement = \"bottom-start\",\n strategy = \"absolute\",\n modal = true,\n offset: _offset = 4,\n positionReference,\n onPlacementChange,\n hoverOptions,\n focusOptions,\n clickOptions,\n roleOptions,\n dismissOptions,\n}: PopoverOptions) => {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(_open);\n\n const open = _open ?? uncontrolledOpen;\n const onOpenChange = _onOpenChange ?? setUncontrolledOpen;\n\n const data = useFloating({\n open,\n onOpenChange,\n placement,\n strategy,\n middleware: [\n offset(_offset),\n flip({ padding: 5, fallbackPlacements: [\"bottom\", \"top\"] }),\n shift({ padding: 12 }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const context = data.context;\n\n const click = useClick(context, {\n enabled: false,\n ...clickOptions,\n });\n const hover = useHover(context, { enabled: false, ...hoverOptions });\n const focus = useFocus(context, { enabled: false, ...focusOptions });\n const dismiss = useDismiss(context, dismissOptions);\n const role = useRole(context, roleOptions);\n\n const interactions = useInteractions([click, dismiss, focus, hover, role]);\n\n React.useLayoutEffect(() => {\n if (positionReference) {\n data.refs.setPositionReference(positionReference?.current);\n }\n }, [positionReference, data.refs]);\n\n // useLayoutEffect (i stedet for useEffect) sikrer at konsumenter får\n // riktig placement før paint — ellers ville første frame bruke default\n // placement og deretter snappe over til den faktiske, noe som gir et\n // synlig \"glitch\" på styling som er placement-avhengig (f.eks. flat side\n // / border-radius på Select-listboxen ved flip).\n React.useLayoutEffect(() => {\n if (!open) return;\n onPlacementChange?.(data.placement);\n }, [open, data.placement, onPlacementChange]);\n\n return React.useMemo(\n () => ({\n open,\n onOpenChange,\n modal,\n ...interactions,\n ...data,\n }),\n [open, onOpenChange, modal, interactions, data],\n );\n};\n\ntype PopoverContextType = ReturnType<typeof usePopover> | null;\n\nconst PopoverContext = React.createContext<PopoverContextType>(null);\n\nconst usePopoverContext = () => {\n const context = React.useContext(PopoverContext);\n\n if (context == null) {\n throw new Error(\n \"Popover komponenter må brukes innenfor en <Popover /> komponent\",\n );\n }\n\n return context;\n};\n\nexport const Popover = ({\n children,\n ...restOptions\n}: {\n children: React.ReactNode;\n} & PopoverOptions) => {\n const popover = usePopover({ ...restOptions });\n return (\n <PopoverContext.Provider value={popover}>\n {children}\n </PopoverContext.Provider>\n );\n};\n\ninterface PopoverTriggerProps {\n children: React.ReactNode;\n /**\n * Rendrer komponenten som child-elementet sitt, og slår sammen egenskaper og props.\n *\n * Default er `false`.\n *\n * @example\n * ```tsx\n * <Component asChild foo=\"bar\">\n * <Child baz=\"qux\" />\n * </Component>\n *\n * // Rendrer følgende:\n * <Child foo=\"bar\" baz=\"qux\" />\n * ```\n */\n asChild?: boolean;\n}\n\nconst PopoverTrigger = React.forwardRef<\n HTMLElement,\n React.HTMLProps<HTMLElement> & PopoverTriggerProps\n>(function PopoverTrigger({ children, asChild = false, ...props }, propRef) {\n const { refs, getReferenceProps, open, onOpenChange } = usePopoverContext();\n const childrenRef = (children as any).ref;\n const ref = useMergeRefs([refs.setReference, propRef, childrenRef]);\n\n if (asChild && React.isValidElement(children)) {\n return React.cloneElement(\n children,\n getReferenceProps({\n ref,\n ...props,\n ...children.props,\n }),\n );\n }\n\n return (\n <button\n ref={ref}\n onClick={() => onOpenChange?.(!open)}\n aria-expanded={open}\n {...getReferenceProps({\n ...props,\n className: clsx(\"jkl-popover-trigger\", props.className),\n })}\n >\n {children}\n </button>\n );\n});\n\ninterface PopoverContentProps {\n /**\n * Padding rundt innholdet i popoveren.\n *\n * Default er `0`.\n */\n padding?: 0 | 8 | 16 | 24;\n /**\n *\n * Angir hvilket element som skal motta fokus ved åpning.\n * Kan være en tabbar index eller en referanse til et element.\"\n *\n * Default er `0`, som betyr at det første fokuserbare elementet i popoveren får fokus.\n * @see https://floating-ui.com/docs/FloatingFocusManager#initialfocus\n */\n initialFocus?: number | React.RefObject<HTMLElement>;\n /**\n * Angir om fokus skal returneres til triggeren når popoveren lukkes.\n *\n * Default er `true`.\n * @see https://floating-ui.com/docs/FloatingFocusManager#returnfocus\n */\n returnFocus?: boolean;\n}\n\n// Er popover-elementet posisjonert i forhold til et annet element enn triggeren?\nconst isCustomPositioned = (\n referenceElement: ReferenceElement,\n): referenceElement is VirtualElement => {\n if (!referenceElement) return false;\n\n return \"contextElement\" in referenceElement;\n};\n\nconst PopoverContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLProps<HTMLDivElement> & PopoverContentProps\n>(function PopoverContent(\n {\n style,\n className,\n padding = 0,\n initialFocus = 0,\n returnFocus = true,\n ...props\n },\n propRef,\n) {\n const {\n context,\n modal,\n refs,\n open,\n floatingStyles,\n getFloatingProps,\n isPositioned,\n } = usePopoverContext();\n const ref = useMergeRefs([refs.setFloating, propRef]);\n\n const referenceElement = refs.reference.current as ReferenceElement;\n\n const { theme, size } = isCustomPositioned(referenceElement)\n ? getThemeAndSize(referenceElement.contextElement)\n : getThemeAndSize(referenceElement);\n\n const floatingPortalRef = React.useRef<HTMLElement | null>(null);\n\n // TODO: Løser et problem hvor nestede portaler ikke \"fester\" seg til det nærmeste portal-elementet. Fjernes når alle komponenter som rendres i en portal tar i bruk popover komponenten da den håndterer dette internt. Issue: https://github.com/fremtind/jokul/issues/4356\n React.useEffect(() => {\n floatingPortalRef.current =\n context.elements.domReference?.closest<HTMLElement>(\n \"[data-portal]\",\n ) || document.body;\n }, [context.elements.domReference]);\n\n if (!open) return null;\n\n return (\n <FloatingPortal root={floatingPortalRef.current}>\n <FloatingFocusManager\n context={context}\n modal={modal}\n initialFocus={initialFocus}\n returnFocus={returnFocus}\n >\n <div\n data-theme={theme}\n data-size={size}\n className={clsx(\"jkl jkl-popover\", className)}\n ref={ref}\n style={\n {\n ...style,\n ...floatingStyles,\n \"--popover-padding\": `var(--jkl-spacing-${padding})`,\n // Skjul popoveren inntil floating-ui har regnet\n // ut første posisjon — ellers blinker den\n // kort i (0,0) før den hopper på plass.\n // Bare for ikke-modale popovere; modale bruker\n // umiddelbar fokus-trap som forutsetter at\n // innholdet er fokuserbart fra første render.\n visibility:\n modal || isPositioned ? \"visible\" : \"hidden\",\n } as React.CSSProperties\n }\n {...getFloatingProps(props)}\n >\n {props.children}\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n );\n});\n\nPopover.Trigger = PopoverTrigger;\nPopover.Content = PopoverContent;\n\nexport default Popover;\n"],"names":["PopoverContext","React","createContext","usePopoverContext","context","useContext","Error","Popover","children","restOptions","popover","open","_open","onOpenChange","_onOpenChange","placement","strategy","modal","offset","_offset","positionReference","onPlacementChange","hoverOptions","focusOptions","clickOptions","roleOptions","dismissOptions","uncontrolledOpen","setUncontrolledOpen","useState","data","useFloating","middleware","flip","padding","fallbackPlacements","shift","whileElementsMounted","autoUpdate","click","useClick","enabled","hover","useHover","focus","useFocus","dismiss","useDismiss","role","useRole","interactions","useInteractions","useLayoutEffect","refs","setPositionReference","current","useMemo","usePopover","Provider","value","PopoverTrigger","forwardRef","asChild","props","propRef","getReferenceProps","childrenRef","ref","useMergeRefs","setReference","isValidElement","cloneElement","jsx","onClick","className","clsx","PopoverContent","style","initialFocus","returnFocus","floatingStyles","getFloatingProps","isPositioned","setFloating","referenceElement","reference","theme","size","getThemeAndSize","contextElement","floatingPortalRef","useRef","useEffect","elements","domReference","closest","document","body","FloatingPortal","root","FloatingFocusManager","visibility","Trigger","Content"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { ReferenceType, UseFloatingOptions, useClick, useDismiss, useFocus, useHover, useRole } from '@floating-ui/react';
1
+ import { Placement, ReferenceType, UseFloatingOptions, useClick, useDismiss, useFocus, useHover, useRole } from '@floating-ui/react';
2
2
  export type ClickOptions = Parameters<typeof useClick>[1];
3
3
  export type DismissOptions = Parameters<typeof useDismiss>[1];
4
4
  export type FocusOptions = Parameters<typeof useFocus>[1];
@@ -58,6 +58,13 @@ export interface PopoverOptions {
58
58
  * @default Popover.Trigger
59
59
  */
60
60
  positionReference?: React.RefObject<ReferenceType>;
61
+ /**
62
+ * Trigges når popoverens faktiske plassering endrer seg, f.eks. når
63
+ * `flip`-middlewaren snur popoveren over triggeren fordi det ikke er
64
+ * plass under. Kan brukes til å justere styling avhengig av om
65
+ * popoveren ligger over eller under referansen.
66
+ */
67
+ onPlacementChange?: (placement: Placement) => void;
61
68
  /**
62
69
  * Options for hover-interaksjoner.
63
70
  *
@@ -1,2 +1,2 @@
1
- import{jsxs as e,Fragment as t,jsx as n}from"react/jsx-runtime";import{c as r}from"../../../clsx-BeLtu-UY.js";import o,{forwardRef as a,useState as s,useCallback as l,useMemo as i,useRef as u,useEffect as c}from"react";import{useAnimatedHeight as p}from"../../hooks/useAnimatedHeight/useAnimatedHeight.js";import{useId as d}from"../../hooks/useId/useId.js";import{useListNavigation as v}from"../../hooks/useListNavigation/useListNavigation.js";import{usePreviousValue as f}from"../../hooks/usePreviousValue/usePreviousValue.js";import{getValuePair as m}from"../../utilities/valuePair.js";import{ArrowVerticalAnimated as b}from"../icon/icons/animated/ArrowVerticalAnimated.js";import{InputGroup as g}from"../input-group/InputGroup.js";import{focusSelected as h,toLower as k}from"./select-utils.js";const y=()=>{},j=a((a,j)=>{const{id:w,name:_,items:P,value:D,label:E,labelProps:L,onChange:$,onBlur:x,onFocus:N,className:A,helpLabel:V,errorLabel:C,invalid:F,searchable:S=!1,inline:T=!1,defaultPrompt:I="Velg",width:K,maxShownOptions:B=5,style:H,tooltip:M,...O}=a,G=d(w||"jkl-select",{generateSuffix:!w}),R=`${G}_label`,q=`${G}_button`,U=`${G}_search-input`,[z,J]=s(!1),Q=l(()=>{J(e=>!e)},[]),W=!!S,X=W&&z,[Y,Z]=s(""),ee=l(e=>!!e.label.toLowerCase().includes(Y.toLowerCase())||"function"==typeof S&&S(Y,e),[S,Y]),te=i(()=>P.map(m).map(e=>{const t=!W||""===Y||ee(e);return{...e,visible:t}}),[P,W,Y,ee]),ne=i(()=>!(typeof D>"u")&&P.some(e=>"string"==typeof e?e===D:e.value===D),[D,P]),[re,oe]=s(ne&&void 0!==D?D:""),ae=""!==re,se=i(()=>te.find(e=>e.value===re)?.label||I,[te,re,I]),le=u(null),ie=l(e=>{le.current=e,j&&("function"==typeof j?j(e):j.current=e),e&&oe(e.value)},[j]),ue=f(D);c(()=>{D!==ue&&oe(typeof D>"u"||!ne?"":D)},[D,ue,ne]);const ce=l(e=>{const t=e.value;Z(""),oe(t),Q(),me.current?.focus()},[Q]),pe=f(re);c(()=>{typeof pe>"u"||pe===re||re===D||($&&$({type:"change",target:{name:_,value:re}}),le.current&&le.current.dispatchEvent(new Event("change",{bubbles:!0})))},[$,_,D,re,pe]);const de=u(null),ve=u(!1),fe=u(null),me=u(null),be=l((e,t)=>{if(e&&!W){const e=t.current;e&&h(e,re)}else e?fe.current&&fe.current.focus():ve.current&&me.current&&me.current.focus()},[W,re]),[ge]=p(z,{onFirstVisible:be,onTransitionEnd:be});v({ref:ge});const he=l(()=>{W&&Z(""),x&&(x({type:"blur",target:{name:_,value:re}}),le.current?.dispatchEvent(new Event("focusout",{bubbles:!0}))),ve.current=!1,J(!1)},[x,W,_,re]),ke=l(e=>{de.current?.contains(e.relatedTarget)||he()},[he]),ye=l(()=>{ve.current||(N&&N({type:"change",target:{name:_,value:re}}),ve.current=!0)},[N,re,_]),je=l(e=>{e.target.focus({preventScroll:!0})},[]);c(()=>{const e=le.current,t=fe.current,n=me.current,r=de.current;return e?.addEventListener("focus",()=>{X?t?.focus():n?.focus()}),e?.addEventListener("blur",function(e){r?.contains(e.relatedTarget)&&e.preventDefault()}),()=>{e?.removeEventListener("focus",()=>{X?t?.focus():n?.focus()}),e?.removeEventListener("blur",function(e){r?.contains(e.relatedTarget)&&e.preventDefault()})}},[X]);const we=l(e=>{"ArrowDown"!==e.key&&" "!==e.key||z?"Escape"===e.key&&(e.preventDefault(),e.stopPropagation(),J(!1)):(e.preventDefault(),e.stopPropagation(),J(!0))},[z]),_e=l(e=>{if("ArrowDown"===e.key){e.preventDefault(),e.stopPropagation();const t=ge.current;t&&h(t,W?void 0:re)}else if("Escape"===e.key)e.preventDefault(),e.stopPropagation(),J(!1);else if("Tab"!==e.key||e.shiftKey)"Enter"===e.key&&z&&(e.preventDefault(),e.stopPropagation());else{const t=ge.current;t&&(e.preventDefault(),e.stopPropagation(),h(t,re))}},[ge,re,W,z]),Pe=l(e=>{if("Tab"===e.key)e.preventDefault(),e.stopPropagation(),e.shiftKey&&fe.current?fe.current.focus():me.current&&(oe(e.currentTarget.value),J(!1),me.current.focus());else if("ArrowUp"===e.key&&ge.current&&fe.current){const t=ge.current.querySelector('[role="option"]:not([hidden])');e.currentTarget.id===t?.id&&fe.current&&fe.current.focus()}},[ge]);return c(()=>{const e=e=>{"Escape"===e.key&&z&&J(!1)};return typeof window<"u"&&z&&window.addEventListener("keydown",e),()=>{typeof window<"u"&&window.removeEventListener("keydown",e)}},[z]),e(t,{children:[e("select",{name:_,tabIndex:-1,"data-testid":"jkl-native-select",className:"jkl-sr-only","aria-hidden":!0,ref:ie,value:re,onChange:y,children:[n("option",{value:""})," ",te.map(e=>n("option",{hidden:!e.visible,value:e.value,children:e.label},`${G}-opt-${e.value}`))]}),n(g,{ref:de,"data-testid":"jkl-select",className:r("jkl-select",A,{"jkl-select--inline":T,"jkl-select--open":z&&te.some(e=>e.visible),"jkl-select--no-value":!ae,"jkl-select--invalid":!!C||F}),tooltip:M&&o.isValidElement(M)?o.cloneElement(M,{triggerProps:{...M.props.triggerProps,onFocus:e=>{M.props.triggerProps?.onFocus?.(e),he()}}}):null,...O,id:W?U:q,style:{"--jkl-select-max-shown-options":B,...H},label:E,labelProps:{id:R,srOnly:T,...L,htmlFor:W?U:q},helpLabel:V,errorLabel:C,render:({"aria-invalid":t,...o})=>e("div",{className:"jkl-select__outer-wrapper",style:{width:K},children:[W&&n("input",{...o,"aria-invalid":t,id:U,hidden:!X,ref:fe,placeholder:"Søk",value:Y,onChange:e=>Z(e.target.value),"data-testid":"jkl-select__search-input",className:"jkl-select__search-input","aria-autocomplete":"list","aria-activedescendant":ae?`${G}__${k(re)}`:void 0,"aria-controls":G,"aria-expanded":z,role:"combobox",onKeyDown:_e,onBlur:ke,onFocus:ye,onClick:e=>{e.stopPropagation()}}),n("button",{"aria-invalid":t,...o,id:q,ref:me,hidden:X,type:"button",name:`${_}-btn`,className:r("jkl-select__button",{"jkl-select__button--active-value":!!re}),"data-testid":"jkl-select__button","aria-label":`${se||"Velg"},${E}`,"aria-expanded":z,"aria-controls":G,onBlur:ke,onFocus:ye,onKeyDown:we,onClick:Q,onMouseDown:e=>{e.preventDefault(),me.current?.focus()},children:se}),n("div",{id:G,ref:ge,role:"listbox",className:"jkl-select__options-menu",hidden:!z||te.every(e=>!e.visible),"aria-labelledby":R,tabIndex:-1,"data-focus":"controlled",children:te.map((t,r)=>t.visible?e("button",{hidden:!t.visible,type:"button",id:`${G}__${k(t.value)}`,className:"jkl-select__option","data-testid":"jkl-select__option","aria-selected":t.value===re,role:"option",value:t.value,"data-testautoid":`jkl-select__option-${r}`,onBlur:ke,onFocus:ye,onKeyDown:Pe,onClick:e=>{e.preventDefault(),ce(t)},onMouseOver:je,children:[t.label,t.description?n("span",{className:"jkl-select__option-description",children:t.description}):null]},`${G}-${t.value}`):null)}),n(b,{variant:"medium",pointingDown:!z,className:"jkl-select__arrow"})]})})]})});j.displayName="Select";export{j as Select};
1
+ import{jsxs as e,Fragment as t,jsx as r}from"react/jsx-runtime";import{c as o}from"../../../clsx-BeLtu-UY.js";import n,{forwardRef as a,useState as l,useCallback as s,useMemo as i,useRef as c,useEffect as u}from"react";import{useId as p}from"../../hooks/useId/useId.js";import{useListNavigation as d}from"../../hooks/useListNavigation/useListNavigation.js";import{usePreviousValue as v}from"../../hooks/usePreviousValue/usePreviousValue.js";import{getValuePair as m}from"../../utilities/valuePair.js";import{ArrowVerticalAnimated as f}from"../icon/icons/animated/ArrowVerticalAnimated.js";import{InputGroup as b}from"../input-group/InputGroup.js";import{Popover as h}from"../popover/Popover.js";import{focusSelected as g,toLower as k}from"./select-utils.js";const y=()=>{},w=a((a,w)=>{const{id:j,name:_,items:P,value:D,label:E,labelProps:$,onChange:L,onBlur:N,onFocus:x,className:C,helpLabel:F,errorLabel:A,invalid:S,searchable:V=!1,inline:T=!1,defaultPrompt:I="Velg",width:O,maxShownOptions:K=5,style:B,tooltip:M,...q}=a,z=p(j||"jkl-select",{generateSuffix:!j}),G=`${z}_label`,R=`${z}_button`,U=`${z}_search-input`,W=`--${z.replace(/[^a-zA-Z0-9-]/g,"-")}-anchor`,[Z,H]=l(!1),J=s(()=>{H(e=>!e)},[]),[Q,X]=l("bottom"),Y=s(e=>{X(e.startsWith("top")?"top":"bottom")},[]),ee=!!V,te=ee&&Z,[re,oe]=l(""),ne=s(e=>!!e.label.toLowerCase().includes(re.toLowerCase())||"function"==typeof V&&V(re,e),[V,re]),ae=i(()=>P.map(m).map(e=>{const t=!ee||""===re||ne(e);return{...e,visible:t}}),[P,ee,re,ne]),le=i(()=>!(typeof D>"u")&&P.some(e=>"string"==typeof e?e===D:e.value===D),[D,P]),[se,ie]=l(le&&void 0!==D?D:""),ce=""!==se,ue=i(()=>ae.find(e=>e.value===se)?.label||I,[ae,se,I]),pe=c(null),de=s(e=>{pe.current=e,w&&("function"==typeof w?w(e):w.current=e),e&&ie(e.value)},[w]),ve=v(D);u(()=>{D!==ve&&ie(typeof D>"u"||!le?"":D)},[D,ve,le]);const me=s(e=>{const t=e.value;oe(""),ie(t),J(),ke.current?.focus()},[J]),fe=v(se);u(()=>{typeof fe>"u"||fe===se||se===D||(L&&L({type:"change",target:{name:_,value:se}}),pe.current&&pe.current.dispatchEvent(new Event("change",{bubbles:!0})))},[L,_,D,se,fe]);const be=c(null),he=c(!1),ge=c(null),ke=c(null),ye=c(null),[we,je]=l(null),_e=c(ee),Pe=c(se);u(()=>{_e.current=ee,Pe.current=se});const De=s(e=>{ye.current=e,je(e),e&&!_e.current&&requestAnimationFrame(()=>{ye.current===e&&g(e,Pe.current)})},[]),Ee=v(Z);u(()=>{Z!==Ee&&(Z&&ee?ge.current?.focus():!Z&&he.current&&ke.current&&ke.current.focus())},[Z,Ee,ee]),d({element:we});const $e=s(()=>{ee&&oe(""),N&&(N({type:"blur",target:{name:_,value:se}}),pe.current?.dispatchEvent(new Event("focusout",{bubbles:!0}))),he.current=!1,H(!1)},[N,ee,_,se]),Le=s(e=>{const t=be.current,r=ye.current;t?.contains(e.relatedTarget)||r?.contains(e.relatedTarget)||$e()},[$e]),Ne=s(()=>{he.current||(x&&x({type:"change",target:{name:_,value:se}}),he.current=!0)},[x,se,_]),xe=s(e=>{e.target.focus({preventScroll:!0})},[]);u(()=>{const e=pe.current;if(!e)return;const t=()=>{te?ge.current?.focus():ke.current?.focus()},r=e=>{const t=e.relatedTarget,r=be.current?.contains(t),o=ye.current?.contains(t);(r||o)&&e.preventDefault()};return e.addEventListener("focus",t),e.addEventListener("blur",r),()=>{e.removeEventListener("focus",t),e.removeEventListener("blur",r)}},[te]);const Ce=s(e=>{"ArrowDown"!==e.key&&" "!==e.key||Z?"Escape"===e.key&&(e.preventDefault(),e.stopPropagation(),H(!1)):(e.preventDefault(),e.stopPropagation(),H(!0))},[Z]),Fe=s(e=>{if("ArrowDown"===e.key){e.preventDefault(),e.stopPropagation();const t=ye.current;t&&g(t,ee?void 0:se)}else if("Escape"===e.key)e.preventDefault(),e.stopPropagation(),H(!1);else if("Tab"!==e.key||e.shiftKey)"Enter"===e.key&&Z&&(e.preventDefault(),e.stopPropagation());else{const t=ye.current;t&&(e.preventDefault(),e.stopPropagation(),g(t,se))}},[se,ee,Z]),Ae=s(e=>{if("Tab"===e.key)e.preventDefault(),e.stopPropagation(),e.shiftKey&&ge.current?ge.current.focus():ke.current&&(ie(e.currentTarget.value),H(!1),ke.current.focus());else if("ArrowUp"===e.key&&ye.current&&ge.current){const t=ye.current.querySelector('[role="option"]:not([hidden])');e.currentTarget.id===t?.id&&ge.current&&ge.current.focus()}},[]);return u(()=>{const e=e=>{"Escape"===e.key&&Z&&H(!1)};return typeof window<"u"&&Z&&window.addEventListener("keydown",e),()=>{typeof window<"u"&&window.removeEventListener("keydown",e)}},[Z]),e(t,{children:[e("select",{name:_,tabIndex:-1,"data-testid":"jkl-native-select",className:"jkl-sr-only","aria-hidden":!0,ref:de,value:se,onChange:y,children:[r("option",{value:""})," ",ae.map(e=>r("option",{hidden:!e.visible,value:e.value,children:e.label},`${z}-opt-${e.value}`))]}),r(b,{ref:be,"data-testid":"jkl-select",className:o("jkl-select",C,{"jkl-select--inline":T,"jkl-select--open":Z&&ae.some(e=>e.visible),"jkl-select--no-value":!ce,"jkl-select--invalid":!!A||S}),tooltip:M&&n.isValidElement(M)?n.cloneElement(M,{triggerProps:{...M.props.triggerProps,onFocus:e=>{M.props.triggerProps?.onFocus?.(e),$e()}}}):null,...q,id:ee?U:R,style:B,label:E,labelProps:{id:G,srOnly:T,...$,htmlFor:ee?U:R},helpLabel:F,errorLabel:A,render:({"aria-invalid":t,...n})=>{const a=Z&&ae.some(e=>e.visible);return e(h,{open:a,placement:"bottom-start",offset:0,modal:!1,onPlacementChange:Y,clickOptions:{enabled:!1},dismissOptions:{enabled:!1},roleOptions:{enabled:!1},children:[r(h.Trigger,{asChild:!0,children:e("div",{className:"jkl-select__outer-wrapper","data-popover-placement":Q,style:{width:O,anchorName:W},children:[ee&&r("input",{...n,"aria-invalid":t,id:U,hidden:!te,ref:ge,placeholder:"Søk",value:re,onChange:e=>oe(e.target.value),"data-testid":"jkl-select__search-input",className:"jkl-select__search-input","aria-autocomplete":"list","aria-activedescendant":a&&ce?`${z}__${k(se)}`:void 0,"aria-controls":a?z:void 0,"aria-expanded":a,role:"combobox",onKeyDown:Fe,onBlur:Le,onFocus:Ne,onClick:e=>{e.stopPropagation()}}),r("button",{"aria-invalid":t,...n,id:R,ref:ke,hidden:te,type:"button",name:`${_}-btn`,className:o("jkl-select__button",{"jkl-select__button--active-value":!!se}),"data-testid":"jkl-select__button","aria-label":`${ue||"Velg"},${E}`,"aria-expanded":a,"aria-controls":a?z:void 0,onBlur:Le,onFocus:Ne,onKeyDown:Ce,onClick:J,onMouseDown:e=>{e.preventDefault(),ke.current?.focus()},children:ue}),r(f,{variant:"medium",pointingDown:!a,className:"jkl-select__arrow"})]})}),r(h.Content,{initialFocus:-1,returnFocus:!1,className:"jkl-select__popover",style:{width:`anchor-size(${W} width)`},children:r("div",{id:z,ref:De,role:"listbox",className:"jkl-select__options-menu","data-popover-placement":Q,"aria-labelledby":G,tabIndex:-1,"data-focus":"controlled",style:{"--jkl-select-max-shown-options":K},children:ae.map((t,o)=>t.visible?e("button",{hidden:!t.visible,type:"button",id:`${z}__${k(t.value)}`,className:"jkl-select__option","data-testid":"jkl-select__option","aria-selected":t.value===se,role:"option",value:t.value,"data-testautoid":`jkl-select__option-${o}`,onBlur:Le,onFocus:Ne,onKeyDown:Ae,onClick:e=>{e.preventDefault(),me(t)},onMouseOver:xe,children:[t.label,t.description?r("span",{className:"jkl-select__option-description",children:t.description}):null]},`${z}-${t.value}`):null)})})]})}})]})});w.displayName="Select";export{w as Select};
2
2
  //# sourceMappingURL=Select.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Select.js","sources":["../../../../src/components/select/Select.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, {\n type CSSProperties,\n type FocusEvent,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n type RefObject,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useAnimatedHeight } from \"../../hooks/useAnimatedHeight/useAnimatedHeight.js\";\nimport { useId } from \"../../hooks/useId/useId.js\";\nimport { useListNavigation } from \"../../hooks/useListNavigation/useListNavigation.js\";\nimport { usePreviousValue } from \"../../hooks/usePreviousValue/usePreviousValue.js\";\nimport { type ValuePair, getValuePair } from \"../../utilities/valuePair.js\";\nimport { ArrowVerticalAnimated } from \"../icon/icons/animated/ArrowVerticalAnimated.js\";\nimport { InputGroup } from \"../input-group/InputGroup.js\";\nimport type { PopupTipProps } from \"../tooltip/types.js\";\nimport { focusSelected, toLower } from \"./select-utils.js\";\nimport type { SelectProps } from \"./types.js\";\n\nconst noop = () => {\n return;\n};\n\ninterface Option extends ValuePair {\n visible: boolean;\n}\n\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(\n (props, forwardedSelectRef) => {\n const {\n id,\n name,\n items,\n value,\n label,\n labelProps,\n onChange,\n onBlur,\n onFocus,\n className,\n helpLabel,\n errorLabel,\n invalid,\n searchable = false,\n inline = false,\n defaultPrompt = \"Velg\",\n width,\n maxShownOptions = 5,\n style,\n tooltip,\n ...rest\n } = props;\n\n const listId = useId(id || \"jkl-select\", { generateSuffix: !id });\n const labelId = `${listId}_label`;\n const buttonId = `${listId}_button`;\n const searchInputId = `${listId}_search-input`;\n\n const [dropdownIsShown, setShown] = useState(false);\n const toggleListVisibility = useCallback(() => {\n setShown((previousValue) => !previousValue);\n }, []);\n\n /// Søk\n\n const isSearchable = Boolean(searchable);\n const showSearchInputField = isSearchable && dropdownIsShown;\n const [searchValue, setSearchValue] = useState(\"\");\n const searchFn = useCallback(\n (item: ValuePair) => {\n if (\n item.label.toLowerCase().includes(searchValue.toLowerCase())\n ) {\n return true;\n }\n\n if (typeof searchable === \"function\") {\n return searchable(searchValue, item);\n }\n\n return false;\n },\n [searchable, searchValue],\n );\n const visibleItems: Option[] = useMemo(\n () =>\n items.map(getValuePair).map((item) => {\n const visible =\n !isSearchable || searchValue === \"\" || searchFn(item);\n return { ...item, visible };\n }),\n [items, isSearchable, searchValue, searchFn],\n );\n const valueIsInItems: boolean = useMemo(() => {\n if (typeof value === \"undefined\") {\n return false;\n }\n return items.some((item) =>\n typeof item === \"string\"\n ? item === value\n : item.value === value,\n );\n }, [value, items]);\n\n /// Valg av <option>\n\n const [selectedValue, setSelectedValue] = useState<string>(\n valueIsInItems && value !== undefined ? value : \"\",\n );\n const hasSelectedValue = selectedValue !== \"\";\n const selectedValueLabel = useMemo(\n () =>\n visibleItems.find((item) => item.value === selectedValue)\n ?.label || defaultPrompt,\n [visibleItems, selectedValue, defaultPrompt],\n );\n\n const selectRef = useRef<HTMLSelectElement | null>(null);\n // Hjelpefunksjon som gjør det enklere å forwarde refen og å bruke den selv internt\n const unifiedSelectRef = useCallback(\n (instance: HTMLSelectElement | null) => {\n selectRef.current = instance;\n if (forwardedSelectRef) {\n if (typeof forwardedSelectRef === \"function\") {\n forwardedSelectRef(instance);\n } else {\n forwardedSelectRef.current = instance;\n }\n }\n if (instance) {\n setSelectedValue(instance.value);\n }\n },\n [forwardedSelectRef],\n );\n\n const previousValue = usePreviousValue(value);\n useEffect(() => {\n if (value === previousValue) {\n return;\n }\n if (typeof value === \"undefined\" || !valueIsInItems) {\n setSelectedValue(\"\");\n } else {\n setSelectedValue(value);\n }\n }, [value, previousValue, valueIsInItems]);\n\n const selectOption = useCallback(\n (item: Option) => {\n const nextValue = item.value;\n setSearchValue(\"\");\n setSelectedValue(nextValue);\n toggleListVisibility();\n buttonRef.current?.focus();\n },\n [toggleListVisibility],\n );\n\n // La komponenten rendre <select> med den valgte verdien før onChange trigges, slik at\n // react-hook-form@>7.41.1 behandler feltet som at det har en verdi.\n const previousSelectedValue = usePreviousValue(selectedValue);\n useEffect(() => {\n // previousSelectedValue er undefined på første render, men da vil vi ikke ha en onChange uansett\n if (\n typeof previousSelectedValue === \"undefined\" ||\n previousSelectedValue === selectedValue ||\n selectedValue === value\n ) {\n return;\n }\n if (onChange) {\n onChange({\n type: \"change\",\n target: { name, value: selectedValue },\n });\n }\n if (selectRef.current) {\n selectRef.current.dispatchEvent(\n new Event(\"change\", { bubbles: true }),\n );\n }\n }, [onChange, name, value, selectedValue, previousSelectedValue]);\n\n /// Fokushåndtering\n\n const componentRootElementRef = useRef<HTMLDivElement>(null);\n const focusInsideRef = useRef(false);\n const searchFieldRef = useRef<HTMLInputElement>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n const handleFocusPlacement = useCallback(\n (isOpen: boolean, ref: RefObject<HTMLElement | null>) => {\n if (isOpen && !isSearchable) {\n const listElement = ref.current;\n if (listElement) {\n focusSelected(listElement, selectedValue);\n }\n } else if (isOpen) {\n if (searchFieldRef.current) {\n searchFieldRef.current.focus();\n }\n } else {\n if (focusInsideRef.current && buttonRef.current) {\n buttonRef.current.focus();\n }\n }\n },\n [isSearchable, selectedValue],\n );\n\n const [dropdownRef] = useAnimatedHeight<HTMLDivElement>(\n dropdownIsShown,\n {\n onFirstVisible: handleFocusPlacement,\n onTransitionEnd: handleFocusPlacement,\n },\n );\n\n useListNavigation({ ref: dropdownRef });\n\n const close = useCallback(() => {\n if (isSearchable) {\n setSearchValue(\"\");\n }\n if (onBlur) {\n onBlur({\n type: \"blur\",\n target: { name, value: selectedValue },\n });\n selectRef.current?.dispatchEvent(\n new Event(\"focusout\", { bubbles: true }),\n );\n }\n focusInsideRef.current = false;\n setShown(false);\n }, [onBlur, isSearchable, name, selectedValue]);\n\n const handleBlur = useCallback(\n (e: FocusEvent<HTMLButtonElement | HTMLInputElement>) => {\n const componentRootElement = componentRootElementRef.current;\n // There are known issues in Firefox when using \"relatedTarget\" in onBlur events:\n // https://github.com/facebook/react/issues/2011\n // This might be fixed in react 17. Se issue above.\n const nextFocusIsInsideComponent =\n componentRootElement?.contains(e.relatedTarget as Node);\n if (!nextFocusIsInsideComponent) {\n close();\n }\n },\n [close],\n );\n\n const handleFocus = useCallback(() => {\n if (!focusInsideRef.current) {\n if (onFocus) {\n onFocus({\n type: \"change\",\n target: { name, value: selectedValue },\n });\n }\n focusInsideRef.current = true;\n }\n }, [onFocus, selectedValue, name]);\n\n const handleMouseOver = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n // Ved mouseOver på options flytter vi fokus til dem for å unngå \"dobbel fokus\"\n // der det ser ut som to forskjellige elementer er fokusert/hovered samtidig\n (e.target as HTMLButtonElement).focus({ preventScroll: true });\n },\n [],\n );\n\n // Handle focus and blur of hidden select element\n useEffect(() => {\n const select = selectRef.current;\n const searchField = searchFieldRef.current;\n const button = buttonRef.current;\n const componentRootElement = componentRootElementRef.current;\n\n select?.addEventListener(\"focus\", () => {\n showSearchInputField ? searchField?.focus() : button?.focus();\n });\n select?.addEventListener(\"blur\", function (this, ev) {\n componentRootElement?.contains(ev.relatedTarget as Node) &&\n ev.preventDefault();\n });\n\n return () => {\n select?.removeEventListener(\"focus\", () => {\n showSearchInputField\n ? searchField?.focus()\n : button?.focus();\n });\n select?.removeEventListener(\"blur\", function (this, ev) {\n componentRootElement?.contains(ev.relatedTarget as Node) &&\n ev.preventDefault();\n });\n };\n }, [showSearchInputField]);\n\n /// Tastaturnavigasjon\n\n // Add support for opening dropdown with arrowkey down as expected from native select\n // onKeyDown to stop ArrowDown from scrolling the page\n const handleOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLButtonElement>) => {\n if (\n (e.key === \"ArrowDown\" || e.key === \" \") &&\n !dropdownIsShown\n ) {\n e.preventDefault();\n e.stopPropagation();\n setShown(true);\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n setShown(false);\n }\n },\n [dropdownIsShown],\n );\n\n // onKeyDown to stop ArrowDown from scrolling the page\n const handleSearchOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n e.stopPropagation();\n\n const listElement = dropdownRef.current;\n if (listElement) {\n if (isSearchable) {\n // Flytt fokus til det første elementet i listen, ikke det forrige valgte.\n // Ved endring i filter er det ikke gitt at vi ønsker å ta utgangspunkt i\n // den valgte verdien.\n focusSelected(listElement, undefined);\n } else {\n focusSelected(listElement, selectedValue);\n }\n }\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n setShown(false);\n } else if (e.key === \"Tab\" && !e.shiftKey) {\n const listElement = dropdownRef.current;\n if (listElement) {\n e.preventDefault();\n e.stopPropagation();\n focusSelected(listElement, selectedValue);\n }\n } else if (e.key === \"Enter\" && dropdownIsShown) {\n // Should not propagate Enter keyevent because form might submit\n e.preventDefault();\n e.stopPropagation();\n }\n },\n [dropdownRef, selectedValue, isSearchable, dropdownIsShown],\n );\n\n // onKeyDown so this Tab listener isn't triggered by tabbing from search field to option\n const handleOptionOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === \"Tab\") {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.shiftKey && searchFieldRef.current) {\n searchFieldRef.current.focus();\n } else if (buttonRef.current) {\n // Mimic behaviour of Firefox and native select, where Tab selects the current item and closes the menu\n setSelectedValue(e.currentTarget.value);\n setShown(false);\n buttonRef.current.focus();\n }\n } else if (e.key === \"ArrowUp\") {\n if (dropdownRef.current && searchFieldRef.current) {\n // Can't be based on index since the first item might be filtered out\n const firstVisible = dropdownRef.current.querySelector(\n '[role=\"option\"]:not([hidden])',\n );\n if (\n e.currentTarget.id === firstVisible?.id &&\n searchFieldRef.current\n ) {\n searchFieldRef.current.focus();\n }\n }\n }\n },\n [dropdownRef],\n );\n\n // Add support for closing the dropdown with Escape like native select. Unfortunately, Escape does not trigger the button onKeyDown.\n useEffect(() => {\n const handleEscape = (e: globalThis.KeyboardEvent) => {\n if (e.key === \"Escape\" && dropdownIsShown) {\n setShown(false);\n }\n };\n if (typeof window !== \"undefined\" && dropdownIsShown) {\n window.addEventListener(\"keydown\", handleEscape);\n }\n return () => {\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"keydown\", handleEscape);\n }\n };\n }, [dropdownIsShown]);\n\n return (\n <>\n <select\n name={name}\n tabIndex={-1}\n data-testid=\"jkl-native-select\"\n className=\"jkl-sr-only\"\n aria-hidden\n ref={unifiedSelectRef}\n value={selectedValue}\n onChange={noop} // React complains unless we give an onChange handler. This is technically a read-only field, but readOnly isn't an option here.\n >\n <option value=\"\" />{\" \"}\n {/* Tom option må være et valg, ellers vil <select> alltid ha en value */}\n {visibleItems.map((item) => (\n <option\n key={`${listId}-opt-${item.value}`}\n hidden={!item.visible}\n value={item.value}\n >\n {item.label}\n </option>\n ))}\n </select>\n <InputGroup\n ref={componentRootElementRef}\n data-testid=\"jkl-select\"\n className={clsx(\"jkl-select\", className, {\n \"jkl-select--inline\": inline,\n \"jkl-select--open\":\n dropdownIsShown &&\n visibleItems.some((item) => item.visible),\n \"jkl-select--no-value\": !hasSelectedValue,\n \"jkl-select--invalid\": !!errorLabel || invalid,\n })}\n tooltip={\n tooltip && React.isValidElement<PopupTipProps>(tooltip)\n ? React.cloneElement(tooltip, {\n triggerProps: {\n ...tooltip.props.triggerProps,\n onFocus: (\n e: FocusEvent<HTMLButtonElement>,\n ) => {\n tooltip.props.triggerProps?.onFocus?.(\n e,\n );\n close();\n },\n },\n })\n : null\n }\n {...rest}\n id={isSearchable ? searchInputId : buttonId}\n style={\n {\n \"--jkl-select-max-shown-options\": maxShownOptions,\n ...style,\n } as CSSProperties\n }\n label={label}\n labelProps={{\n id: labelId,\n srOnly: inline,\n ...labelProps,\n htmlFor: isSearchable ? searchInputId : buttonId,\n }}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n render={({\n \"aria-invalid\": ariaInvalid,\n ...inputProps\n }) => (\n <div\n className=\"jkl-select__outer-wrapper\"\n style={{ width }}\n >\n {isSearchable && (\n <input\n {...inputProps}\n aria-invalid={ariaInvalid}\n id={searchInputId}\n hidden={!showSearchInputField}\n ref={searchFieldRef}\n placeholder=\"Søk\"\n value={searchValue}\n onChange={(e) =>\n setSearchValue(e.target.value)\n }\n data-testid=\"jkl-select__search-input\"\n className=\"jkl-select__search-input\"\n aria-autocomplete=\"list\"\n aria-activedescendant={\n hasSelectedValue\n ? `${listId}__${toLower(\n selectedValue,\n )}`\n : undefined\n }\n aria-controls={listId}\n aria-expanded={dropdownIsShown}\n role=\"combobox\"\n onKeyDown={handleSearchOnKeyDown}\n onBlur={handleBlur}\n onFocus={handleFocus}\n onClick={(e) => {\n e.stopPropagation();\n }}\n />\n )}\n {/* eslint-disable-next-line jsx-a11y/role-supports-aria-props */}\n <button\n // Nei dette er ikke i henhold til speccen, men VoiceOver leser den likevel og det er oppførselen vi ønsker\n aria-invalid={ariaInvalid}\n {...inputProps}\n id={buttonId}\n ref={buttonRef}\n hidden={showSearchInputField}\n type=\"button\"\n name={`${name}-btn`}\n className={clsx(\"jkl-select__button\", {\n \"jkl-select__button--active-value\":\n !!selectedValue,\n })}\n data-testid=\"jkl-select__button\"\n aria-label={`${\n selectedValueLabel || \"Velg\"\n },${label}`}\n aria-expanded={dropdownIsShown}\n aria-controls={listId}\n onBlur={handleBlur}\n onFocus={handleFocus}\n onKeyDown={handleOnKeyDown}\n onClick={toggleListVisibility}\n onMouseDown={(e) => {\n // Workaround for en Safari-bug hvor e.relatedTarget er null i onBlur\n // https://twitter.com/MilesSorce/status/1278762360669265925\n e.preventDefault();\n buttonRef.current?.focus();\n }}\n >\n {selectedValueLabel}\n </button>\n <div\n id={listId}\n ref={dropdownRef}\n // biome-ignore lint/a11y/useSemanticElements: Vi reimplementerer select\n role=\"listbox\"\n className=\"jkl-select__options-menu\"\n hidden={\n !dropdownIsShown ||\n visibleItems.every((item) => !item.visible)\n }\n aria-labelledby={labelId}\n tabIndex={-1}\n data-focus=\"controlled\" // lar oss styre markering av valg vha focus\n >\n {visibleItems.map((item, i) =>\n // Det er viktig at vi _fjerner_ elementer som ikke er synlige fra DOMen for at tastaturnavigasjon skal fungere.\n // For eksempel, hvis vi har elementene Apple, Samsung og LG i den rekkefølgen og søker etter \"l\"\n // vil Samsung ikke synes. Om vi bare setter hidden-attributtet på Samsung vil ArrowDown fra Apple ikke fungere.\n // Dette lar seg ikke gjenskape i en enhetstest med JSDOM + user-events, og Cypress lukker Select\n // ved første {downArrow} ¯\\_(ツ)_/¯. Så please test scenariet over manuelt om dette skaper trøbbel for deg.\n item.visible ? (\n <button\n key={`${listId}-${item.value}`}\n hidden={!item.visible}\n type=\"button\"\n id={`${listId}__${toLower(\n item.value,\n )}`}\n className=\"jkl-select__option\"\n data-testid=\"jkl-select__option\"\n aria-selected={\n item.value === selectedValue\n }\n // biome-ignore lint/a11y/useSemanticElements: Vi reimplementerer select\n role=\"option\"\n value={item.value}\n data-testautoid={`jkl-select__option-${i}`}\n onBlur={handleBlur}\n onFocus={handleFocus}\n onKeyDown={handleOptionOnKeyDown}\n onClick={(e) => {\n e.preventDefault();\n selectOption(item);\n }}\n onMouseOver={handleMouseOver}\n >\n {item.label}\n {item.description ? (\n <span className=\"jkl-select__option-description\">\n {item.description}\n </span>\n ) : null}\n </button>\n ) : null,\n )}\n </div>\n <ArrowVerticalAnimated\n variant=\"medium\"\n pointingDown={!dropdownIsShown}\n className=\"jkl-select__arrow\"\n />\n </div>\n )}\n />\n </>\n );\n },\n);\n\nSelect.displayName = \"Select\";\n"],"names":["noop","Select","forwardRef","props","forwardedSelectRef","id","name","items","value","label","labelProps","onChange","onBlur","onFocus","className","helpLabel","errorLabel","invalid","searchable","inline","defaultPrompt","width","maxShownOptions","style","tooltip","rest","listId","useId","generateSuffix","labelId","buttonId","searchInputId","dropdownIsShown","setShown","useState","toggleListVisibility","useCallback","previousValue","isSearchable","showSearchInputField","searchValue","setSearchValue","searchFn","item","toLowerCase","includes","visibleItems","useMemo","map","getValuePair","visible","valueIsInItems","some","selectedValue","setSelectedValue","hasSelectedValue","selectedValueLabel","find","selectRef","useRef","unifiedSelectRef","instance","current","usePreviousValue","useEffect","selectOption","nextValue","buttonRef","focus","previousSelectedValue","type","target","dispatchEvent","Event","bubbles","componentRootElementRef","focusInsideRef","searchFieldRef","handleFocusPlacement","isOpen","ref","listElement","focusSelected","dropdownRef","useAnimatedHeight","onFirstVisible","onTransitionEnd","useListNavigation","close","handleBlur","e","contains","relatedTarget","handleFocus","handleMouseOver","preventScroll","select","searchField","button","componentRootElement","addEventListener","ev","preventDefault","removeEventListener","handleOnKeyDown","key","stopPropagation","handleSearchOnKeyDown","shiftKey","handleOptionOnKeyDown","currentTarget","firstVisible","querySelector","handleEscape","window","jsxs","Fragment","children","tabIndex","jsx","hidden","InputGroup","clsx","React","isValidElement","cloneElement","triggerProps","srOnly","htmlFor","render","ariaInvalid","inputProps","placeholder","toLower","role","onKeyDown","onClick","onMouseDown","every","i","onMouseOver","description","ArrowVerticalAnimated","variant","pointingDown","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"Select.js","sources":["../../../../src/components/select/Select.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, {\n type CSSProperties,\n type FocusEvent,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useId } from \"../../hooks/useId/useId.js\";\nimport { useListNavigation } from \"../../hooks/useListNavigation/useListNavigation.js\";\nimport { usePreviousValue } from \"../../hooks/usePreviousValue/usePreviousValue.js\";\nimport { type ValuePair, getValuePair } from \"../../utilities/valuePair.js\";\nimport { ArrowVerticalAnimated } from \"../icon/icons/animated/ArrowVerticalAnimated.js\";\nimport { InputGroup } from \"../input-group/InputGroup.js\";\nimport Popover from \"../popover/Popover.js\";\nimport type { PopupTipProps } from \"../tooltip/types.js\";\nimport { focusSelected, toLower } from \"./select-utils.js\";\nimport type { SelectProps } from \"./types.js\";\n\nconst noop = () => {\n return;\n};\n\ninterface Option extends ValuePair {\n visible: boolean;\n}\n\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(\n (props, forwardedSelectRef) => {\n const {\n id,\n name,\n items,\n value,\n label,\n labelProps,\n onChange,\n onBlur,\n onFocus,\n className,\n helpLabel,\n errorLabel,\n invalid,\n searchable = false,\n inline = false,\n defaultPrompt = \"Velg\",\n width,\n maxShownOptions = 5,\n style,\n tooltip,\n ...rest\n } = props;\n\n const listId = useId(id || \"jkl-select\", { generateSuffix: !id });\n const labelId = `${listId}_label`;\n const buttonId = `${listId}_button`;\n const searchInputId = `${listId}_search-input`;\n // Unik anchor-name som CSS anchor positioning bruker for å la\n // dropdown-listen matche bredden til triggeren.\n const anchorName = `--${listId.replace(/[^a-zA-Z0-9-]/g, \"-\")}-anchor`;\n\n const [dropdownIsShown, setShown] = useState(false);\n const toggleListVisibility = useCallback(() => {\n setShown((previousValue) => !previousValue);\n }, []);\n\n // Lagrer faktisk placement etter at floating-ui har kjørt `flip`,\n // slik at vi kan bytte hvilken side av lista og knappen som er\n // flat når lista snus over triggeren.\n const [popoverPlacement, setPopoverPlacement] = useState<\n \"top\" | \"bottom\"\n >(\"bottom\");\n const handlePlacementChange = useCallback((p: string) => {\n setPopoverPlacement(p.startsWith(\"top\") ? \"top\" : \"bottom\");\n }, []);\n\n /// Søk\n\n const isSearchable = Boolean(searchable);\n const showSearchInputField = isSearchable && dropdownIsShown;\n const [searchValue, setSearchValue] = useState(\"\");\n const searchFn = useCallback(\n (item: ValuePair) => {\n if (\n item.label.toLowerCase().includes(searchValue.toLowerCase())\n ) {\n return true;\n }\n\n if (typeof searchable === \"function\") {\n return searchable(searchValue, item);\n }\n\n return false;\n },\n [searchable, searchValue],\n );\n const visibleItems: Option[] = useMemo(\n () =>\n items.map(getValuePair).map((item) => {\n const visible =\n !isSearchable || searchValue === \"\" || searchFn(item);\n return { ...item, visible };\n }),\n [items, isSearchable, searchValue, searchFn],\n );\n const valueIsInItems: boolean = useMemo(() => {\n if (typeof value === \"undefined\") {\n return false;\n }\n return items.some((item) =>\n typeof item === \"string\"\n ? item === value\n : item.value === value,\n );\n }, [value, items]);\n\n /// Valg av <option>\n\n const [selectedValue, setSelectedValue] = useState<string>(\n valueIsInItems && value !== undefined ? value : \"\",\n );\n const hasSelectedValue = selectedValue !== \"\";\n const selectedValueLabel = useMemo(\n () =>\n visibleItems.find((item) => item.value === selectedValue)\n ?.label || defaultPrompt,\n [visibleItems, selectedValue, defaultPrompt],\n );\n\n const selectRef = useRef<HTMLSelectElement | null>(null);\n // Hjelpefunksjon som gjør det enklere å forwarde refen og å bruke den selv internt\n const unifiedSelectRef = useCallback(\n (instance: HTMLSelectElement | null) => {\n selectRef.current = instance;\n if (forwardedSelectRef) {\n if (typeof forwardedSelectRef === \"function\") {\n forwardedSelectRef(instance);\n } else {\n forwardedSelectRef.current = instance;\n }\n }\n if (instance) {\n setSelectedValue(instance.value);\n }\n },\n [forwardedSelectRef],\n );\n\n const previousValue = usePreviousValue(value);\n useEffect(() => {\n if (value === previousValue) {\n return;\n }\n if (typeof value === \"undefined\" || !valueIsInItems) {\n setSelectedValue(\"\");\n } else {\n setSelectedValue(value);\n }\n }, [value, previousValue, valueIsInItems]);\n\n const selectOption = useCallback(\n (item: Option) => {\n const nextValue = item.value;\n setSearchValue(\"\");\n setSelectedValue(nextValue);\n toggleListVisibility();\n buttonRef.current?.focus();\n },\n [toggleListVisibility],\n );\n\n // La komponenten rendre <select> med den valgte verdien før onChange trigges, slik at\n // react-hook-form@>7.41.1 behandler feltet som at det har en verdi.\n const previousSelectedValue = usePreviousValue(selectedValue);\n useEffect(() => {\n // previousSelectedValue er undefined på første render, men da vil vi ikke ha en onChange uansett\n if (\n typeof previousSelectedValue === \"undefined\" ||\n previousSelectedValue === selectedValue ||\n selectedValue === value\n ) {\n return;\n }\n if (onChange) {\n onChange({\n type: \"change\",\n target: { name, value: selectedValue },\n });\n }\n if (selectRef.current) {\n selectRef.current.dispatchEvent(\n new Event(\"change\", { bubbles: true }),\n );\n }\n }, [onChange, name, value, selectedValue, previousSelectedValue]);\n\n /// Fokushåndtering\n\n const componentRootElementRef = useRef<HTMLDivElement>(null);\n const focusInsideRef = useRef(false);\n const searchFieldRef = useRef<HTMLInputElement>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n const dropdownRef = useRef<HTMLDivElement | null>(null);\n // Lagrer listbox-elementet i state slik at downstream-hooks\n // (f.eks. `useListNavigation`) kan re-feste listeneren idet\n // `FloatingPortal` mounter listen.\n const [listboxEl, setListboxEl] = useState<HTMLDivElement | null>(null);\n\n // Listen rendres i en `FloatingPortal` som monteres via en\n // `useLayoutEffect` + `setState` i floating-ui. Refen er derfor\n // ikke tilgjengelig før i en senere render. Vi bruker en\n // callback-ref for å plassere fokus på valgt option idet listen\n // faktisk er i DOM-en. Refen holdes stabil (tom dependency-list)\n // slik at en endring i `selectedValue`/`isSearchable` ikke får\n // React til å avmontere/remontere refen og dermed flytte fokus\n // mens menyen er åpen — vi leser siste verdier via refs.\n const isSearchableRef = useRef(isSearchable);\n const selectedValueRef = useRef(selectedValue);\n useEffect(() => {\n isSearchableRef.current = isSearchable;\n selectedValueRef.current = selectedValue;\n });\n\n const setDropdownRef = useCallback((node: HTMLDivElement | null) => {\n dropdownRef.current = node;\n setListboxEl(node);\n if (node && !isSearchableRef.current) {\n // Popover skjules med `visibility: hidden` til\n // floating-ui har regnet ut første posisjon. Defer\n // fokus til etter neste paint, slik at vi ikke flytter\n // fokus til et usynlig element (kan gi manglende\n // fokusindikator i enkelte nettlesere).\n requestAnimationFrame(() => {\n if (dropdownRef.current === node) {\n focusSelected(node, selectedValueRef.current);\n }\n });\n }\n }, []);\n\n // Søkbart felt og knappen som får fokus ved lukking lever i hoved-\n // DOM-en, så for de tilfellene holder en useEffect.\n const wasShown = usePreviousValue(dropdownIsShown);\n useEffect(() => {\n if (dropdownIsShown === wasShown) return;\n if (dropdownIsShown && isSearchable) {\n searchFieldRef.current?.focus();\n } else if (\n !dropdownIsShown &&\n focusInsideRef.current &&\n buttonRef.current\n ) {\n buttonRef.current.focus();\n }\n }, [dropdownIsShown, wasShown, isSearchable]);\n\n useListNavigation({ element: listboxEl });\n\n const close = useCallback(() => {\n if (isSearchable) {\n setSearchValue(\"\");\n }\n if (onBlur) {\n onBlur({\n type: \"blur\",\n target: { name, value: selectedValue },\n });\n selectRef.current?.dispatchEvent(\n new Event(\"focusout\", { bubbles: true }),\n );\n }\n focusInsideRef.current = false;\n setShown(false);\n }, [onBlur, isSearchable, name, selectedValue]);\n\n const handleBlur = useCallback(\n (e: FocusEvent<HTMLButtonElement | HTMLInputElement>) => {\n const componentRootElement = componentRootElementRef.current;\n const dropdownElement = dropdownRef.current;\n // There are known issues in Firefox when using \"relatedTarget\" in onBlur events:\n // https://github.com/facebook/react/issues/2011\n // This might be fixed in react 17. Se issue above.\n // Dropdown rendres i en portal, så vi må sjekke begge trærne\n // for å avgjøre om fokus blir værende inne i komponenten.\n const nextFocusIsInsideComponent =\n componentRootElement?.contains(e.relatedTarget as Node) ||\n dropdownElement?.contains(e.relatedTarget as Node);\n if (!nextFocusIsInsideComponent) {\n close();\n }\n },\n [close],\n );\n\n const handleFocus = useCallback(() => {\n if (!focusInsideRef.current) {\n if (onFocus) {\n onFocus({\n type: \"change\",\n target: { name, value: selectedValue },\n });\n }\n focusInsideRef.current = true;\n }\n }, [onFocus, selectedValue, name]);\n\n const handleMouseOver = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n // Ved mouseOver på options flytter vi fokus til dem for å unngå \"dobbel fokus\"\n // der det ser ut som to forskjellige elementer er fokusert/hovered samtidig\n (e.target as HTMLButtonElement).focus({ preventScroll: true });\n },\n [],\n );\n\n // Handle focus and blur of hidden select element\n useEffect(() => {\n const select = selectRef.current;\n if (!select) return;\n\n const onSelectFocus = () => {\n if (showSearchInputField) {\n searchFieldRef.current?.focus();\n } else {\n buttonRef.current?.focus();\n }\n };\n const onSelectBlur = (ev: globalThis.FocusEvent) => {\n // Les refs ved hvert kall slik at vi alltid sjekker mot\n // siste listbox-element — den portalerte listen kan ha\n // mountet etter at denne effekten ble satt opp.\n const target = ev.relatedTarget as Node | null;\n const insideComponent =\n componentRootElementRef.current?.contains(target);\n const insideDropdown = dropdownRef.current?.contains(target);\n if (insideComponent || insideDropdown) {\n ev.preventDefault();\n }\n };\n\n select.addEventListener(\"focus\", onSelectFocus);\n select.addEventListener(\"blur\", onSelectBlur);\n return () => {\n select.removeEventListener(\"focus\", onSelectFocus);\n select.removeEventListener(\"blur\", onSelectBlur);\n };\n }, [showSearchInputField]);\n\n /// Tastaturnavigasjon\n\n // Add support for opening dropdown with arrowkey down as expected from native select\n // onKeyDown to stop ArrowDown from scrolling the page\n const handleOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLButtonElement>) => {\n if (\n (e.key === \"ArrowDown\" || e.key === \" \") &&\n !dropdownIsShown\n ) {\n e.preventDefault();\n e.stopPropagation();\n setShown(true);\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n setShown(false);\n }\n },\n [dropdownIsShown],\n );\n\n // onKeyDown to stop ArrowDown from scrolling the page\n const handleSearchOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n e.stopPropagation();\n\n const listElement = dropdownRef.current;\n if (listElement) {\n if (isSearchable) {\n // Flytt fokus til det første elementet i listen, ikke det forrige valgte.\n // Ved endring i filter er det ikke gitt at vi ønsker å ta utgangspunkt i\n // den valgte verdien.\n focusSelected(listElement, undefined);\n } else {\n focusSelected(listElement, selectedValue);\n }\n }\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n setShown(false);\n } else if (e.key === \"Tab\" && !e.shiftKey) {\n const listElement = dropdownRef.current;\n if (listElement) {\n e.preventDefault();\n e.stopPropagation();\n focusSelected(listElement, selectedValue);\n }\n } else if (e.key === \"Enter\" && dropdownIsShown) {\n // Should not propagate Enter keyevent because form might submit\n e.preventDefault();\n e.stopPropagation();\n }\n },\n [selectedValue, isSearchable, dropdownIsShown],\n );\n\n // onKeyDown so this Tab listener isn't triggered by tabbing from search field to option\n const handleOptionOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === \"Tab\") {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.shiftKey && searchFieldRef.current) {\n searchFieldRef.current.focus();\n } else if (buttonRef.current) {\n // Mimic behaviour of Firefox and native select, where Tab selects the current item and closes the menu\n setSelectedValue(e.currentTarget.value);\n setShown(false);\n buttonRef.current.focus();\n }\n } else if (e.key === \"ArrowUp\") {\n if (dropdownRef.current && searchFieldRef.current) {\n // Can't be based on index since the first item might be filtered out\n const firstVisible = dropdownRef.current.querySelector(\n '[role=\"option\"]:not([hidden])',\n );\n if (\n e.currentTarget.id === firstVisible?.id &&\n searchFieldRef.current\n ) {\n searchFieldRef.current.focus();\n }\n }\n }\n },\n [],\n );\n\n // Add support for closing the dropdown with Escape like native select. Unfortunately, Escape does not trigger the button onKeyDown.\n useEffect(() => {\n const handleEscape = (e: globalThis.KeyboardEvent) => {\n if (e.key === \"Escape\" && dropdownIsShown) {\n setShown(false);\n }\n };\n if (typeof window !== \"undefined\" && dropdownIsShown) {\n window.addEventListener(\"keydown\", handleEscape);\n }\n return () => {\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"keydown\", handleEscape);\n }\n };\n }, [dropdownIsShown]);\n\n return (\n <>\n <select\n name={name}\n tabIndex={-1}\n data-testid=\"jkl-native-select\"\n className=\"jkl-sr-only\"\n aria-hidden\n ref={unifiedSelectRef}\n value={selectedValue}\n onChange={noop} // React complains unless we give an onChange handler. This is technically a read-only field, but readOnly isn't an option here.\n >\n <option value=\"\" />{\" \"}\n {/* Tom option må være et valg, ellers vil <select> alltid ha en value */}\n {visibleItems.map((item) => (\n <option\n key={`${listId}-opt-${item.value}`}\n hidden={!item.visible}\n value={item.value}\n >\n {item.label}\n </option>\n ))}\n </select>\n <InputGroup\n ref={componentRootElementRef}\n data-testid=\"jkl-select\"\n className={clsx(\"jkl-select\", className, {\n \"jkl-select--inline\": inline,\n \"jkl-select--open\":\n dropdownIsShown &&\n visibleItems.some((item) => item.visible),\n \"jkl-select--no-value\": !hasSelectedValue,\n \"jkl-select--invalid\": !!errorLabel || invalid,\n })}\n tooltip={\n tooltip && React.isValidElement<PopupTipProps>(tooltip)\n ? React.cloneElement(tooltip, {\n triggerProps: {\n ...tooltip.props.triggerProps,\n onFocus: (\n e: FocusEvent<HTMLButtonElement>,\n ) => {\n tooltip.props.triggerProps?.onFocus?.(\n e,\n );\n close();\n },\n },\n })\n : null\n }\n {...rest}\n id={isSearchable ? searchInputId : buttonId}\n style={style}\n label={label}\n labelProps={{\n id: labelId,\n srOnly: inline,\n ...labelProps,\n htmlFor: isSearchable ? searchInputId : buttonId,\n }}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n render={({\n \"aria-invalid\": ariaInvalid,\n ...inputProps\n }) => {\n // Lista vises kun når dropdown er åpnet *og* det\n // finnes minst ett synlig valg. `aria-expanded` på\n // trigger og combobox må følge samme boolean for\n // ikke å lyve om popoverens tilstand.\n const isPopoverOpen =\n dropdownIsShown &&\n visibleItems.some((item) => item.visible);\n return (\n <Popover\n open={isPopoverOpen}\n placement=\"bottom-start\"\n offset={0}\n modal={false}\n onPlacementChange={handlePlacementChange}\n clickOptions={{ enabled: false }}\n dismissOptions={{ enabled: false }}\n roleOptions={{ enabled: false }}\n >\n <Popover.Trigger asChild>\n <div\n className=\"jkl-select__outer-wrapper\"\n data-popover-placement={\n popoverPlacement\n }\n style={\n {\n width,\n anchorName,\n } as CSSProperties\n }\n >\n {isSearchable && (\n <input\n {...inputProps}\n aria-invalid={ariaInvalid}\n id={searchInputId}\n hidden={!showSearchInputField}\n ref={searchFieldRef}\n placeholder=\"Søk\"\n value={searchValue}\n onChange={(e) =>\n setSearchValue(\n e.target.value,\n )\n }\n data-testid=\"jkl-select__search-input\"\n className=\"jkl-select__search-input\"\n aria-autocomplete=\"list\"\n aria-activedescendant={\n isPopoverOpen &&\n hasSelectedValue\n ? `${listId}__${toLower(\n selectedValue,\n )}`\n : undefined\n }\n aria-controls={\n isPopoverOpen\n ? listId\n : undefined\n }\n aria-expanded={isPopoverOpen}\n role=\"combobox\"\n onKeyDown={\n handleSearchOnKeyDown\n }\n onBlur={handleBlur}\n onFocus={handleFocus}\n onClick={(e) => {\n e.stopPropagation();\n }}\n />\n )}\n {/* eslint-disable-next-line jsx-a11y/role-supports-aria-props */}\n <button\n // Nei dette er ikke i henhold til speccen, men VoiceOver leser den likevel og det er oppførselen vi ønsker\n aria-invalid={ariaInvalid}\n {...inputProps}\n id={buttonId}\n ref={buttonRef}\n hidden={showSearchInputField}\n type=\"button\"\n name={`${name}-btn`}\n className={clsx(\n \"jkl-select__button\",\n {\n \"jkl-select__button--active-value\":\n !!selectedValue,\n },\n )}\n data-testid=\"jkl-select__button\"\n aria-label={`${\n selectedValueLabel || \"Velg\"\n },${label}`}\n aria-expanded={isPopoverOpen}\n aria-controls={\n isPopoverOpen\n ? listId\n : undefined\n }\n onBlur={handleBlur}\n onFocus={handleFocus}\n onKeyDown={handleOnKeyDown}\n onClick={toggleListVisibility}\n onMouseDown={(e) => {\n // Workaround for en Safari-bug hvor e.relatedTarget er null i onBlur\n // https://twitter.com/MilesSorce/status/1278762360669265925\n e.preventDefault();\n buttonRef.current?.focus();\n }}\n >\n {selectedValueLabel}\n </button>\n <ArrowVerticalAnimated\n variant=\"medium\"\n pointingDown={!isPopoverOpen}\n className=\"jkl-select__arrow\"\n />\n </div>\n </Popover.Trigger>\n <Popover.Content\n initialFocus={-1}\n returnFocus={false}\n className=\"jkl-select__popover\"\n style={{\n width: `anchor-size(${anchorName} width)`,\n }}\n >\n <div\n id={listId}\n ref={setDropdownRef}\n // biome-ignore lint/a11y/useSemanticElements: Vi reimplementerer select\n role=\"listbox\"\n className=\"jkl-select__options-menu\"\n data-popover-placement={\n popoverPlacement\n }\n aria-labelledby={labelId}\n tabIndex={-1}\n data-focus=\"controlled\" // lar oss styre markering av valg vha focus\n style={\n {\n \"--jkl-select-max-shown-options\":\n maxShownOptions,\n } as CSSProperties\n }\n >\n {visibleItems.map((item, i) =>\n // Det er viktig at vi _fjerner_ elementer som ikke er synlige fra DOMen for at tastaturnavigasjon skal fungere.\n // For eksempel, hvis vi har elementene Apple, Samsung og LG i den rekkefølgen og søker etter \"l\"\n // vil Samsung ikke synes. Om vi bare setter hidden-attributtet på Samsung vil ArrowDown fra Apple ikke fungere.\n // Dette lar seg ikke gjenskape i en enhetstest med JSDOM + user-events, og Cypress lukker Select\n // ved første {downArrow} ¯\\_(ツ)_/¯. Så please test scenariet over manuelt om dette skaper trøbbel for deg.\n item.visible ? (\n <button\n key={`${listId}-${item.value}`}\n hidden={!item.visible}\n type=\"button\"\n id={`${listId}__${toLower(\n item.value,\n )}`}\n className=\"jkl-select__option\"\n data-testid=\"jkl-select__option\"\n aria-selected={\n item.value ===\n selectedValue\n }\n // biome-ignore lint/a11y/useSemanticElements: Vi reimplementerer select\n role=\"option\"\n value={item.value}\n data-testautoid={`jkl-select__option-${i}`}\n onBlur={handleBlur}\n onFocus={handleFocus}\n onKeyDown={\n handleOptionOnKeyDown\n }\n onClick={(e) => {\n e.preventDefault();\n selectOption(item);\n }}\n onMouseOver={\n handleMouseOver\n }\n >\n {item.label}\n {item.description ? (\n <span className=\"jkl-select__option-description\">\n {item.description}\n </span>\n ) : null}\n </button>\n ) : null,\n )}\n </div>\n </Popover.Content>\n </Popover>\n );\n }}\n />\n </>\n );\n },\n);\n\nSelect.displayName = \"Select\";\n"],"names":["noop","Select","forwardRef","props","forwardedSelectRef","id","name","items","value","label","labelProps","onChange","onBlur","onFocus","className","helpLabel","errorLabel","invalid","searchable","inline","defaultPrompt","width","maxShownOptions","style","tooltip","rest","listId","useId","generateSuffix","labelId","buttonId","searchInputId","anchorName","replace","dropdownIsShown","setShown","useState","toggleListVisibility","useCallback","previousValue","popoverPlacement","setPopoverPlacement","handlePlacementChange","p","startsWith","isSearchable","showSearchInputField","searchValue","setSearchValue","searchFn","item","toLowerCase","includes","visibleItems","useMemo","map","getValuePair","visible","valueIsInItems","some","selectedValue","setSelectedValue","hasSelectedValue","selectedValueLabel","find","selectRef","useRef","unifiedSelectRef","instance","current","usePreviousValue","useEffect","selectOption","nextValue","buttonRef","focus","previousSelectedValue","type","target","dispatchEvent","Event","bubbles","componentRootElementRef","focusInsideRef","searchFieldRef","dropdownRef","listboxEl","setListboxEl","isSearchableRef","selectedValueRef","setDropdownRef","node","requestAnimationFrame","focusSelected","wasShown","useListNavigation","element","close","handleBlur","e","componentRootElement","dropdownElement","contains","relatedTarget","handleFocus","handleMouseOver","preventScroll","select","onSelectFocus","onSelectBlur","ev","insideComponent","insideDropdown","preventDefault","addEventListener","removeEventListener","handleOnKeyDown","key","stopPropagation","handleSearchOnKeyDown","listElement","shiftKey","handleOptionOnKeyDown","currentTarget","firstVisible","querySelector","handleEscape","window","jsxs","Fragment","children","tabIndex","ref","jsx","hidden","InputGroup","clsx","React","isValidElement","cloneElement","triggerProps","srOnly","htmlFor","render","ariaInvalid","inputProps","isPopoverOpen","Popover","open","placement","offset","modal","onPlacementChange","clickOptions","enabled","dismissOptions","roleOptions","Trigger","asChild","placeholder","toLower","role","onKeyDown","onClick","onMouseDown","ArrowVerticalAnimated","variant","pointingDown","Content","initialFocus","returnFocus","i","onMouseOver","description","displayName"],"mappings":"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"}
@@ -1,11 +1,16 @@
1
+ import { AriaRole } from 'react';
1
2
  import { WithChildren } from '../../utilities/types.js';
2
3
  export interface SystemMessageProps extends WithChildren {
3
4
  id?: string;
4
5
  className?: string;
5
6
  maxContentWidth?: string;
6
7
  paddingLeft?: string;
7
- /** Overstyr standardrollen til meldingen. Om du ønsker å "skru av" rollen kan du bruke verdien `none presentation`. */
8
- role?: string;
8
+ /**
9
+ * Overstyr standardrollen til meldingen. Om du ønsker å "skru av" rollen kan du bruke verdien `none` eller `presentation`.
10
+ *
11
+ * @see https://www.w3.org/TR/wai-aria-1.2/#role_definitions
12
+ */
13
+ role?: AriaRole | string;
9
14
  dismissed?: boolean;
10
15
  dismissAction?: {
11
16
  handleDismiss: () => void;
@@ -1,2 +1,2 @@
1
- import{jsxs as e,jsx as t}from"react/jsx-runtime";import{ToastQueue as o}from"@react-stately/toast";import{createContext as s,useContext as a,useState as i}from"react";import{ToastRegion as r}from"./ToastRegion.js";const m=s({add:()=>"missing-provider",close:()=>{}}),n=()=>a(m),u=({children:s,maxVisibleToasts:a=5,placement:n="center"})=>{const[u]=i(new o({maxVisibleToasts:a,hasExitAnimation:!0}));return e(m.Provider,{value:{close:u.close.bind(u),add:(e,t)=>{let o=5e3;return"number"==typeof t?.timeout?o=t.timeout:(null===t?.timeout||"off"===t?.timeout)&&(o=void 0),u.add(e,{...t,timeout:o})}},children:[s,t(r,{queue:u,placement:n})]})};export{u as ToastProvider,n as useToast};
1
+ import{jsxs as e,jsx as t}from"react/jsx-runtime";import{ToastQueue as o}from"@react-stately/toast";import{createContext as s,useState as a,useContext as i}from"react";import{ToastRegion as r}from"./ToastRegion.js";const m=s({add:()=>"missing-provider",close:()=>{}}),n=()=>i(m),u=({children:s,maxVisibleToasts:i=5,placement:n="center"})=>{const[u]=a(new o({maxVisibleToasts:i,hasExitAnimation:!0}));return e(m.Provider,{value:{close:u.close.bind(u),add:(e,t)=>{let o=5e3;return"number"==typeof t?.timeout?o=t.timeout:(null===t?.timeout||"off"===t?.timeout)&&(o=void 0),u.add(e,{...t,timeout:o})}},children:[s,t(r,{queue:u,placement:n})]})};export{u as ToastProvider,n as useToast};
2
2
  //# sourceMappingURL=toastContext.js.map
@@ -1,2 +1,2 @@
1
- import{jsx as e}from"react/jsx-runtime";import{useFloating as t,offset as n,flip as o,shift as s,arrow as r,autoUpdate as a,useRole as i,useDismiss as l,useClick as u,useHover as p,useFocus as c,useInteractions as d}from"@floating-ui/react";import{createContext as m,useContext as f,useState as x,useRef as g}from"react";const h=m(null),v=h.Provider,O=()=>{const e=f(h);if(null===e)throw new Error("Tooltip-komponentene kan kun brukes inne i <Tooltip />");return e},k=({children:m,...f})=>{const h=(({initialOpen:e=!1,placement:m="top",delay:f=250,triggerOn:h="hover",onOpenChange:v})=>{const[O,k]=x(e),w=g(null),C=g(null),T=t({open:O,onOpenChange:e=>{v?.(e),k(e)},placement:m,whileElementsMounted:a,middleware:[n(16),o(),s({padding:16}),r({element:w,padding:8})]}),b=i(T.context,{role:"tooltip"}),E=l(T.context),j=u(T.context,{enabled:"click"===h}),y=p(T.context,{enabled:"hover"===h,delay:O?0:f}),D=c(T.context,{enabled:"hover"===h}),F=d([E,D,b,j,y]);return{triggerOn:h,isOpen:O,setOpen:k,arrowElement:w,...T,refs:{...T.refs,description:C,setDescription:e=>{C.current=e}},...F}})(f);return e(v,{value:h,children:m})};export{k as Tooltip,v as TooltipProvider,O as useTooltipContext};
1
+ import{jsx as e}from"react/jsx-runtime";import{useFloating as t,autoUpdate as n,offset as o,flip as s,shift as r,arrow as a,useRole as i,useDismiss as l,useClick as u,useHover as p,useFocus as c,useInteractions as d}from"@floating-ui/react";import{createContext as m,useContext as f,useState as x,useRef as g}from"react";const h=m(null),v=h.Provider,O=()=>{const e=f(h);if(null===e)throw new Error("Tooltip-komponentene kan kun brukes inne i <Tooltip />");return e},k=({children:m,...f})=>{const h=(({initialOpen:e=!1,placement:m="top",delay:f=250,triggerOn:h="hover",onOpenChange:v})=>{const[O,k]=x(e),w=g(null),C=g(null),T=t({open:O,onOpenChange:e=>{v?.(e),k(e)},placement:m,whileElementsMounted:n,middleware:[o(16),s(),r({padding:16}),a({element:w,padding:8})]}),b=i(T.context,{role:"tooltip"}),E=l(T.context),j=u(T.context,{enabled:"click"===h}),y=p(T.context,{enabled:"hover"===h,delay:O?0:f}),D=c(T.context,{enabled:"hover"===h}),F=d([E,D,b,j,y]);return{triggerOn:h,isOpen:O,setOpen:k,arrowElement:w,...T,refs:{...T.refs,description:C,setDescription:e=>{C.current=e}},...F}})(f);return e(v,{value:h,children:m})};export{k as Tooltip,v as TooltipProvider,O as useTooltipContext};
2
2
  //# sourceMappingURL=Tooltip.js.map
@@ -1,2 +1,2 @@
1
- import{jsx as e,jsxs as t,Fragment as n}from"react/jsx-runtime";import"react";const s=[e(n,{children:e("p",{className:"jkl-body",children:"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."})}),t(n,{children:[e("p",{className:"jkl-body",children:"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."}),e("p",{className:"jkl-body",children:"It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged."})]}),t(n,{children:[e("p",{className:"jkl-body",children:"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."}),e("p",{className:"jkl-body",children:"It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged."}),e("p",{className:"jkl-body",children:"It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."})]}),t(n,{children:[e("p",{className:"jkl-body",children:"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."}),e("p",{className:"jkl-body",children:"It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged."}),e("p",{className:"jkl-body",children:"It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."}),e("p",{className:"jkl-body",children:"Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old."})]})];function a(e){let t=s[Math.floor(Math.random()*s.length)];return t===e&&(t=a(e)),t}export{a as randomContentBlock};
1
+ import{jsx as e,Fragment as t,jsxs as n}from"react/jsx-runtime";import"react";const s=[e(t,{children:e("p",{className:"jkl-body",children:"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."})}),n(t,{children:[e("p",{className:"jkl-body",children:"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."}),e("p",{className:"jkl-body",children:"It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged."})]}),n(t,{children:[e("p",{className:"jkl-body",children:"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."}),e("p",{className:"jkl-body",children:"It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged."}),e("p",{className:"jkl-body",children:"It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."})]}),n(t,{children:[e("p",{className:"jkl-body",children:"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."}),e("p",{className:"jkl-body",children:"It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged."}),e("p",{className:"jkl-body",children:"It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."}),e("p",{className:"jkl-body",children:"Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old."})]})];function a(e){let t=s[Math.floor(Math.random()*s.length)];return t===e&&(t=a(e)),t}export{a as randomContentBlock};
2
2
  //# sourceMappingURL=content.js.map
@@ -1,7 +1,16 @@
1
1
  import { RefObject } from 'react';
2
+ /**
3
+ * Enten `ref` eller `element` må gis. `ref` brukes når listen alltid
4
+ * er i DOM-en; `element` foretrekkes når elementet mountes/unmountes
5
+ * dynamisk (f.eks. portalert via floating-ui), slik at listeneren
6
+ * re-festes når elementet faktisk er tilgjengelig.
7
+ */
2
8
  type UseListNavigationProps<T> = {
3
- /** Ref til et element med rollen `listbox` */
4
9
  ref: RefObject<T | null>;
10
+ element?: never;
11
+ } | {
12
+ ref?: never;
13
+ element: T | null;
5
14
  };
6
- export declare function useListNavigation<T extends HTMLElement>({ ref, }: UseListNavigationProps<T>): void;
15
+ export declare function useListNavigation<T extends HTMLElement>({ ref, element, }: UseListNavigationProps<T>): void;
7
16
  export {};
@@ -1,2 +1,2 @@
1
- import{useEffect as e}from"react";function t({ref:t}){e(()=>{const e={keys:""},s=t.current,n=t=>{s&&function({list:e,event:t,search:s,searchResetTimer:n}){const{key:c,target:o}=t,a={event:t,list:e,currentFocus:o};switch(c){case"ArrowUp":case"PageUp":r("prev",a);break;case"ArrowDown":case"PageDown":r("next",a);break;case"Home":r("first",a);break;case"End":r("last",a);break;case"Tab":t.preventDefault();break;case"Enter":case" ":break;default:if(void 0!==s){const t=function({list:e,key:t,search:r,searchResetTimer:s}){const n=e.querySelectorAll('[role="option"]');if(!n.length)return null;if(r){r.keys=r.keys.concat(t),function(e,t){t&&(clearTimeout(t),t=void 0),t=setTimeout(()=>{e?e.keys="":e={keys:""},t=void 0},500,e,t)}(r,s);for(let e=0;e<n.length;e++){const t=n[e].innerText;if(t&&0===t.toLowerCase().indexOf(r.keys))return n[e]}}return null}({list:e,key:c,search:s,searchResetTimer:n});t&&t.focus()}}}({list:s,event:t,search:e,searchResetTimer:undefined})};return s&&s.addEventListener("keydown",n),()=>{s&&s.removeEventListener("keydown",n)}},[t])}function r(e,{event:t,list:r,currentFocus:s}){t.preventDefault(),function(e,t,r){const s=r;switch(e){case"prev":{const e=s&&s.previousElementSibling;e&&e.focus();break}case"next":{const e=s&&s.nextElementSibling;e&&e.focus();break}case"first":{const e=t.querySelector('[role="option"]');e&&e.focus();break}case"last":{const e=t.querySelectorAll('[role="option"]');e.length&&e[e.length-1].focus();break}}}(e,r,s)}export{t as useListNavigation};
1
+ import{useLayoutEffect as e}from"react";function t({ref:t,element:n}){e(()=>{const e=n??t?.current??null;if(!e)return;const s={id:void 0},o={keys:""},c=t=>{!function({list:e,event:t,search:n,searchResetTimer:s}){const{key:o,target:c}=t,i={event:t,list:e,currentFocus:c};switch(o){case"ArrowUp":case"PageUp":r("prev",i);break;case"ArrowDown":case"PageDown":r("next",i);break;case"Home":r("first",i);break;case"End":r("last",i);break;case"Tab":t.preventDefault();break;case"Enter":case" ":break;default:if(void 0!==n){const t=function({list:e,key:t,search:r,searchResetTimer:n}){const s=e.querySelectorAll('[role="option"]');if(!s.length)return null;if(r){r.keys=r.keys.concat(t),function(e,t){void 0!==t.id&&(clearTimeout(t.id),t.id=void 0),t.id=window.setTimeout(()=>{e&&(e.keys=""),t.id=void 0},500)}(r,n);for(let e=0;e<s.length;e++){const t=s[e].innerText;if(t&&0===t.toLowerCase().indexOf(r.keys))return s[e]}}return null}({list:e,key:o,search:n,searchResetTimer:s});t&&t.focus()}}}({list:e,event:t,search:o,searchResetTimer:s})};return e.addEventListener("keydown",c),()=>{e.removeEventListener("keydown",c),void 0!==s.id&&clearTimeout(s.id)}},[n,t])}function r(e,{event:t,list:r,currentFocus:n}){t.preventDefault(),function(e,t,r){const n=r;switch(e){case"prev":{const e=n&&n.previousElementSibling;e&&e.focus();break}case"next":{const e=n&&n.nextElementSibling;e&&e.focus();break}case"first":{const e=t.querySelector('[role="option"]');e&&e.focus();break}case"last":{const e=t.querySelectorAll('[role="option"]');e.length&&e[e.length-1].focus();break}}}(e,r,n)}export{t as useListNavigation};
2
2
  //# sourceMappingURL=useListNavigation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useListNavigation.js","sources":["../../../../src/hooks/useListNavigation/useListNavigation.ts"],"sourcesContent":["import { type RefObject, useEffect } from \"react\";\n\ntype Timer = number | undefined;\ntype KeyBuffer = { keys: string } | undefined;\ntype Direction = \"prev\" | \"next\" | \"first\" | \"last\";\ninterface MoveDetails {\n event: KeyboardEvent;\n list: HTMLElement;\n currentFocus: HTMLButtonElement;\n}\ninterface ListDetails {\n list: HTMLElement;\n search: KeyBuffer;\n searchResetTimer: Timer;\n}\ninterface SearchDetails extends ListDetails {\n key: string;\n}\ninterface EventDetails extends ListDetails {\n event: KeyboardEvent;\n}\ntype UseListNavigationProps<T> = {\n /** Ref til et element med rollen `listbox` */\n ref: RefObject<T | null>;\n};\n\nexport function useListNavigation<T extends HTMLElement>({\n ref,\n}: UseListNavigationProps<T>): void {\n useEffect(() => {\n let searchResetTimer: Timer;\n const search: KeyBuffer = { keys: \"\" }; // keypress buffer is an object to preserve state\n const list = ref.current;\n const handler = (event: KeyboardEvent) => {\n if (list) {\n handleListKeyNav({ list, event, search, searchResetTimer });\n }\n };\n\n if (list) {\n list.addEventListener(\"keydown\", handler);\n }\n\n return () => {\n if (list) {\n list.removeEventListener(\"keydown\", handler);\n }\n };\n }, [ref]);\n}\n\nfunction handleMoveTo(\n direction: Direction,\n { event, list, currentFocus }: MoveDetails,\n) {\n event.preventDefault();\n moveFocusTo(direction, list, currentFocus);\n}\n\nfunction handleListKeyNav({\n list,\n event,\n search,\n searchResetTimer,\n}: EventDetails) {\n const { key, target } = event;\n const currentFocus = target as HTMLButtonElement;\n\n const moveDetails = {\n event,\n list,\n currentFocus,\n };\n\n switch (key) {\n case \"ArrowUp\":\n case \"PageUp\":\n handleMoveTo(\"prev\", moveDetails);\n break;\n case \"ArrowDown\":\n case \"PageDown\":\n handleMoveTo(\"next\", moveDetails);\n break;\n case \"Home\":\n handleMoveTo(\"first\", moveDetails);\n break;\n case \"End\":\n handleMoveTo(\"last\", moveDetails);\n break;\n case \"Tab\":\n // in a standard select, tab does nothing in-menu\n event.preventDefault();\n break;\n case \"Enter\":\n case \" \":\n break;\n\n default:\n if (search !== undefined) {\n const searchResult = findItem({\n list,\n key,\n search,\n searchResetTimer,\n });\n if (searchResult) {\n searchResult.focus();\n }\n }\n break;\n }\n}\n\nfunction moveFocusTo(\n direction: Direction,\n list: HTMLElement,\n current: HTMLButtonElement,\n) {\n const thisOption = current;\n switch (direction) {\n case \"prev\": {\n const prevOption: HTMLButtonElement | null =\n thisOption &&\n (thisOption.previousElementSibling as HTMLButtonElement);\n if (prevOption) {\n prevOption.focus();\n }\n break;\n }\n case \"next\": {\n const nextOption: HTMLButtonElement | null =\n thisOption &&\n (thisOption.nextElementSibling as HTMLButtonElement);\n if (nextOption) {\n nextOption.focus();\n }\n break;\n }\n case \"first\": {\n const firstItem =\n list.querySelector<HTMLButtonElement>(`[role=\"option\"]`);\n if (firstItem) {\n firstItem.focus();\n }\n break;\n }\n case \"last\": {\n const listItems =\n list.querySelectorAll<HTMLButtonElement>(`[role=\"option\"]`);\n if (listItems.length) {\n listItems[listItems.length - 1].focus();\n }\n break;\n }\n }\n}\n\nfunction findItem({\n list,\n key,\n search,\n searchResetTimer,\n}: SearchDetails): HTMLButtonElement | null {\n const listItems = list.querySelectorAll(`[role=\"option\"]`);\n if (!listItems.length) return null;\n\n if (search) {\n search.keys = search.keys.concat(key);\n resetWhenIdle(search, searchResetTimer);\n\n for (let n = 0; n < listItems.length; n++) {\n const label = (listItems[n] as HTMLButtonElement).innerText;\n if (label && label.toLowerCase().indexOf(search.keys) === 0) {\n return listItems[n] as HTMLButtonElement;\n }\n }\n }\n\n return null;\n}\n\nfunction resetWhenIdle(search: KeyBuffer, timer: Timer) {\n if (timer) {\n clearTimeout(timer);\n timer = undefined;\n }\n timer = setTimeout(\n () => {\n // biome-ignore lint/suspicious/noAssignInExpressions: <explanation>\n search ? (search.keys = \"\") : (search = { keys: \"\" });\n timer = undefined;\n },\n 500,\n search,\n timer,\n );\n}\n"],"names":["useListNavigation","ref","useEffect","search","keys","list","current","handler","event","searchResetTimer","key","target","moveDetails","currentFocus","handleMoveTo","preventDefault","searchResult","listItems","querySelectorAll","length","concat","timer","clearTimeout","setTimeout","resetWhenIdle","n","label","innerText","toLowerCase","indexOf","findItem","focus","handleListKeyNav","addEventListener","removeEventListener","direction","thisOption","prevOption","previousElementSibling","nextOption","nextElementSibling","firstItem","querySelector","moveFocusTo"],"mappings":"kCA0BO,SAASA,GACZC,IAAAA,IAEAC,EAAU,KAEN,MAAMC,EAAoB,CAAEC,KAAM,IAC5BC,EAAOJ,EAAIK,QACXC,EAAWC,IACTH,GAyBhB,UACIA,KAAAA,EACAG,MAAAA,EACAL,OAAAA,EACAM,iBAAAA,IAEA,MAAQC,IAAAA,EAAKC,OAAAA,GAAWH,EAGlBI,EAAc,CAChBJ,MAAAA,EACAH,KAAAA,EACAQ,aALiBF,GAQrB,OAAQD,GACJ,IAAK,UACL,IAAK,SACDI,EAAa,OAAQF,GACrB,MACJ,IAAK,YACL,IAAK,WACDE,EAAa,OAAQF,GACrB,MACJ,IAAK,OACDE,EAAa,QAASF,GACtB,MACJ,IAAK,MACDE,EAAa,OAAQF,GACrB,MACJ,IAAK,MAEDJ,EAAMO,iBACN,MACJ,IAAK,QACL,IAAK,IACD,MAEJ,QACI,QAAe,IAAXZ,EAAsB,CACtB,MAAMa,EA0DtB,UACIX,KAAAA,EACAK,IAAAA,EACAP,OAAAA,EACAM,iBAAAA,IAEA,MAAMQ,EAAYZ,EAAKa,iBAAiB,mBACxC,IAAKD,EAAUE,OAAQ,OAAO,KAE9B,GAAIhB,EAAQ,CACRA,EAAOC,KAAOD,EAAOC,KAAKgB,OAAOV,GAczC,SAAuBP,EAAmBkB,GAClCA,IACAC,aAAaD,GACbA,OAAQ,GAEZA,EAAQE,WACJ,KAEIpB,EAAUA,EAAOC,KAAO,GAAOD,EAAS,CAAEC,KAAM,IAChDiB,OAAQ,GAEZ,IACAlB,EACAkB,EAER,CA5BQG,CAAcrB,EAAQM,GAEtB,IAAA,IAASgB,EAAI,EAAGA,EAAIR,EAAUE,OAAQM,IAAK,CACvC,MAAMC,EAAST,EAAUQ,GAAyBE,UAClD,GAAID,GAAsD,IAA7CA,EAAME,cAAcC,QAAQ1B,EAAOC,MAC5C,OAAOa,EAAUQ,EAEzB,CACJ,CAEA,OAAO,IACX,CAhFqCK,CAAS,CAC1BzB,KAAAA,EACAK,IAAAA,EACAP,OAAAA,EACAM,iBAAAA,IAEAO,GACAA,EAAae,OAErB,EAGZ,CA5EgBC,CAAiB,CAAE3B,KAAAA,EAAMG,MAAAA,EAAOL,OAAAA,EAAQM,iBAL5CA,aASJ,OAAIJ,GACAA,EAAK4B,iBAAiB,UAAW1B,GAG9B,KACCF,GACAA,EAAK6B,oBAAoB,UAAW3B,KAG7C,CAACN,GACR,CAEA,SAASa,EACLqB,GACE3B,MAAAA,EAAOH,KAAAA,EAAMQ,aAAAA,IAEfL,EAAMO,iBA0DV,SACIoB,EACA9B,EACAC,GAEA,MAAM8B,EAAa9B,EACnB,OAAQ6B,GACJ,IAAK,OAAQ,CACT,MAAME,EACFD,GACCA,EAAWE,uBACZD,GACAA,EAAWN,QAEf,KACJ,CACA,IAAK,OAAQ,CACT,MAAMQ,EACFH,GACCA,EAAWI,mBACZD,GACAA,EAAWR,QAEf,KACJ,CACA,IAAK,QAAS,CACV,MAAMU,EACFpC,EAAKqC,cAAiC,mBACtCD,GACAA,EAAUV,QAEd,KACJ,CACA,IAAK,OAAQ,CACT,MAAMd,EACFZ,EAAKa,iBAAoC,mBACzCD,EAAUE,QACVF,EAAUA,EAAUE,OAAS,GAAGY,QAEpC,KACJ,EAER,CAnGIY,CAAYR,EAAW9B,EAAMQ,EACjC"}
1
+ {"version":3,"file":"useListNavigation.js","sources":["../../../../src/hooks/useListNavigation/useListNavigation.ts"],"sourcesContent":["import { type RefObject, useLayoutEffect } from \"react\";\n\ntype TimerHandle = { id: number | undefined };\ntype KeyBuffer = { keys: string } | undefined;\ntype Direction = \"prev\" | \"next\" | \"first\" | \"last\";\ninterface MoveDetails {\n event: KeyboardEvent;\n list: HTMLElement;\n currentFocus: HTMLButtonElement;\n}\ninterface ListDetails {\n list: HTMLElement;\n search: KeyBuffer;\n searchResetTimer: TimerHandle;\n}\ninterface SearchDetails extends ListDetails {\n key: string;\n}\ninterface EventDetails extends ListDetails {\n event: KeyboardEvent;\n}\n/**\n * Enten `ref` eller `element` må gis. `ref` brukes når listen alltid\n * er i DOM-en; `element` foretrekkes når elementet mountes/unmountes\n * dynamisk (f.eks. portalert via floating-ui), slik at listeneren\n * re-festes når elementet faktisk er tilgjengelig.\n */\ntype UseListNavigationProps<T> =\n | {\n ref: RefObject<T | null>;\n element?: never;\n }\n | {\n ref?: never;\n element: T | null;\n };\n\nexport function useListNavigation<T extends HTMLElement>({\n ref,\n element,\n}: UseListNavigationProps<T>): void {\n // Bruker `useLayoutEffect` slik at keydown-listeneren er på plass før\n // browseren maler neste frame. Det er viktig for konsumenter som\n // flytter fokus inn i lista i en `requestAnimationFrame`-callback\n // (som Select), ellers kan første tastetrykk gå tapt.\n useLayoutEffect(() => {\n // `ref?.current` leses inne i effekten — refen er fylt i commit-\n // fasen, og var `null` i render-tid for callere som passerer\n // `ref` (som Combobox).\n const list = element ?? ref?.current ?? null;\n if (!list) return;\n\n // `TimerHandle` er et muterbart objekt slik at `resetWhenIdle`\n // kan oppdatere `id` på samme referanse — `setTimeout`-handlen må\n // være delt på tvers av tastetrykk for at `clearTimeout` skal\n // kunne avbryte forrige timeout.\n const searchResetTimer: TimerHandle = { id: undefined };\n const search: KeyBuffer = { keys: \"\" }; // keypress buffer is an object to preserve state\n const handler = (event: KeyboardEvent) => {\n handleListKeyNav({ list, event, search, searchResetTimer });\n };\n\n list.addEventListener(\"keydown\", handler);\n return () => {\n list.removeEventListener(\"keydown\", handler);\n if (searchResetTimer.id !== undefined) {\n clearTimeout(searchResetTimer.id);\n }\n };\n }, [element, ref]);\n}\n\nfunction handleMoveTo(\n direction: Direction,\n { event, list, currentFocus }: MoveDetails,\n) {\n event.preventDefault();\n moveFocusTo(direction, list, currentFocus);\n}\n\nfunction handleListKeyNav({\n list,\n event,\n search,\n searchResetTimer,\n}: EventDetails) {\n const { key, target } = event;\n const currentFocus = target as HTMLButtonElement;\n\n const moveDetails = {\n event,\n list,\n currentFocus,\n };\n\n switch (key) {\n case \"ArrowUp\":\n case \"PageUp\":\n handleMoveTo(\"prev\", moveDetails);\n break;\n case \"ArrowDown\":\n case \"PageDown\":\n handleMoveTo(\"next\", moveDetails);\n break;\n case \"Home\":\n handleMoveTo(\"first\", moveDetails);\n break;\n case \"End\":\n handleMoveTo(\"last\", moveDetails);\n break;\n case \"Tab\":\n // in a standard select, tab does nothing in-menu\n event.preventDefault();\n break;\n case \"Enter\":\n case \" \":\n break;\n\n default:\n if (search !== undefined) {\n const searchResult = findItem({\n list,\n key,\n search,\n searchResetTimer,\n });\n if (searchResult) {\n searchResult.focus();\n }\n }\n break;\n }\n}\n\nfunction moveFocusTo(\n direction: Direction,\n list: HTMLElement,\n current: HTMLButtonElement,\n) {\n const thisOption = current;\n switch (direction) {\n case \"prev\": {\n const prevOption: HTMLButtonElement | null =\n thisOption &&\n (thisOption.previousElementSibling as HTMLButtonElement);\n if (prevOption) {\n prevOption.focus();\n }\n break;\n }\n case \"next\": {\n const nextOption: HTMLButtonElement | null =\n thisOption &&\n (thisOption.nextElementSibling as HTMLButtonElement);\n if (nextOption) {\n nextOption.focus();\n }\n break;\n }\n case \"first\": {\n const firstItem =\n list.querySelector<HTMLButtonElement>(`[role=\"option\"]`);\n if (firstItem) {\n firstItem.focus();\n }\n break;\n }\n case \"last\": {\n const listItems =\n list.querySelectorAll<HTMLButtonElement>(`[role=\"option\"]`);\n if (listItems.length) {\n listItems[listItems.length - 1].focus();\n }\n break;\n }\n }\n}\n\nfunction findItem({\n list,\n key,\n search,\n searchResetTimer,\n}: SearchDetails): HTMLButtonElement | null {\n const listItems = list.querySelectorAll(`[role=\"option\"]`);\n if (!listItems.length) return null;\n\n if (search) {\n search.keys = search.keys.concat(key);\n resetWhenIdle(search, searchResetTimer);\n\n for (let n = 0; n < listItems.length; n++) {\n const label = (listItems[n] as HTMLButtonElement).innerText;\n if (label && label.toLowerCase().indexOf(search.keys) === 0) {\n return listItems[n] as HTMLButtonElement;\n }\n }\n }\n\n return null;\n}\n\nfunction resetWhenIdle(search: KeyBuffer, timer: TimerHandle) {\n if (timer.id !== undefined) {\n clearTimeout(timer.id);\n timer.id = undefined;\n }\n timer.id = window.setTimeout(() => {\n if (search) {\n search.keys = \"\";\n }\n timer.id = undefined;\n }, 500);\n}\n"],"names":["useListNavigation","ref","element","useLayoutEffect","list","current","searchResetTimer","id","search","keys","handler","event","key","target","moveDetails","currentFocus","handleMoveTo","preventDefault","searchResult","listItems","querySelectorAll","length","concat","timer","clearTimeout","window","setTimeout","resetWhenIdle","n","label","innerText","toLowerCase","indexOf","findItem","focus","handleListKeyNav","addEventListener","removeEventListener","direction","thisOption","prevOption","previousElementSibling","nextOption","nextElementSibling","firstItem","querySelector","moveFocusTo"],"mappings":"wCAqCO,SAASA,GACZC,IAAAA,EACAC,QAAAA,IAMAC,EAAgB,KAIZ,MAAMC,EAAOF,GAAWD,GAAKI,SAAW,KACxC,IAAKD,EAAM,OAMX,MAAME,EAAgC,CAAEC,QAAI,GACtCC,EAAoB,CAAEC,KAAM,IAC5BC,EAAWC,KAsBzB,UACIP,KAAAA,EACAO,MAAAA,EACAH,OAAAA,EACAF,iBAAAA,IAEA,MAAQM,IAAAA,EAAKC,OAAAA,GAAWF,EAGlBG,EAAc,CAChBH,MAAAA,EACAP,KAAAA,EACAW,aALiBF,GAQrB,OAAQD,GACJ,IAAK,UACL,IAAK,SACDI,EAAa,OAAQF,GACrB,MACJ,IAAK,YACL,IAAK,WACDE,EAAa,OAAQF,GACrB,MACJ,IAAK,OACDE,EAAa,QAASF,GACtB,MACJ,IAAK,MACDE,EAAa,OAAQF,GACrB,MACJ,IAAK,MAEDH,EAAMM,iBACN,MACJ,IAAK,QACL,IAAK,IACD,MAEJ,QACI,QAAe,IAAXT,EAAsB,CACtB,MAAMU,EA0DtB,UACId,KAAAA,EACAQ,IAAAA,EACAJ,OAAAA,EACAF,iBAAAA,IAEA,MAAMa,EAAYf,EAAKgB,iBAAiB,mBACxC,IAAKD,EAAUE,OAAQ,OAAO,KAE9B,GAAIb,EAAQ,CACRA,EAAOC,KAAOD,EAAOC,KAAKa,OAAOV,GAczC,SAAuBJ,EAAmBe,QACrB,IAAbA,EAAMhB,KACNiB,aAAaD,EAAMhB,IACnBgB,EAAMhB,QAAK,GAEfgB,EAAMhB,GAAKkB,OAAOC,WAAW,KACrBlB,IACAA,EAAOC,KAAO,IAElBc,EAAMhB,QAAK,GACZ,IACP,CAxBQoB,CAAcnB,EAAQF,GAEtB,IAAA,IAASsB,EAAI,EAAGA,EAAIT,EAAUE,OAAQO,IAAK,CACvC,MAAMC,EAASV,EAAUS,GAAyBE,UAClD,GAAID,GAAsD,IAA7CA,EAAME,cAAcC,QAAQxB,EAAOC,MAC5C,OAAOU,EAAUS,EAEzB,CACJ,CAEA,OAAO,IACX,CAhFqCK,CAAS,CAC1B7B,KAAAA,EACAQ,IAAAA,EACAJ,OAAAA,EACAF,iBAAAA,IAEAY,GACAA,EAAagB,OAErB,EAGZ,CAzEYC,CAAiB,CAAE/B,KAAAA,EAAMO,MAAAA,EAAOH,OAAAA,EAAQF,iBAAAA,KAG5C,OAAAF,EAAKgC,iBAAiB,UAAW1B,GAC1B,KACHN,EAAKiC,oBAAoB,UAAW3B,QACR,IAAxBJ,EAAiBC,IACjBiB,aAAalB,EAAiBC,MAGvC,CAACL,EAASD,GACjB,CAEA,SAASe,EACLsB,GACE3B,MAAAA,EAAOP,KAAAA,EAAMW,aAAAA,IAEfJ,EAAMM,iBA0DV,SACIqB,EACAlC,EACAC,GAEA,MAAMkC,EAAalC,EACnB,OAAQiC,GACJ,IAAK,OAAQ,CACT,MAAME,EACFD,GACCA,EAAWE,uBACZD,GACAA,EAAWN,QAEf,KACJ,CACA,IAAK,OAAQ,CACT,MAAMQ,EACFH,GACCA,EAAWI,mBACZD,GACAA,EAAWR,QAEf,KACJ,CACA,IAAK,QAAS,CACV,MAAMU,EACFxC,EAAKyC,cAAiC,mBACtCD,GACAA,EAAUV,QAEd,KACJ,CACA,IAAK,OAAQ,CACT,MAAMf,EACFf,EAAKgB,iBAAoC,mBACzCD,EAAUE,QACVF,EAAUA,EAAUE,OAAS,GAAGa,QAEpC,KACJ,EAER,CAnGIY,CAAYR,EAAWlC,EAAMW,EACjC"}
@@ -1,2 +1,2 @@
1
- const r={color:{"@":{background:{page:"var(--jkl-color-background-page)",container:"var(--jkl-color-background-container)","container-accent":"var(--jkl-color-background-container-accent)",contrast:"var(--jkl-color-background-contrast)"},text:{default:"var(--jkl-color-text-default)",subdued:"var(--jkl-color-text-subdued)",accent:"var(--jkl-color-text-accent)","on-contrast":"var(--jkl-color-text-on-contrast)"},border:{default:"var(--jkl-color-border-default)",subdued:"var(--jkl-color-border-subdued)",strong:"var(--jkl-color-border-strong)"}},warning:{background:{page:"var(--jkl-color-warning-background-page)",container:"var(--jkl-color-warning-background-container)","container-accent":"var(--jkl-color-warning-background-container-accent)",contrast:"var(--jkl-color-warning-background-contrast)"},text:{default:"var(--jkl-color-warning-text-default)",subdued:"var(--jkl-color-warning-text-subdued)",accent:"var(--jkl-color-warning-text-accent)","on-contrast":"var(--jkl-color-warning-text-on-contrast)"},border:{default:"var(--jkl-color-warning-border-default)",subdued:"var(--jkl-color-warning-border-subdued)",strong:"var(--jkl-color-warning-border-strong)"}},success:{background:{page:"var(--jkl-color-success-background-page)",container:"var(--jkl-color-success-background-container)","container-accent":"var(--jkl-color-success-background-container-accent)",contrast:"var(--jkl-color-success-background-contrast)"},text:{default:"var(--jkl-color-success-text-default)",subdued:"var(--jkl-color-success-text-subdued)",accent:"var(--jkl-color-success-text-accent)","on-contrast":"var(--jkl-color-success-text-on-contrast)"},border:{default:"var(--jkl-color-success-border-default)",subdued:"var(--jkl-color-success-border-subdued)",strong:"var(--jkl-color-success-border-strong)"}},info:{background:{page:"var(--jkl-color-info-background-page)",container:"var(--jkl-color-info-background-container)","container-accent":"var(--jkl-color-info-background-container-accent)",contrast:"var(--jkl-color-info-background-contrast)"},text:{default:"var(--jkl-color-info-text-default)",subdued:"var(--jkl-color-info-text-subdued)",accent:"var(--jkl-color-info-text-accent)","on-contrast":"var(--jkl-color-info-text-on-contrast)"},border:{default:"var(--jkl-color-info-border-default)",subdued:"var(--jkl-color-info-border-subdued)",strong:"var(--jkl-color-info-border-strong)"}},error:{background:{page:"var(--jkl-color-error-background-page)",container:"var(--jkl-color-error-background-container)","container-accent":"var(--jkl-color-error-background-container-accent)",contrast:"var(--jkl-color-error-background-contrast)"},text:{default:"var(--jkl-color-error-text-default)",subdued:"var(--jkl-color-error-text-subdued)",accent:"var(--jkl-color-error-text-accent)","on-contrast":"var(--jkl-color-error-text-on-contrast)"},border:{default:"var(--jkl-color-error-border-default)",subdued:"var(--jkl-color-error-border-subdued)",strong:"var(--jkl-color-error-border-strong)"}}},unit:{0:"var(--jkl-unit-0)",10:"var(--jkl-unit-10)",15:"var(--jkl-unit-15)",20:"var(--jkl-unit-20)",25:"var(--jkl-unit-25)",30:"var(--jkl-unit-30)",35:"var(--jkl-unit-35)",40:"var(--jkl-unit-40)",50:"var(--jkl-unit-50)",60:"var(--jkl-unit-60)",70:"var(--jkl-unit-70)",80:"var(--jkl-unit-80)",90:"var(--jkl-unit-90)",100:"var(--jkl-unit-100)",130:"var(--jkl-unit-130)",210:"var(--jkl-unit-210)",base:"var(--jkl-unit-base)","02":"var(--jkl-unit-02)","05":"var(--jkl-unit-05)"},spacing:{0:"var(--jkl-spacing-0)",2:"var(--jkl-spacing-2)",4:"var(--jkl-spacing-4)",8:"var(--jkl-spacing-8)",12:"var(--jkl-spacing-12)",16:"var(--jkl-spacing-16)",24:"var(--jkl-spacing-24)",32:"var(--jkl-spacing-32)",40:"var(--jkl-spacing-40)",64:"var(--jkl-spacing-64)",104:"var(--jkl-spacing-104)",168:"var(--jkl-spacing-168)",none:"var(--jkl-spacing-none)","2xs":"var(--jkl-spacing-2xs)",xs:"var(--jkl-spacing-xs)",s:"var(--jkl-spacing-s)",m:"var(--jkl-spacing-m)",l:"var(--jkl-spacing-l)",xl:"var(--jkl-spacing-xl)","2xl":"var(--jkl-spacing-2xl)"},border:{width:{1:"var(--jkl-border-width-1)",2:"var(--jkl-border-width-2)",3:"var(--jkl-border-width-3)"},radius:{none:"var(--jkl-border-radius-none)",xs:"var(--jkl-border-radius-xs)",s:"var(--jkl-border-radius-s)",m:"var(--jkl-border-radius-m)",l:"var(--jkl-border-radius-l)",full:"var(--jkl-border-radius-full)"}},breakpoint:{small:"var(--jkl-breakpoint-small)",medium:"var(--jkl-breakpoint-medium)",large:"var(--jkl-breakpoint-large)",xl:"var(--jkl-breakpoint-xl)"},motion:{timing:{energetic:"var(--jkl-motion-timing-energetic)",snappy:"var(--jkl-motion-timing-snappy)",productive:"var(--jkl-motion-timing-productive)",polite:"var(--jkl-motion-timing-polite)",expressive:"var(--jkl-motion-timing-expressive)",lazy:"var(--jkl-motion-timing-lazy)"},easing:{standard:"var(--jkl-motion-easing-standard)",entrance:"var(--jkl-motion-easing-entrance)",exit:"var(--jkl-motion-easing-exit)",easeInBounceOut:"var(--jkl-motion-easing-ease-in-bounce-out)",focus:"var(--jkl-motion-easing-focus)"}},font:{size:{1:"var(--jkl-font-size-1)",2:"var(--jkl-font-size-2)",3:"var(--jkl-font-size-3)",4:"var(--jkl-font-size-4)",5:"var(--jkl-font-size-5)",6:"var(--jkl-font-size-6)",7:"var(--jkl-font-size-7)",8:"var(--jkl-font-size-8)",9:"var(--jkl-font-size-9)",10:"var(--jkl-font-size-10)"},weight:{normal:"var(--jkl-font-weight-normal)",bold:"var(--jkl-font-weight-bold)"},family:{regular:"var(--jkl-font-family-regular)",display:"var(--jkl-font-family-display)",mono:"var(--jkl-font-family-mono)"}},lineHeight:{flush:"var(--jkl-line-height-flush)",tight:"var(--jkl-line-height-tight)",relaxed:"var(--jkl-line-height-relaxed)"},textStyle:{title:"var(--jkl-text-style-title)","title-small":"var(--jkl-text-style-title-small)","heading-1":"var(--jkl-text-style-heading-1)","heading-2":"var(--jkl-text-style-heading-2)","heading-3":"var(--jkl-text-style-heading-3)","heading-4":"var(--jkl-text-style-heading-4)","heading-5":"var(--jkl-text-style-heading-5)","paragraph-large":"var(--jkl-text-style-paragraph-large)","paragraph-medium":"var(--jkl-text-style-paragraph-medium)","paragraph-small":"var(--jkl-text-style-paragraph-small)","text-large":"var(--jkl-text-style-text-large)","text-medium":"var(--jkl-text-style-text-medium)","text-small":"var(--jkl-text-style-text-small)","text-micro":"var(--jkl-text-style-text-micro)"}};export{r as default};
1
+ const r={color:{"@":{background:{page:"var(--jkl-color-background-page)",container:"var(--jkl-color-background-container)","container-accent":"var(--jkl-color-background-container-accent)",contrast:"var(--jkl-color-background-contrast)"},text:{default:"var(--jkl-color-text-default)",subdued:"var(--jkl-color-text-subdued)",accent:"var(--jkl-color-text-accent)","on-contrast":"var(--jkl-color-text-on-contrast)"},border:{default:"var(--jkl-color-border-default)",subdued:"var(--jkl-color-border-subdued)",strong:"var(--jkl-color-border-strong)"}},warning:{background:{page:"var(--jkl-color-warning-background-page)",container:"var(--jkl-color-warning-background-container)","container-accent":"var(--jkl-color-warning-background-container-accent)",contrast:"var(--jkl-color-warning-background-contrast)"},text:{default:"var(--jkl-color-warning-text-default)",subdued:"var(--jkl-color-warning-text-subdued)",accent:"var(--jkl-color-warning-text-accent)","on-contrast":"var(--jkl-color-warning-text-on-contrast)"},border:{default:"var(--jkl-color-warning-border-default)",subdued:"var(--jkl-color-warning-border-subdued)",strong:"var(--jkl-color-warning-border-strong)"}},success:{background:{page:"var(--jkl-color-success-background-page)",container:"var(--jkl-color-success-background-container)","container-accent":"var(--jkl-color-success-background-container-accent)",contrast:"var(--jkl-color-success-background-contrast)"},text:{default:"var(--jkl-color-success-text-default)",subdued:"var(--jkl-color-success-text-subdued)",accent:"var(--jkl-color-success-text-accent)","on-contrast":"var(--jkl-color-success-text-on-contrast)"},border:{default:"var(--jkl-color-success-border-default)",subdued:"var(--jkl-color-success-border-subdued)",strong:"var(--jkl-color-success-border-strong)"}},info:{background:{page:"var(--jkl-color-info-background-page)",container:"var(--jkl-color-info-background-container)","container-accent":"var(--jkl-color-info-background-container-accent)",contrast:"var(--jkl-color-info-background-contrast)"},text:{default:"var(--jkl-color-info-text-default)",subdued:"var(--jkl-color-info-text-subdued)",accent:"var(--jkl-color-info-text-accent)","on-contrast":"var(--jkl-color-info-text-on-contrast)"},border:{default:"var(--jkl-color-info-border-default)",subdued:"var(--jkl-color-info-border-subdued)",strong:"var(--jkl-color-info-border-strong)"}},error:{background:{page:"var(--jkl-color-error-background-page)",container:"var(--jkl-color-error-background-container)","container-accent":"var(--jkl-color-error-background-container-accent)",contrast:"var(--jkl-color-error-background-contrast)"},text:{default:"var(--jkl-color-error-text-default)",subdued:"var(--jkl-color-error-text-subdued)",accent:"var(--jkl-color-error-text-accent)","on-contrast":"var(--jkl-color-error-text-on-contrast)"},border:{default:"var(--jkl-color-error-border-default)",subdued:"var(--jkl-color-error-border-subdued)",strong:"var(--jkl-color-error-border-strong)"}}},unit:{0:"var(--jkl-unit-0)",10:"var(--jkl-unit-10)",15:"var(--jkl-unit-15)",20:"var(--jkl-unit-20)",25:"var(--jkl-unit-25)",30:"var(--jkl-unit-30)",35:"var(--jkl-unit-35)",40:"var(--jkl-unit-40)",50:"var(--jkl-unit-50)",60:"var(--jkl-unit-60)",70:"var(--jkl-unit-70)",80:"var(--jkl-unit-80)",90:"var(--jkl-unit-90)",100:"var(--jkl-unit-100)",130:"var(--jkl-unit-130)",210:"var(--jkl-unit-210)",base:"var(--jkl-unit-base)","02":"var(--jkl-unit-02)","05":"var(--jkl-unit-05)"},spacing:{0:"var(--jkl-spacing-0)",2:"var(--jkl-spacing-2)",4:"var(--jkl-spacing-4)",8:"var(--jkl-spacing-8)",12:"var(--jkl-spacing-12)",16:"var(--jkl-spacing-16)",24:"var(--jkl-spacing-24)",32:"var(--jkl-spacing-32)",40:"var(--jkl-spacing-40)",64:"var(--jkl-spacing-64)",104:"var(--jkl-spacing-104)",168:"var(--jkl-spacing-168)",none:"var(--jkl-spacing-none)","2xs":"var(--jkl-spacing-2xs)",xs:"var(--jkl-spacing-xs)",s:"var(--jkl-spacing-s)",m:"var(--jkl-spacing-m)",l:"var(--jkl-spacing-l)",xl:"var(--jkl-spacing-xl)","2xl":"var(--jkl-spacing-2xl)"},border:{width:{1:"var(--jkl-border-width-1)",2:"var(--jkl-border-width-2)",3:"var(--jkl-border-width-3)"},radius:{none:"var(--jkl-border-radius-none)",xs:"var(--jkl-border-radius-xs)",s:"var(--jkl-border-radius-s)",m:"var(--jkl-border-radius-m)",l:"var(--jkl-border-radius-l)",full:"var(--jkl-border-radius-full)"}},breakpoint:{small:"0",medium:"680px",large:"1200px",xl:"1600px"},motion:{timing:{energetic:"var(--jkl-motion-timing-energetic)",snappy:"var(--jkl-motion-timing-snappy)",productive:"var(--jkl-motion-timing-productive)",polite:"var(--jkl-motion-timing-polite)",expressive:"var(--jkl-motion-timing-expressive)",lazy:"var(--jkl-motion-timing-lazy)"},easing:{standard:"var(--jkl-motion-easing-standard)",entrance:"var(--jkl-motion-easing-entrance)",exit:"var(--jkl-motion-easing-exit)",easeInBounceOut:"var(--jkl-motion-easing-ease-in-bounce-out)",focus:"var(--jkl-motion-easing-focus)"}},font:{size:{1:"var(--jkl-font-size-1)",2:"var(--jkl-font-size-2)",3:"var(--jkl-font-size-3)",4:"var(--jkl-font-size-4)",5:"var(--jkl-font-size-5)",6:"var(--jkl-font-size-6)",7:"var(--jkl-font-size-7)",8:"var(--jkl-font-size-8)",9:"var(--jkl-font-size-9)",10:"var(--jkl-font-size-10)"},weight:{normal:"var(--jkl-font-weight-normal)",bold:"var(--jkl-font-weight-bold)"},family:{regular:"var(--jkl-font-family-regular)",display:"var(--jkl-font-family-display)",mono:"var(--jkl-font-family-mono)"}},lineHeight:{flush:"var(--jkl-line-height-flush)",tight:"var(--jkl-line-height-tight)",relaxed:"var(--jkl-line-height-relaxed)"},textStyle:{title:"var(--jkl-text-style-title)","title-small":"var(--jkl-text-style-title-small)","heading-1":"var(--jkl-text-style-heading-1)","heading-2":"var(--jkl-text-style-heading-2)","heading-3":"var(--jkl-text-style-heading-3)","heading-4":"var(--jkl-text-style-heading-4)","heading-5":"var(--jkl-text-style-heading-5)","paragraph-large":"var(--jkl-text-style-paragraph-large)","paragraph-medium":"var(--jkl-text-style-paragraph-medium)","paragraph-small":"var(--jkl-text-style-paragraph-small)","text-large":"var(--jkl-text-style-text-large)","text-medium":"var(--jkl-text-style-text-medium)","text-small":"var(--jkl-text-style-text-small)","text-micro":"var(--jkl-text-style-text-micro)"}};export{r as default};
2
2
  //# sourceMappingURL=tokens.js.map