@fremtind/jokul 6.0.0-next.3 → 6.0.0-next.5

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 (79) hide show
  1. package/build/build-stats.html +1 -1
  2. package/build/cjs/components/autosuggest/Autosuggest.cjs.map +1 -1
  3. package/build/cjs/components/autosuggest/Autosuggest.d.cts +5 -0
  4. package/build/cjs/components/combobox/Combobox.cjs.map +1 -1
  5. package/build/cjs/components/combobox/Combobox.d.cts +4 -0
  6. package/build/cjs/components/flex/Flex.cjs +1 -1
  7. package/build/cjs/components/flex/Flex.cjs.map +1 -1
  8. package/build/cjs/components/flex/types.cjs +1 -1
  9. package/build/cjs/components/flex/types.cjs.map +1 -1
  10. package/build/cjs/components/flex/types.d.cts +36 -26
  11. package/build/cjs/components/image/Image.cjs +1 -1
  12. package/build/cjs/components/image/Image.cjs.map +1 -1
  13. package/build/cjs/components/number-input/NumberInput.cjs.map +1 -1
  14. package/build/cjs/components/segmented-control/SegmentedControl.cjs +1 -1
  15. package/build/cjs/components/segmented-control/SegmentedControl.cjs.map +1 -1
  16. package/build/cjs/components/select/Option.cjs.map +1 -1
  17. package/build/cjs/components/select/Select.cjs.map +1 -1
  18. package/build/cjs/components/select/Select.d.cts +1 -1
  19. package/build/cjs/components/select/utils.cjs.map +1 -1
  20. package/build/cjs/components/table/stories/assets/table-data.cjs +2 -0
  21. package/build/cjs/components/table/stories/assets/table-data.cjs.map +1 -0
  22. package/build/cjs/components/table/stories/assets/table-data.d.cts +8 -0
  23. package/build/es/components/autosuggest/Autosuggest.d.ts +5 -0
  24. package/build/es/components/autosuggest/Autosuggest.js.map +1 -1
  25. package/build/es/components/combobox/Combobox.d.ts +4 -0
  26. package/build/es/components/combobox/Combobox.js.map +1 -1
  27. package/build/es/components/flex/Flex.js +1 -1
  28. package/build/es/components/flex/Flex.js.map +1 -1
  29. package/build/es/components/flex/types.d.ts +36 -26
  30. package/build/es/components/flex/types.js +1 -1
  31. package/build/es/components/flex/types.js.map +1 -1
  32. package/build/es/components/image/Image.js +1 -1
  33. package/build/es/components/image/Image.js.map +1 -1
  34. package/build/es/components/number-input/NumberInput.js.map +1 -1
  35. package/build/es/components/segmented-control/SegmentedControl.js +1 -1
  36. package/build/es/components/segmented-control/SegmentedControl.js.map +1 -1
  37. package/build/es/components/select/Option.js.map +1 -1
  38. package/build/es/components/select/Select.d.ts +1 -1
  39. package/build/es/components/select/Select.js.map +1 -1
  40. package/build/es/components/select/utils.js.map +1 -1
  41. package/build/es/components/table/stories/assets/table-data.d.ts +8 -0
  42. package/build/es/components/table/stories/assets/table-data.js +2 -0
  43. package/build/es/components/table/stories/assets/table-data.js.map +1 -0
  44. package/codemods/CODEMODS.md +115 -83
  45. package/codemods/__tests__/import-paths.test.mjs +107 -1
  46. package/codemods/import-paths.mjs +5 -1
  47. package/codemods/transforms/select.mjs +237 -0
  48. package/package.json +1 -2
  49. package/styles/base.css +4 -3
  50. package/styles/base.min.css +1 -1
  51. package/styles/components/countdown/countdown.css +2 -2
  52. package/styles/components/countdown/countdown.min.css +1 -1
  53. package/styles/components/feedback/feedback.css +2 -2
  54. package/styles/components/feedback/feedback.min.css +1 -1
  55. package/styles/components/file-input/file-input.css +9 -9
  56. package/styles/components/file-input/file-input.min.css +1 -1
  57. package/styles/components/flex/flex.css +16 -1343
  58. package/styles/components/flex/flex.min.css +1 -1
  59. package/styles/components/flex/flex.scss +14 -280
  60. package/styles/components/input-group/input-group.css +2 -2
  61. package/styles/components/input-group/input-group.min.css +1 -1
  62. package/styles/components/loader/loader.css +6 -6
  63. package/styles/components/loader/loader.min.css +1 -1
  64. package/styles/components/loader/skeleton-loader.css +3 -3
  65. package/styles/components/loader/skeleton-loader.min.css +1 -1
  66. package/styles/components/message/message.css +2 -2
  67. package/styles/components/message/message.min.css +1 -1
  68. package/styles/components/progress-bar/progress-bar.css +1 -1
  69. package/styles/components/progress-bar/progress-bar.min.css +1 -1
  70. package/styles/components/segmented-control/segmented-control.css +2 -2
  71. package/styles/components/segmented-control/segmented-control.min.css +1 -1
  72. package/styles/components/system-message/system-message.css +2 -2
  73. package/styles/components/system-message/system-message.min.css +1 -1
  74. package/styles/components/toast/toast.css +4 -4
  75. package/styles/components/toast/toast.min.css +1 -1
  76. package/styles/components.css +37 -1367
  77. package/styles/components.min.css +2 -2
  78. package/styles/theme/_tokens.scss +2 -1
  79. package/styles/theme/brands/dnb/_color-scheme.scss +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"Autosuggest.cjs","sources":["../../../../src/components/autosuggest/Autosuggest.tsx"],"sourcesContent":["import type { StateChangeOptions } from \"downshift\";\nimport React, { useEffect, useState } from \"react\";\nimport BaseAutosuggest from \"./BaseAutosuggest.js\";\nimport type { AutosuggestProps } from \"./types.js\";\nimport { filter } from \"./utils.js\";\n\nexport const Autosuggest = ({\n allItems,\n onChange = () => {\n /* default noop */\n },\n onConfirm = () => {\n /* noop */\n },\n onInputValueChange,\n onStateChange,\n value,\n isOpen,\n ...rest\n}: AutosuggestProps): JSX.Element => {\n const [hits, setHits] = useState(allItems);\n\n useEffect(() => setHits(allItems), [allItems]);\n\n const handleStateChange = (changes: StateChangeOptions<string>) => {\n if (onStateChange) {\n onStateChange(changes);\n }\n\n if (changes.selectedItem !== undefined) {\n onChange(changes.selectedItem || \"\");\n } else if (changes.inputValue) {\n setHits(filter(allItems, changes.inputValue));\n }\n };\n\n const itemToString = (item: string | null) => (item ? item : \"\");\n\n return (\n <BaseAutosuggest\n {...rest}\n items={hits}\n itemToString={itemToString}\n onConfirm={onConfirm}\n downshiftProps={{\n selectedItem: value,\n onInputValueChange,\n onStateChange: handleStateChange,\n isOpen,\n }}\n />\n );\n};\n"],"names":["allItems","onChange","onConfirm","onInputValueChange","onStateChange","value","isOpen","rest","hits","setHits","useState","useEffect","jsx","BaseAutosuggest","items","itemToString","item","downshiftProps","selectedItem","changes","inputValue","filter"],"mappings":"wNAM2B,EACvBA,SAAAA,EACAC,SAAAA,EAAW,OAGXC,UAAAA,EAAY,OAGZC,mBAAAA,EACAC,cAAAA,EACAC,MAAAA,EACAC,OAAAA,KACGC,MAEH,MAAOC,EAAMC,GAAWC,EAAAA,SAASV,GAEjCW,EAAAA,UAAU,IAAMF,EAAQT,GAAW,CAACA,IAgBpC,OACIY,EAAAA,IAACC,EAAA,IACON,EACJO,MAAON,EACPO,aANcC,GAAyBA,GAAc,GAOrDd,UAAAA,EACAe,eAAgB,CACZC,aAAcb,EACdF,mBAAAA,EACAC,cAvBee,IACnBf,GACAA,EAAce,QAGW,IAAzBA,EAAQD,aACRjB,EAASkB,EAAQD,cAAgB,IAC1BC,EAAQC,YACfX,EAAQY,EAAAA,OAAOrB,EAAUmB,EAAQC,cAgB7Bd,OAAAA"}
1
+ {"version":3,"file":"Autosuggest.cjs","sources":["../../../../src/components/autosuggest/Autosuggest.tsx"],"sourcesContent":["import type { StateChangeOptions } from \"downshift\";\nimport React, { useEffect, useState } from \"react\";\nimport BaseAutosuggest from \"./BaseAutosuggest.js\";\nimport type { AutosuggestProps } from \"./types.js\";\nimport { filter } from \"./utils.js\";\n\n/**\n * @deprecated Denne komponenten er utdatert, og vil fjernes i en kommende oppdatering.\n * Bruk heller Select, eller en kombinasjon av Select og TextInput. Se mer om hvordan\n * du gjør dette i portalen: https://jokul.fremtind.no/monster/eget-alternativ\n */\nexport const Autosuggest = ({\n allItems,\n onChange = () => {\n /* default noop */\n },\n onConfirm = () => {\n /* noop */\n },\n onInputValueChange,\n onStateChange,\n value,\n isOpen,\n ...rest\n}: AutosuggestProps): JSX.Element => {\n const [hits, setHits] = useState(allItems);\n\n useEffect(() => setHits(allItems), [allItems]);\n\n const handleStateChange = (changes: StateChangeOptions<string>) => {\n if (onStateChange) {\n onStateChange(changes);\n }\n\n if (changes.selectedItem !== undefined) {\n onChange(changes.selectedItem || \"\");\n } else if (changes.inputValue) {\n setHits(filter(allItems, changes.inputValue));\n }\n };\n\n const itemToString = (item: string | null) => (item ? item : \"\");\n\n return (\n <BaseAutosuggest\n {...rest}\n items={hits}\n itemToString={itemToString}\n onConfirm={onConfirm}\n downshiftProps={{\n selectedItem: value,\n onInputValueChange,\n onStateChange: handleStateChange,\n isOpen,\n }}\n />\n );\n};\n"],"names":["allItems","onChange","onConfirm","onInputValueChange","onStateChange","value","isOpen","rest","hits","setHits","useState","useEffect","jsx","BaseAutosuggest","items","itemToString","item","downshiftProps","selectedItem","changes","inputValue","filter"],"mappings":"wNAW2B,EACvBA,SAAAA,EACAC,SAAAA,EAAW,OAGXC,UAAAA,EAAY,OAGZC,mBAAAA,EACAC,cAAAA,EACAC,MAAAA,EACAC,OAAAA,KACGC,MAEH,MAAOC,EAAMC,GAAWC,EAAAA,SAASV,GAEjCW,EAAAA,UAAU,IAAMF,EAAQT,GAAW,CAACA,IAgBpC,OACIY,EAAAA,IAACC,EAAA,IACON,EACJO,MAAON,EACPO,aANcC,GAAyBA,GAAc,GAOrDd,UAAAA,EACAe,eAAgB,CACZC,aAAcb,EACdF,mBAAAA,EACAC,cAvBee,IACnBf,GACAA,EAAce,QAGW,IAAzBA,EAAQD,aACRjB,EAASkB,EAAQD,cAAgB,IAC1BC,EAAQC,YACfX,EAAQY,EAAAA,OAAOrB,EAAUmB,EAAQC,cAgB7Bd,OAAAA"}
@@ -1,2 +1,7 @@
1
1
  import { AutosuggestProps } from './types.cjs';
2
+ /**
3
+ * @deprecated Denne komponenten er utdatert, og vil fjernes i en kommende oppdatering.
4
+ * Bruk heller Select, eller en kombinasjon av Select og TextInput. Se mer om hvordan
5
+ * du gjør dette i portalen: https://jokul.fremtind.no/monster/eget-alternativ
6
+ */
2
7
  export declare const Autosuggest: ({ allItems, onChange, onConfirm, onInputValueChange, onStateChange, value, isOpen, ...rest }: AutosuggestProps) => JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"Combobox.cjs","sources":["../../../../src/components/combobox/Combobox.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, {\n type FC,\n type FocusEvent,\n type KeyboardEvent,\n type MouseEvent,\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 type { ValuePair } from \"../../utilities/valuePair.js\";\nimport { Chip } from \"../chip/Chip.js\";\nimport { IconButton } from \"../icon-button/IconButton.js\";\nimport { CheckIcon } from \"../icon/icons/CheckIcon.js\";\nimport { ArrowVerticalAnimated } from \"../icon/icons/animated/ArrowVerticalAnimated.js\";\nimport { InputGroup } from \"../input-group/InputGroup.js\";\nimport { Tooltip } from \"../tooltip/Tooltip.js\";\nimport { TooltipContent } from \"../tooltip/TooltipContent.js\";\nimport { TooltipTrigger } from \"../tooltip/TooltipTrigger.js\";\nimport type { ComboboxProps, ComboboxValuePair } from \"./types.js\";\n\nexport function getComboboxValuePair(\n item: string | ComboboxValuePair,\n): ComboboxValuePair {\n return typeof item === \"string\" ? { value: item, label: item } : item;\n}\n\nexport const Combobox: FC<ComboboxProps> = (props) => {\n const {\n \"data-size\": dataSize,\n id,\n placeholder,\n items,\n onChange,\n onFocus,\n onBlur,\n value,\n label,\n noMatchingOption,\n labelProps,\n helpLabel,\n errorLabel,\n width,\n name,\n className,\n invalid,\n description,\n hasTagHover,\n tooltip,\n } = props;\n const listId = useId(id || \"jkl-combobox\", { generateSuffix: !id });\n const labelId = `${listId}_label`;\n const buttonId = `${listId}_button`;\n const inputId = `${listId}_search-input`;\n\n const [selectedValue, setSelectedValue] = useState<\n Array<ComboboxValuePair>\n >(value || []);\n const [showMenu, setShowMenu] = useState<boolean>(false);\n const [searchValue, setSearchValue] = useState<string>(\"\");\n const [noResults, setNoResults] = useState(false);\n const [marked, setMarked] = useState<boolean>(false);\n\n const searchRef = useRef<HTMLInputElement>(null);\n const inputRef = useRef<HTMLDivElement>(null);\n const focusInsideRef = useRef(false);\n\n useEffect(() => {\n setSearchValue(\"\");\n if (showMenu && searchRef.current) {\n searchRef.current.focus();\n }\n }, [showMenu]);\n\n useEffect(() => {\n setSelectedValue((prev) => value || prev);\n }, [value]);\n\n // Funksjon for å stile valgt element\n const isSelected = (option: ValuePair) => {\n if (!selectedValue) {\n return false;\n }\n\n return selectedValue.some((value) => value.value === option.value);\n };\n\n // Fjerne ett eller flere valg\n const removeOption = useCallback(\n (option: string) => {\n return selectedValue.filter((value) => value.value !== option);\n },\n [selectedValue],\n );\n\n const onTagRemove = useCallback(\n (\n e:\n | React.MouseEvent<HTMLButtonElement, globalThis.MouseEvent>\n | React.KeyboardEvent<HTMLInputElement>,\n option: string,\n ) => {\n const newValue = removeOption(option);\n setSelectedValue(newValue);\n onChange({\n type: \"change\",\n target: { name, value: option, selectedOptions: newValue },\n });\n e.stopPropagation();\n\n if (newValue.length === 0) {\n setMarked(false);\n }\n },\n [removeOption, onChange, name],\n );\n\n // Håndtere valgt verdi i listen\n const onItemClick = useCallback(\n (option: string) => {\n let newValue: Array<ValuePair>;\n\n if (selectedValue.some((value) => value.value === option)) {\n newValue = removeOption(option);\n } else {\n const item = items.find((i) => i.value === option);\n newValue = [...selectedValue, item as ValuePair];\n }\n searchRef.current?.focus();\n setSelectedValue(newValue);\n onChange({\n type: \"change\",\n target: { name, value: option, selectedOptions: newValue },\n });\n },\n [selectedValue, onChange, name, removeOption, items],\n );\n\n // Funksjon for søk\n const onSearch = (e: {\n target: { value: React.SetStateAction<string> };\n }) => {\n searchRef.current?.focus();\n setShowMenu(true);\n setSearchValue(e.target.value);\n };\n\n const options = useMemo(() => {\n if (!searchValue) {\n return items;\n }\n\n const filteredOptions = items.filter(\n (option) =>\n option.label.toLowerCase().indexOf(searchValue.toLowerCase()) >=\n 0,\n );\n\n setNoResults(filteredOptions.length === 0);\n\n return filteredOptions;\n }, [searchValue, items]);\n\n // Det første elementet i listen skal være aktivt fram til brukeren klikker på noe annet\n const [activeDescendant, setActiveDescendant] = useState<\n string | undefined\n >(options[0]?.value ? `${listId}-${options[0]?.value}` : undefined);\n\n // Håndtere arrow-state\n const isPointingDown = !showMenu;\n\n // Lukk meny med ESC\n useEffect(() => {\n const handleEscape = (e: globalThis.KeyboardEvent) => {\n if (e.key === \"Escape\" && showMenu) {\n setShowMenu(false);\n }\n };\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"keydown\", handleEscape);\n }\n return () => {\n if (typeof window !== \"undefined\" && showMenu) {\n window.removeEventListener(\"keydown\", handleEscape);\n }\n };\n }, [showMenu]);\n\n // Fokushåndtering\n const handleFocusPlacement = useCallback((isOpen: boolean) => {\n if (isOpen) {\n if (searchRef.current) {\n searchRef.current.focus();\n }\n } else {\n if (focusInsideRef.current && inputRef.current) {\n inputRef.current.focus();\n }\n }\n }, []);\n\n const handleFocus = useCallback(() => {\n if (!focusInsideRef.current) {\n if (onFocus) {\n onFocus({\n type: \"change\",\n target: {\n name,\n value: selectedValue?.[0].value || \"\",\n selectedOptions: selectedValue,\n },\n });\n }\n focusInsideRef.current = true;\n setShowMenu(true);\n }\n }, [onFocus, selectedValue, name]);\n\n const [dropdownRef] = useAnimatedHeight<HTMLDivElement>(showMenu, {\n onFirstVisible: handleFocusPlacement,\n onTransitionEnd: handleFocusPlacement,\n });\n\n useListNavigation({ ref: dropdownRef });\n\n const componentRootElementRef = useRef<HTMLDivElement>(null);\n\n const handleBlur = useCallback(\n (\n e: FocusEvent<\n HTMLDivElement | HTMLInputElement | HTMLButtonElement\n >,\n ) => {\n const componentRootElement = componentRootElementRef.current;\n const nextFocusIsInsideComponent = componentRootElement?.contains(\n e.relatedTarget as Node,\n );\n if (!nextFocusIsInsideComponent) {\n setSearchValue(\"\");\n\n if (onBlur) {\n onBlur({\n type: \"blur\",\n target: {\n name,\n value: selectedValue?.[0]?.value || \"\",\n selectedOptions: selectedValue,\n },\n });\n inputRef.current?.dispatchEvent(\n new Event(\"focusout\", { bubbles: true }),\n );\n }\n focusInsideRef.current = false;\n setShowMenu(false);\n }\n },\n [onBlur, name, selectedValue],\n );\n\n const handleMouseOver = useCallback((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 // Tastaturnavigasjon\n const handleSearchOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n e.stopPropagation();\n const listElement = dropdownRef.current;\n if (listElement) {\n listElement\n .querySelector<HTMLButtonElement>('[role=\"option\"]')\n ?.focus();\n }\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n setShowMenu(false);\n }\n\n if ((e.metaKey && e.key === \"a\") || (e.ctrlKey && e.key === \"a\")) {\n e.preventDefault();\n e.stopPropagation();\n const updatedSelectedValue = selectedValue.map((item) => ({\n ...item,\n isMarked: true,\n }));\n setMarked(true);\n setSelectedValue(updatedSelectedValue);\n } else if (e.key === \"Backspace\") {\n e.stopPropagation();\n setMarked(false);\n\n // Sjekk om selectedValue er markert\n const selectedValueIsMarked = selectedValue.some(\n (item) => item.isMarked,\n );\n\n if (selectedValueIsMarked) {\n const updatedSelectedValue = selectedValue.filter(\n (item) => !item.isMarked,\n );\n setSelectedValue(updatedSelectedValue);\n setSearchValue(\"\");\n } else if (selectedValue.length > 0 && searchValue === \"\") {\n // Hvis ingen items er markert, fjern siste valgte item\n onTagRemove(\n e,\n selectedValue[selectedValue.length - 1].value,\n );\n }\n }\n },\n [selectedValue, searchValue, dropdownRef, onTagRemove],\n );\n\n const handleOptionOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === \"Tab\") {\n if (searchRef.current) {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.shiftKey) {\n searchRef.current.focus();\n } else {\n setShowMenu(false);\n searchRef.current.focus();\n }\n }\n } else if (e.key === \"ArrowUp\") {\n if (dropdownRef.current && searchRef.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 searchRef.current\n ) {\n searchRef.current.focus();\n }\n }\n }\n },\n [dropdownRef],\n );\n\n const hasSelection = selectedValue.length >= 1;\n\n const renderSelectedOption = useCallback(\n (option: ComboboxValuePair) => (\n <Chip\n key={option.value}\n data-testid=\"jkl-chip\"\n aria-label={`Fjern ${option.tagLabel}`}\n className={`jkl-combobox__selected-option ${\n marked && \"jkl-combobox__selected-option--marked\"\n }`}\n variant=\"input\"\n onClick={(e) => {\n if (searchRef.current) {\n searchRef.current.focus();\n }\n onTagRemove(e, option.value);\n }}\n onBlur={handleBlur}\n >\n {option.tagLabel ? option.tagLabel : option.label}\n </Chip>\n ),\n [handleBlur, onTagRemove, marked],\n );\n\n return (\n <InputGroup\n label={label}\n id={inputId}\n ref={componentRootElementRef}\n data-testid=\"jkl-combobox\"\n data-size={dataSize}\n className={clsx(\"jkl-combobox\", className, {\n \"jkl-combobox--invalid\": !!errorLabel || invalid,\n \"jkl-combobox--menu-open\": showMenu,\n \"jkl-combobox--menu-closed\": !showMenu && hasSelection,\n })}\n labelProps={{\n id: labelId,\n ...labelProps,\n }}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n description={description}\n tooltip={tooltip}\n render={(inputProps) => (\n <div\n className={clsx(\"jkl-combobox__wrapper\", {\n \"jkl-combobox__wrapper--active-value\": hasSelection,\n })}\n style={{ width }}\n tabIndex={-1}\n onFocus={handleFocus}\n onBlur={handleBlur}\n data-invalid={!!errorLabel || invalid}\n >\n <div\n className=\"jkl-combobox__chips\"\n data-testid=\"jkl-combobox__chips\"\n >\n {selectedValue\n .map(getComboboxValuePair)\n .map((option) => {\n return hasTagHover ? (\n <Tooltip key={option.value}>\n <TooltipTrigger>\n {renderSelectedOption(option)}\n </TooltipTrigger>\n <TooltipContent>\n {option.label}\n </TooltipContent>\n </Tooltip>\n ) : (\n renderSelectedOption(option)\n );\n })}\n <input\n {...inputProps}\n className=\"jkl-combobox__search-input\"\n onChange={onSearch}\n data-testid=\"jkl-combobox__search-input\"\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleSearchOnKeyDown}\n value={searchValue}\n ref={searchRef}\n aria-controls={listId}\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded={showMenu}\n placeholder={\n selectedValue.length > 0 ? \"\" : placeholder\n }\n autoComplete=\"off\"\n />\n </div>\n\n <div\n className=\"jkl-combobox__menu\"\n // biome-ignore lint/a11y/useSemanticElements: Dette er en reimplementering av en liste\n role=\"listbox\"\n ref={dropdownRef}\n id={listId}\n aria-labelledby={labelId}\n aria-multiselectable=\"true\"\n aria-activedescendant={activeDescendant}\n onFocus={handleFocus}\n onBlur={handleBlur}\n tabIndex={-1}\n >\n {options.map((option, i) => (\n <button\n key={`${listId}-${option.value}`}\n type=\"button\"\n id={`${listId}__${option.value}`}\n aria-selected={isSelected(option)}\n // biome-ignore lint/a11y/useSemanticElements: Dette er en reimplementering av en liste\n role=\"option\"\n value={option.value}\n onBlur={handleBlur}\n className={`jkl-combobox__option ${\n isSelected(option) &&\n \"jkl-combobox__option--selected\"\n }`}\n data-testid=\"jkl-combobox__option\"\n data-testautoid={`jkl-combobox__option-${i}`}\n onFocus={handleFocus}\n onKeyDown={handleOptionOnKeyDown}\n onClick={(e) => {\n setActiveDescendant(\n `${listId}__${option.value}`,\n ); // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/listbox_role#required_javascript_features\n e.stopPropagation();\n onItemClick(option.value);\n setSearchValue(\"\");\n }}\n onMouseOver={handleMouseOver}\n >\n {option.description ? (\n <span>\n {option.label}\n <span className=\"jkl-combobox__option-description\">\n {option.description}\n </span>\n </span>\n ) : (\n option.label\n )}\n {isSelected(option) ? (\n <span>\n <CheckIcon />{\" \"}\n </span>\n ) : null}\n </button>\n ))}\n {noResults && (\n <div className=\"jkl-combobox__no-option\">\n {noMatchingOption}\n </div>\n )}\n </div>\n <IconButton\n id={buttonId}\n onFocus={handleFocus}\n onBlur={handleBlur}\n className=\"jkl-text-input-action-button\"\n data-testid=\"jkl-combobox__button\"\n aria-label=\"Åpne meny\"\n aria-expanded={showMenu}\n aria-controls={listId}\n onClick={() => setShowMenu((previous) => !previous)}\n onMouseDown={(e) => {\n e.preventDefault();\n inputRef.current?.focus();\n }}\n >\n <ArrowVerticalAnimated pointingDown={isPointingDown} />\n </IconButton>\n </div>\n )}\n />\n );\n};\nCombobox.displayName = \"Combobox\";\n"],"names":["getComboboxValuePair","item","value","label","Combobox","props","dataSize","id","placeholder","items","onChange","onFocus","onBlur","noMatchingOption","labelProps","helpLabel","errorLabel","width","name","className","invalid","description","hasTagHover","tooltip","listId","useId","generateSuffix","labelId","buttonId","inputId","selectedValue","setSelectedValue","useState","showMenu","setShowMenu","searchValue","setSearchValue","noResults","setNoResults","marked","setMarked","searchRef","useRef","inputRef","focusInsideRef","useEffect","current","focus","prev","isSelected","option","some","removeOption","useCallback","filter","onTagRemove","e","newValue","type","target","selectedOptions","stopPropagation","length","onItemClick","find","i","onSearch","options","useMemo","filteredOptions","toLowerCase","indexOf","activeDescendant","setActiveDescendant","isPointingDown","handleEscape","key","window","addEventListener","removeEventListener","handleFocusPlacement","isOpen","handleFocus","dropdownRef","useAnimatedHeight","onFirstVisible","onTransitionEnd","useListNavigation","ref","componentRootElementRef","handleBlur","contains","relatedTarget","dispatchEvent","Event","bubbles","handleMouseOver","preventScroll","handleSearchOnKeyDown","preventDefault","listElement","querySelector","metaKey","ctrlKey","updatedSelectedValue","map","isMarked","handleOptionOnKeyDown","shiftKey","firstVisible","currentTarget","hasSelection","renderSelectedOption","jsx","Chip","tagLabel","variant","onClick","children","InputGroup","clsx","render","inputProps","jsxs","style","tabIndex","Tooltip","TooltipTrigger","TooltipContent","onKeyDown","role","autoComplete","onMouseOver","CheckIcon","IconButton","previous","onMouseDown","ArrowVerticalAnimated","pointingDown","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"Combobox.cjs","sources":["../../../../src/components/combobox/Combobox.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, {\n type FC,\n type FocusEvent,\n type KeyboardEvent,\n type MouseEvent,\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 type { ValuePair } from \"../../utilities/valuePair.js\";\nimport { Chip } from \"../chip/Chip.js\";\nimport { IconButton } from \"../icon-button/IconButton.js\";\nimport { CheckIcon } from \"../icon/icons/CheckIcon.js\";\nimport { ArrowVerticalAnimated } from \"../icon/icons/animated/ArrowVerticalAnimated.js\";\nimport { InputGroup } from \"../input-group/InputGroup.js\";\nimport { Tooltip } from \"../tooltip/Tooltip.js\";\nimport { TooltipContent } from \"../tooltip/TooltipContent.js\";\nimport { TooltipTrigger } from \"../tooltip/TooltipTrigger.js\";\nimport type { ComboboxProps, ComboboxValuePair } from \"./types.js\";\n\nexport function getComboboxValuePair(\n item: string | ComboboxValuePair,\n): ComboboxValuePair {\n return typeof item === \"string\" ? { value: item, label: item } : item;\n}\n\n/**\n * @deprecated Bruk heller Select med `multiple` og `searchable` satt til\n * `true`. Combobox vil bli fjernet ved en senere oppdatering.\n */\nexport const Combobox: FC<ComboboxProps> = (props) => {\n const {\n \"data-size\": dataSize,\n id,\n placeholder,\n items,\n onChange,\n onFocus,\n onBlur,\n value,\n label,\n noMatchingOption,\n labelProps,\n helpLabel,\n errorLabel,\n width,\n name,\n className,\n invalid,\n description,\n hasTagHover,\n tooltip,\n } = props;\n const listId = useId(id || \"jkl-combobox\", { generateSuffix: !id });\n const labelId = `${listId}_label`;\n const buttonId = `${listId}_button`;\n const inputId = `${listId}_search-input`;\n\n const [selectedValue, setSelectedValue] = useState<\n Array<ComboboxValuePair>\n >(value || []);\n const [showMenu, setShowMenu] = useState<boolean>(false);\n const [searchValue, setSearchValue] = useState<string>(\"\");\n const [noResults, setNoResults] = useState(false);\n const [marked, setMarked] = useState<boolean>(false);\n\n const searchRef = useRef<HTMLInputElement>(null);\n const inputRef = useRef<HTMLDivElement>(null);\n const focusInsideRef = useRef(false);\n\n useEffect(() => {\n setSearchValue(\"\");\n if (showMenu && searchRef.current) {\n searchRef.current.focus();\n }\n }, [showMenu]);\n\n useEffect(() => {\n setSelectedValue((prev) => value || prev);\n }, [value]);\n\n // Funksjon for å stile valgt element\n const isSelected = (option: ValuePair) => {\n if (!selectedValue) {\n return false;\n }\n\n return selectedValue.some((value) => value.value === option.value);\n };\n\n // Fjerne ett eller flere valg\n const removeOption = useCallback(\n (option: string) => {\n return selectedValue.filter((value) => value.value !== option);\n },\n [selectedValue],\n );\n\n const onTagRemove = useCallback(\n (\n e:\n | React.MouseEvent<HTMLButtonElement, globalThis.MouseEvent>\n | React.KeyboardEvent<HTMLInputElement>,\n option: string,\n ) => {\n const newValue = removeOption(option);\n setSelectedValue(newValue);\n onChange({\n type: \"change\",\n target: { name, value: option, selectedOptions: newValue },\n });\n e.stopPropagation();\n\n if (newValue.length === 0) {\n setMarked(false);\n }\n },\n [removeOption, onChange, name],\n );\n\n // Håndtere valgt verdi i listen\n const onItemClick = useCallback(\n (option: string) => {\n let newValue: Array<ValuePair>;\n\n if (selectedValue.some((value) => value.value === option)) {\n newValue = removeOption(option);\n } else {\n const item = items.find((i) => i.value === option);\n newValue = [...selectedValue, item as ValuePair];\n }\n searchRef.current?.focus();\n setSelectedValue(newValue);\n onChange({\n type: \"change\",\n target: { name, value: option, selectedOptions: newValue },\n });\n },\n [selectedValue, onChange, name, removeOption, items],\n );\n\n // Funksjon for søk\n const onSearch = (e: {\n target: { value: React.SetStateAction<string> };\n }) => {\n searchRef.current?.focus();\n setShowMenu(true);\n setSearchValue(e.target.value);\n };\n\n const options = useMemo(() => {\n if (!searchValue) {\n return items;\n }\n\n const filteredOptions = items.filter(\n (option) =>\n option.label.toLowerCase().indexOf(searchValue.toLowerCase()) >=\n 0,\n );\n\n setNoResults(filteredOptions.length === 0);\n\n return filteredOptions;\n }, [searchValue, items]);\n\n // Det første elementet i listen skal være aktivt fram til brukeren klikker på noe annet\n const [activeDescendant, setActiveDescendant] = useState<\n string | undefined\n >(options[0]?.value ? `${listId}-${options[0]?.value}` : undefined);\n\n // Håndtere arrow-state\n const isPointingDown = !showMenu;\n\n // Lukk meny med ESC\n useEffect(() => {\n const handleEscape = (e: globalThis.KeyboardEvent) => {\n if (e.key === \"Escape\" && showMenu) {\n setShowMenu(false);\n }\n };\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"keydown\", handleEscape);\n }\n return () => {\n if (typeof window !== \"undefined\" && showMenu) {\n window.removeEventListener(\"keydown\", handleEscape);\n }\n };\n }, [showMenu]);\n\n // Fokushåndtering\n const handleFocusPlacement = useCallback((isOpen: boolean) => {\n if (isOpen) {\n if (searchRef.current) {\n searchRef.current.focus();\n }\n } else {\n if (focusInsideRef.current && inputRef.current) {\n inputRef.current.focus();\n }\n }\n }, []);\n\n const handleFocus = useCallback(() => {\n if (!focusInsideRef.current) {\n if (onFocus) {\n onFocus({\n type: \"change\",\n target: {\n name,\n value: selectedValue?.[0].value || \"\",\n selectedOptions: selectedValue,\n },\n });\n }\n focusInsideRef.current = true;\n setShowMenu(true);\n }\n }, [onFocus, selectedValue, name]);\n\n const [dropdownRef] = useAnimatedHeight<HTMLDivElement>(showMenu, {\n onFirstVisible: handleFocusPlacement,\n onTransitionEnd: handleFocusPlacement,\n });\n\n useListNavigation({ ref: dropdownRef });\n\n const componentRootElementRef = useRef<HTMLDivElement>(null);\n\n const handleBlur = useCallback(\n (\n e: FocusEvent<\n HTMLDivElement | HTMLInputElement | HTMLButtonElement\n >,\n ) => {\n const componentRootElement = componentRootElementRef.current;\n const nextFocusIsInsideComponent = componentRootElement?.contains(\n e.relatedTarget as Node,\n );\n if (!nextFocusIsInsideComponent) {\n setSearchValue(\"\");\n\n if (onBlur) {\n onBlur({\n type: \"blur\",\n target: {\n name,\n value: selectedValue?.[0]?.value || \"\",\n selectedOptions: selectedValue,\n },\n });\n inputRef.current?.dispatchEvent(\n new Event(\"focusout\", { bubbles: true }),\n );\n }\n focusInsideRef.current = false;\n setShowMenu(false);\n }\n },\n [onBlur, name, selectedValue],\n );\n\n const handleMouseOver = useCallback((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 // Tastaturnavigasjon\n const handleSearchOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n e.stopPropagation();\n const listElement = dropdownRef.current;\n if (listElement) {\n listElement\n .querySelector<HTMLButtonElement>('[role=\"option\"]')\n ?.focus();\n }\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n setShowMenu(false);\n }\n\n if ((e.metaKey && e.key === \"a\") || (e.ctrlKey && e.key === \"a\")) {\n e.preventDefault();\n e.stopPropagation();\n const updatedSelectedValue = selectedValue.map((item) => ({\n ...item,\n isMarked: true,\n }));\n setMarked(true);\n setSelectedValue(updatedSelectedValue);\n } else if (e.key === \"Backspace\") {\n e.stopPropagation();\n setMarked(false);\n\n // Sjekk om selectedValue er markert\n const selectedValueIsMarked = selectedValue.some(\n (item) => item.isMarked,\n );\n\n if (selectedValueIsMarked) {\n const updatedSelectedValue = selectedValue.filter(\n (item) => !item.isMarked,\n );\n setSelectedValue(updatedSelectedValue);\n setSearchValue(\"\");\n } else if (selectedValue.length > 0 && searchValue === \"\") {\n // Hvis ingen items er markert, fjern siste valgte item\n onTagRemove(\n e,\n selectedValue[selectedValue.length - 1].value,\n );\n }\n }\n },\n [selectedValue, searchValue, dropdownRef, onTagRemove],\n );\n\n const handleOptionOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === \"Tab\") {\n if (searchRef.current) {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.shiftKey) {\n searchRef.current.focus();\n } else {\n setShowMenu(false);\n searchRef.current.focus();\n }\n }\n } else if (e.key === \"ArrowUp\") {\n if (dropdownRef.current && searchRef.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 searchRef.current\n ) {\n searchRef.current.focus();\n }\n }\n }\n },\n [dropdownRef],\n );\n\n const hasSelection = selectedValue.length >= 1;\n\n const renderSelectedOption = useCallback(\n (option: ComboboxValuePair) => (\n <Chip\n key={option.value}\n data-testid=\"jkl-chip\"\n aria-label={`Fjern ${option.tagLabel}`}\n className={`jkl-combobox__selected-option ${\n marked && \"jkl-combobox__selected-option--marked\"\n }`}\n variant=\"input\"\n onClick={(e) => {\n if (searchRef.current) {\n searchRef.current.focus();\n }\n onTagRemove(e, option.value);\n }}\n onBlur={handleBlur}\n >\n {option.tagLabel ? option.tagLabel : option.label}\n </Chip>\n ),\n [handleBlur, onTagRemove, marked],\n );\n\n return (\n <InputGroup\n label={label}\n id={inputId}\n ref={componentRootElementRef}\n data-testid=\"jkl-combobox\"\n data-size={dataSize}\n className={clsx(\"jkl-combobox\", className, {\n \"jkl-combobox--invalid\": !!errorLabel || invalid,\n \"jkl-combobox--menu-open\": showMenu,\n \"jkl-combobox--menu-closed\": !showMenu && hasSelection,\n })}\n labelProps={{\n id: labelId,\n ...labelProps,\n }}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n description={description}\n tooltip={tooltip}\n render={(inputProps) => (\n <div\n className={clsx(\"jkl-combobox__wrapper\", {\n \"jkl-combobox__wrapper--active-value\": hasSelection,\n })}\n style={{ width }}\n tabIndex={-1}\n onFocus={handleFocus}\n onBlur={handleBlur}\n data-invalid={!!errorLabel || invalid}\n >\n <div\n className=\"jkl-combobox__chips\"\n data-testid=\"jkl-combobox__chips\"\n >\n {selectedValue\n .map(getComboboxValuePair)\n .map((option) => {\n return hasTagHover ? (\n <Tooltip key={option.value}>\n <TooltipTrigger>\n {renderSelectedOption(option)}\n </TooltipTrigger>\n <TooltipContent>\n {option.label}\n </TooltipContent>\n </Tooltip>\n ) : (\n renderSelectedOption(option)\n );\n })}\n <input\n {...inputProps}\n className=\"jkl-combobox__search-input\"\n onChange={onSearch}\n data-testid=\"jkl-combobox__search-input\"\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleSearchOnKeyDown}\n value={searchValue}\n ref={searchRef}\n aria-controls={listId}\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded={showMenu}\n placeholder={\n selectedValue.length > 0 ? \"\" : placeholder\n }\n autoComplete=\"off\"\n />\n </div>\n\n <div\n className=\"jkl-combobox__menu\"\n // biome-ignore lint/a11y/useSemanticElements: Dette er en reimplementering av en liste\n role=\"listbox\"\n ref={dropdownRef}\n id={listId}\n aria-labelledby={labelId}\n aria-multiselectable=\"true\"\n aria-activedescendant={activeDescendant}\n onFocus={handleFocus}\n onBlur={handleBlur}\n tabIndex={-1}\n >\n {options.map((option, i) => (\n <button\n key={`${listId}-${option.value}`}\n type=\"button\"\n id={`${listId}__${option.value}`}\n aria-selected={isSelected(option)}\n // biome-ignore lint/a11y/useSemanticElements: Dette er en reimplementering av en liste\n role=\"option\"\n value={option.value}\n onBlur={handleBlur}\n className={`jkl-combobox__option ${\n isSelected(option) &&\n \"jkl-combobox__option--selected\"\n }`}\n data-testid=\"jkl-combobox__option\"\n data-testautoid={`jkl-combobox__option-${i}`}\n onFocus={handleFocus}\n onKeyDown={handleOptionOnKeyDown}\n onClick={(e) => {\n setActiveDescendant(\n `${listId}__${option.value}`,\n ); // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/listbox_role#required_javascript_features\n e.stopPropagation();\n onItemClick(option.value);\n setSearchValue(\"\");\n }}\n onMouseOver={handleMouseOver}\n >\n {option.description ? (\n <span>\n {option.label}\n <span className=\"jkl-combobox__option-description\">\n {option.description}\n </span>\n </span>\n ) : (\n option.label\n )}\n {isSelected(option) ? (\n <span>\n <CheckIcon />{\" \"}\n </span>\n ) : null}\n </button>\n ))}\n {noResults && (\n <div className=\"jkl-combobox__no-option\">\n {noMatchingOption}\n </div>\n )}\n </div>\n <IconButton\n id={buttonId}\n onFocus={handleFocus}\n onBlur={handleBlur}\n className=\"jkl-text-input-action-button\"\n data-testid=\"jkl-combobox__button\"\n aria-label=\"Åpne meny\"\n aria-expanded={showMenu}\n aria-controls={listId}\n onClick={() => setShowMenu((previous) => !previous)}\n onMouseDown={(e) => {\n e.preventDefault();\n inputRef.current?.focus();\n }}\n >\n <ArrowVerticalAnimated pointingDown={isPointingDown} />\n </IconButton>\n </div>\n )}\n />\n );\n};\nCombobox.displayName = \"Combobox\";\n"],"names":["getComboboxValuePair","item","value","label","Combobox","props","dataSize","id","placeholder","items","onChange","onFocus","onBlur","noMatchingOption","labelProps","helpLabel","errorLabel","width","name","className","invalid","description","hasTagHover","tooltip","listId","useId","generateSuffix","labelId","buttonId","inputId","selectedValue","setSelectedValue","useState","showMenu","setShowMenu","searchValue","setSearchValue","noResults","setNoResults","marked","setMarked","searchRef","useRef","inputRef","focusInsideRef","useEffect","current","focus","prev","isSelected","option","some","removeOption","useCallback","filter","onTagRemove","e","newValue","type","target","selectedOptions","stopPropagation","length","onItemClick","find","i","onSearch","options","useMemo","filteredOptions","toLowerCase","indexOf","activeDescendant","setActiveDescendant","isPointingDown","handleEscape","key","window","addEventListener","removeEventListener","handleFocusPlacement","isOpen","handleFocus","dropdownRef","useAnimatedHeight","onFirstVisible","onTransitionEnd","useListNavigation","ref","componentRootElementRef","handleBlur","contains","relatedTarget","dispatchEvent","Event","bubbles","handleMouseOver","preventScroll","handleSearchOnKeyDown","preventDefault","listElement","querySelector","metaKey","ctrlKey","updatedSelectedValue","map","isMarked","handleOptionOnKeyDown","shiftKey","firstVisible","currentTarget","hasSelection","renderSelectedOption","jsx","Chip","tagLabel","variant","onClick","children","InputGroup","clsx","render","inputProps","jsxs","style","tabIndex","Tooltip","TooltipTrigger","TooltipContent","onKeyDown","role","autoComplete","onMouseOver","CheckIcon","IconButton","previous","onMouseDown","ArrowVerticalAnimated","pointingDown","displayName"],"mappings":"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"}
@@ -1,4 +1,8 @@
1
1
  import { FC } from 'react';
2
2
  import { ComboboxProps, ComboboxValuePair } from './types.cjs';
3
3
  export declare function getComboboxValuePair(item: string | ComboboxValuePair): ComboboxValuePair;
4
+ /**
5
+ * @deprecated Bruk heller Select med `multiple` og `searchable` satt til
6
+ * `true`. Combobox vil bli fjernet ved en senere oppdatering.
7
+ */
4
8
  export declare const Combobox: FC<ComboboxProps>;
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("../../../clsx-E3yX_9sL.cjs"),n=require("react"),r=require("../../utilities/polymorphism/SlotComponent.cjs"),i=require("./types.cjs"),l=n.forwardRef(function(n,i){const{asChild:l,alignItems:o,alignContent:a,as:c="div",center:p=!1,className:u,direction:f="row",fill:m,gap:x="m",inline:$,justifyContent:g,layout:j={},textAlign:d,wrap:y="nowrap",...w}=n,q=l?r.SlotComponent:c,C=s(x).flatMap(([e,t])=>{const[n,r=n]=t.trim().split(" ");return[`screen-${e}-row-gap-${n}`,`screen-${e}-col-gap-${r}`]}),v=s(j).map(([e,t])=>`screen-${e}-${t}`);return e.jsx(q,{...w,className:t.clsx("jkl-flex",!o||`align-items-${o}`,!a||`align-content-${a}`,!p||`center-${!0===p?"2xl":p}`,!m||"fill",!$||"inline-flex",!g||`justify-content-${g}`,!d||`text-align-${d}`,!y||`flex-wrap-${y}`,!f||`flex-direction-${f}`,...C,...v,u),ref:i})});function s(e){return i.isResponsive(e)?Object.entries(e).filter(([,e])=>void 0!==e):[["small",e]]}exports.Flex=l;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("../../../clsx-E3yX_9sL.cjs"),r=require("react"),n=require("../../utilities/polymorphism/SlotComponent.cjs"),i=r.forwardRef(function(r,i){const{asChild:s,alignItems:o,alignContent:a,as:l="div",className:c,direction:p,gap:u,justifyContent:g,wrap:f,style:j,...m}=r,x=!0===f?"wrap":!1===f?"nowrap":"reverse"===f?"wrap-reverse":f;const d=s?n.SlotComponent:l;return e.jsx(d,{style:{"--wrap":x,"--gap":function(e){if(e?.toString().includes(" ")){const[t,r]=e.toString().trim().split(" ");return`var(--jkl-spacing-${t}) var(--jkl-spacing-${r})`}if(e)return`var(--jkl-spacing-${e})`}(u),"--align-items":o,"--align-content":a,"--justify-content":g,"--flex-direction":p,...j},...m,className:t.clsx("jkl-flex",c),ref:i})});exports.Flex=i;
2
2
  //# sourceMappingURL=Flex.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Flex.cjs","sources":["../../../../src/components/flex/Flex.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, { forwardRef } from \"react\";\nimport { SlotComponent } from \"../../utilities/index.js\";\nimport type { PolymorphicRef } from \"../../utilities/polymorphism/polymorphism.js\";\nimport {\n type Breakpoint,\n type FlexComponent,\n type FlexProps,\n type Responsive,\n isResponsive,\n} from \"./types.js\";\n\nexport const Flex = forwardRef(function Flex<\n ElementType extends React.ElementType = \"div\",\n>(props: FlexProps<ElementType>, ref?: PolymorphicRef<ElementType>) {\n const {\n asChild,\n alignItems,\n alignContent,\n as = \"div\",\n center = false,\n className,\n direction = \"row\",\n fill,\n gap = \"m\",\n inline,\n justifyContent,\n layout = {},\n textAlign,\n wrap = \"nowrap\",\n ...rest\n } = props;\n\n const Tag = asChild ? SlotComponent : as;\n const gaps = toObjectEntries(gap).flatMap(([breakpoint, gap]) => {\n const [row, col = row] = gap.trim().split(\" \");\n return [\n `screen-${breakpoint}-row-gap-${row}`,\n `screen-${breakpoint}-col-gap-${col}`,\n ];\n });\n const layouts = toObjectEntries(layout).map(\n ([breakpoint, layout]) => `screen-${breakpoint}-${layout}`, // Convert to number to convert 2.10 to 2.1 and false to 0\n );\n\n return (\n <Tag\n {...rest}\n className={clsx(\n \"jkl-flex\",\n !alignItems || `align-items-${alignItems}`,\n !alignContent || `align-content-${alignContent}`,\n !center || `center-${center === true ? \"2xl\" : center}`,\n !fill || \"fill\",\n !inline || \"inline-flex\",\n !justifyContent || `justify-content-${justifyContent}`,\n !textAlign || `text-align-${textAlign}`,\n !wrap || `flex-wrap-${wrap}`,\n !direction || `flex-direction-${direction}`,\n ...gaps,\n ...layouts,\n className,\n )}\n ref={ref}\n />\n );\n}) as FlexComponent; // Needed to tell Typescript this does not return ReactNode but acutally JSX.Element\n\n/**\n * Gjør en enkeltstående eller responsiv verdi om til et nøstet array,\n * der hvert indre array inneholder et breakpoint med tilhørende verdi.\n * @example `{ small: \"12\", large: \"64\" }` -> `[[\"small\", \"12\"], [\"large\", \"64\"]]`\n * @example `\"24\"` -> `[[\"small\", \"24\"]]`\n * @param value enkeltstående eller responsiv verdi\n * @returns nøstet array med breakpoints og verdier\n */\nfunction toObjectEntries<T>(value: T | Responsive<T>): [Breakpoint, T][] {\n if (isResponsive(value)) {\n return (Object.entries(value) as [Breakpoint, T][]).filter(\n ([, v]) => v !== undefined,\n );\n }\n\n return [[\"small\", value]];\n}\n"],"names":["Flex","forwardRef","props","ref","asChild","alignItems","alignContent","as","center","className","direction","fill","gap","inline","justifyContent","layout","textAlign","wrap","rest","Tag","SlotComponent","gaps","toObjectEntries","flatMap","breakpoint","row","col","trim","split","layouts","map","jsx","clsx","value","isResponsive","Object","entries","filter","v"],"mappings":"qQAYaA,EAAOC,EAAAA,WAAW,SAE7BC,EAA+BC,GAC7B,MACIC,QAAAA,EACAC,WAAAA,EACAC,aAAAA,EACAC,GAAAA,EAAK,MACLC,OAAAA,GAAS,EACTC,UAAAA,EACAC,UAAAA,EAAY,MACZC,KAAAA,EACAC,IAAAA,EAAM,IACNC,OAAAA,EACAC,eAAAA,EACAC,OAAAA,EAAS,CAAA,EACTC,UAAAA,EACAC,KAAAA,EAAO,YACJC,GACHhB,EAEEiB,EAAMf,EAAUgB,EAAAA,cAAgBb,EAChCc,EAAOC,EAAgBV,GAAKW,QAAQ,EAAEC,EAAYZ,MACpD,MAAOa,EAAKC,EAAMD,GAAOb,EAAIe,OAAOC,MAAM,KAC1C,MAAO,CACH,UAAUJ,aAAsBC,IAChC,UAAUD,aAAsBE,OAGlCG,EAAUP,EAAgBP,GAAQe,IACpC,EAAEN,EAAYT,KAAY,UAAUS,KAAcT,KAGtD,OACIgB,EAAAA,IAACZ,EAAA,IACOD,EACJT,UAAWuB,EAAAA,KACP,YACC3B,GAAc,eAAeA,KAC7BC,GAAgB,iBAAiBA,KACjCE,GAAU,WAAqB,IAAXA,EAAkB,MAAQA,KAC9CG,GAAQ,QACRE,GAAU,eACVC,GAAkB,mBAAmBA,KACrCE,GAAa,cAAcA,KAC3BC,GAAQ,aAAaA,KACrBP,GAAa,kBAAkBA,OAC7BW,KACAQ,EACHpB,GAEJN,IAAAA,GAGZ,GAUA,SAASmB,EAAmBW,GACxB,OAAIC,EAAAA,aAAaD,GACLE,OAAOC,QAAQH,GAA6BI,OAChD,EAAC,CAAGC,UAAa,IAANA,GAIZ,CAAC,CAAC,QAASL,GACtB"}
1
+ {"version":3,"file":"Flex.cjs","sources":["../../../../src/components/flex/Flex.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, { type CSSProperties, forwardRef } from \"react\";\nimport { SlotComponent } from \"../../utilities/index.js\";\nimport type { PolymorphicRef } from \"../../utilities/polymorphism/polymorphism.js\";\nimport type { FlexComponent, FlexProps } from \"./types.js\";\n\nexport const Flex = forwardRef(function Flex<\n ElementType extends React.ElementType = \"div\",\n>(props: FlexProps<ElementType>, ref?: PolymorphicRef<ElementType>) {\n const {\n asChild,\n alignItems,\n alignContent,\n as = \"div\",\n className,\n direction,\n gap,\n justifyContent,\n wrap,\n style,\n ...rest\n } = props;\n\n const wrapping =\n wrap === true\n ? \"wrap\"\n : wrap === false\n ? \"nowrap\"\n : wrap === \"reverse\"\n ? \"wrap-reverse\"\n : wrap;\n\n function getGapValue(gap: FlexProps[\"gap\"]) {\n if (gap?.toString().includes(\" \")) {\n const [rowGap, columnGap] = gap.toString().trim().split(\" \");\n return `var(--jkl-spacing-${rowGap}) var(--jkl-spacing-${columnGap})`;\n }\n if (gap) {\n return `var(--jkl-spacing-${gap})`;\n }\n return undefined;\n }\n\n const Tag = asChild ? SlotComponent : as;\n\n return (\n <Tag\n style={\n {\n \"--wrap\": wrapping,\n \"--gap\": getGapValue(gap),\n \"--align-items\": alignItems,\n \"--align-content\": alignContent,\n \"--justify-content\": justifyContent,\n \"--flex-direction\": direction,\n ...style,\n } as CSSProperties\n }\n {...rest}\n className={clsx(\"jkl-flex\", className)}\n ref={ref}\n />\n );\n}) as FlexComponent;\n"],"names":["Flex","forwardRef","props","ref","asChild","alignItems","alignContent","as","className","direction","gap","justifyContent","wrap","style","rest","wrapping","Tag","SlotComponent","jsx","toString","includes","rowGap","columnGap","trim","split","getGapValue","clsx"],"mappings":"4OAMaA,EAAOC,EAAAA,WAAW,SAE7BC,EAA+BC,GAC7B,MACIC,QAAAA,EACAC,WAAAA,EACAC,aAAAA,EACAC,GAAAA,EAAK,MACLC,UAAAA,EACAC,UAAAA,EACAC,IAAAA,EACAC,eAAAA,EACAC,KAAAA,EACAC,MAAAA,KACGC,GACHZ,EAEEa,GACO,IAATH,EACM,QACS,IAATA,EACE,SACS,YAATA,EACE,eACAA,EAad,MAAMI,EAAMZ,EAAUa,EAAAA,cAAgBV,EAEtC,OACIW,EAAAA,IAACF,EAAA,CACGH,MACI,CACI,SAAUE,EACV,QAlBhB,SAAqBL,GACjB,GAAIA,GAAKS,WAAWC,SAAS,KAAM,CAC/B,MAAOC,EAAQC,GAAaZ,EAAIS,WAAWI,OAAOC,MAAM,KACxD,MAAO,qBAAqBH,wBAA6BC,IAC7D,CACA,GAAIZ,EACA,MAAO,qBAAqBA,IAGpC,CASyBe,CAAYf,GACrB,gBAAiBL,EACjB,kBAAmBC,EACnB,oBAAqBK,EACrB,mBAAoBF,KACjBI,MAGPC,EACJN,UAAWkB,EAAAA,KAAK,WAAYlB,GAC5BL,IAAAA,GAGZ"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),require("react");const e=["small","medium","large","xl"];exports.LAYOUTS=["auto","1","2","3","4","6","4.8","8.4","2.10","10.2","3.9","9.3","5.7","7.5"],exports.SEMANTIC_SPACING=["none","2xs","xs","s","m","l","xl","2xl"],exports.STATIC_SPACING=["0","2","4","8","12","16","20","24","28","32","40","48","56","64","72","80","104","168"],exports.isResponsive=function(t){if("object"!=typeof t||null===t||Array.isArray(t))return!1;const r=Object.keys(t);return 0===r.length||e.includes(r[0])};
1
+ "use strict";require("../../tokens.cjs").spacing;
2
2
  //# sourceMappingURL=types.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.cjs","sources":["../../../../src/components/flex/types.ts"],"sourcesContent":["import React from \"react\";\nimport type { AsChildProps } from \"../../utilities/polymorphism/as-child.js\";\nimport type { PolymorphicPropsWithRef } from \"../../utilities/polymorphism/polymorphism.js\";\n\nexport const SEMANTIC_SPACING = [\n \"none\",\n \"2xs\",\n \"xs\",\n \"s\",\n \"m\",\n \"l\",\n \"xl\",\n \"2xl\",\n] as const;\n\nexport const STATIC_SPACING = [\n \"0\",\n \"2\",\n \"4\",\n \"8\",\n \"12\",\n \"16\",\n \"20\",\n \"24\",\n \"28\",\n \"32\",\n \"40\",\n \"48\",\n \"56\",\n \"64\",\n \"72\",\n \"80\",\n \"104\",\n \"168\",\n] as const;\n\nconst BREAKPOINTS = [\"small\", \"medium\", \"large\", \"xl\"] as const;\n\nexport type SemanticSpacing = (typeof SEMANTIC_SPACING)[number];\nexport type StaticSpacing = (typeof STATIC_SPACING)[number];\nexport type Breakpoint = (typeof BREAKPOINTS)[number];\n\nexport type Responsive<T> = Partial<Record<Breakpoint, T>>;\nexport function isResponsive<T>(value: unknown): value is Responsive<T> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return false;\n }\n const keys = Object.keys(value);\n return keys.length === 0 || BREAKPOINTS.includes(keys[0] as Breakpoint);\n}\n\nexport const LAYOUTS = [\n \"auto\",\n \"1\",\n \"2\",\n \"3\",\n \"4\",\n \"6\",\n \"4.8\",\n \"8.4\",\n \"2.10\",\n \"10.2\",\n \"3.9\",\n \"9.3\",\n \"5.7\",\n \"7.5\",\n] as const;\n\nexport type Layout = (typeof LAYOUTS)[number];\nexport type Center = \"m\" | \"l\" | \"xl\" | \"2xl\" | boolean;\n\nexport type DynamicGap =\n | `${SemanticSpacing}`\n | `${SemanticSpacing} ${SemanticSpacing}`;\nexport type StaticGap =\n | `${StaticSpacing}`\n | `${StaticSpacing} ${StaticSpacing}`;\nexport type Gap = DynamicGap | StaticGap;\n\ntype FlexBaseProps = {\n alignItems?: \"normal\" | \"start\" | \"center\" | \"end\" | \"baseline\" | \"stretch\";\n alignContent?:\n | \"normal\"\n | \"start\"\n | \"center\"\n | \"end\"\n | \"stretch\"\n | \"baseline\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\";\n center?: Center;\n direction?: \"row\" | \"column\" | \"row-reverse\" | \"column-reverse\";\n fill?: boolean;\n gap?: Gap | Responsive<Gap>;\n inline?: boolean;\n textAlign?: \"left\" | \"right\" | \"center\";\n justifyContent?:\n | \"normal\"\n | \"start\"\n | \"center\"\n | \"end\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\";\n layout?: Layout | Responsive<Layout>;\n wrap?: \"wrap\" | \"nowrap\" | \"reverse\";\n};\n\nexport type FlexProps<As extends React.ElementType = \"div\"> =\n PolymorphicPropsWithRef<As, FlexBaseProps>;\n\nexport type FlexComponent = <ElementType extends React.ElementType = \"div\">(\n props: FlexProps<ElementType> & AsChildProps,\n) => React.ReactElement | null;\n"],"names":["BREAKPOINTS","value","Array","isArray","keys","Object","length","includes"],"mappings":"iGAIO,MAgCDA,EAAc,CAAC,QAAS,SAAU,QAAS,sBAe1B,CACnB,OACA,IACA,IACA,IACA,IACA,IACA,MACA,MACA,OACA,OACA,MACA,MACA,MACA,gCA7D4B,CAC5B,OACA,MACA,KACA,IACA,IACA,IACA,KACA,8BAG0B,CAC1B,IACA,IACA,IACA,IACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,MACA,4BAUG,SAAyBC,GAC5B,GAAqB,iBAAVA,GAAgC,OAAVA,GAAkBC,MAAMC,QAAQF,GAC7D,OAAO,EAEX,MAAMG,EAAOC,OAAOD,KAAKH,GACzB,OAAuB,IAAhBG,EAAKE,QAAgBN,EAAYO,SAASH,EAAK,GAC1D"}
1
+ {"version":3,"file":"types.cjs","sources":["../../../../src/components/flex/types.ts"],"sourcesContent":["import type React from \"react\";\nimport * as tokens from \"../../tokens.js\";\nimport type {\n AsChildProps,\n PolymorphicPropsWithRef,\n} from \"../../utilities/index.js\";\n\nconst staticSpacingTokens = tokens.default.spacing;\n\ntype Spacing = keyof typeof staticSpacingTokens;\ntype SpacingValue = `${Spacing}`;\n\nexport type Gap = Spacing | SpacingValue | `${SpacingValue} ${SpacingValue}`;\n\ntype FlexBaseProps = {\n alignItems?: \"normal\" | \"start\" | \"center\" | \"end\" | \"baseline\" | \"stretch\";\n alignContent?:\n | \"normal\"\n | \"start\"\n | \"center\"\n | \"end\"\n | \"stretch\"\n | \"baseline\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\";\n direction?: \"row\" | \"row-reverse\" | \"column\" | \"column-reverse\";\n gap?: Gap;\n justifyContent?:\n | \"normal\"\n | \"start\"\n | \"center\"\n | \"end\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\";\n /**\n * Om elementene skal brytes over flere linjer.\n * `true`/`false` setter `wrap`/`nowrap`, `\"reverse\"` som kortform for\n * `\"wrap-reverse\"`.\n */\n wrap?: boolean | \"wrap\" | \"nowrap\" | \"reverse\";\n};\n\nexport type FlexProps<As extends React.ElementType = \"div\"> =\n PolymorphicPropsWithRef<As, FlexBaseProps> & AsChildProps;\n\n// Nødvendig for å fortelle TypeScript at dette ikke returnerer ReactNode, men JSX.Element\nexport type FlexComponent = <ElementType extends React.ElementType = \"div\">(\n props: FlexProps<ElementType>,\n) => React.ReactElement | null;\n"],"names":["spacing"],"mappings":"yCAO2CA"}
@@ -1,33 +1,43 @@
1
1
  import { default as React } from 'react';
2
- import { AsChildProps } from '../../utilities/polymorphism/as-child.cjs';
3
- import { PolymorphicPropsWithRef } from '../../utilities/polymorphism/polymorphism.cjs';
4
- export declare const SEMANTIC_SPACING: readonly ["none", "2xs", "xs", "s", "m", "l", "xl", "2xl"];
5
- export declare const STATIC_SPACING: readonly ["0", "2", "4", "8", "12", "16", "20", "24", "28", "32", "40", "48", "56", "64", "72", "80", "104", "168"];
6
- declare const BREAKPOINTS: readonly ["small", "medium", "large", "xl"];
7
- export type SemanticSpacing = (typeof SEMANTIC_SPACING)[number];
8
- export type StaticSpacing = (typeof STATIC_SPACING)[number];
9
- export type Breakpoint = (typeof BREAKPOINTS)[number];
10
- export type Responsive<T> = Partial<Record<Breakpoint, T>>;
11
- export declare function isResponsive<T>(value: unknown): value is Responsive<T>;
12
- export declare const LAYOUTS: readonly ["auto", "1", "2", "3", "4", "6", "4.8", "8.4", "2.10", "10.2", "3.9", "9.3", "5.7", "7.5"];
13
- export type Layout = (typeof LAYOUTS)[number];
14
- export type Center = "m" | "l" | "xl" | "2xl" | boolean;
15
- export type DynamicGap = `${SemanticSpacing}` | `${SemanticSpacing} ${SemanticSpacing}`;
16
- export type StaticGap = `${StaticSpacing}` | `${StaticSpacing} ${StaticSpacing}`;
17
- export type Gap = DynamicGap | StaticGap;
2
+ import { AsChildProps, PolymorphicPropsWithRef } from '../../utilities/index.cjs';
3
+ declare const staticSpacingTokens: {
4
+ 0: string;
5
+ 2: string;
6
+ 4: string;
7
+ 8: string;
8
+ 12: string;
9
+ 16: string;
10
+ 24: string;
11
+ 32: string;
12
+ 40: string;
13
+ 64: string;
14
+ 104: string;
15
+ 168: string;
16
+ none: string;
17
+ "2xs": string;
18
+ xs: string;
19
+ s: string;
20
+ m: string;
21
+ l: string;
22
+ xl: string;
23
+ "2xl": string;
24
+ };
25
+ type Spacing = keyof typeof staticSpacingTokens;
26
+ type SpacingValue = `${Spacing}`;
27
+ export type Gap = Spacing | SpacingValue | `${SpacingValue} ${SpacingValue}`;
18
28
  type FlexBaseProps = {
19
29
  alignItems?: "normal" | "start" | "center" | "end" | "baseline" | "stretch";
20
30
  alignContent?: "normal" | "start" | "center" | "end" | "stretch" | "baseline" | "space-between" | "space-around" | "space-evenly";
21
- center?: Center;
22
- direction?: "row" | "column" | "row-reverse" | "column-reverse";
23
- fill?: boolean;
24
- gap?: Gap | Responsive<Gap>;
25
- inline?: boolean;
26
- textAlign?: "left" | "right" | "center";
31
+ direction?: "row" | "row-reverse" | "column" | "column-reverse";
32
+ gap?: Gap;
27
33
  justifyContent?: "normal" | "start" | "center" | "end" | "space-between" | "space-around" | "space-evenly";
28
- layout?: Layout | Responsive<Layout>;
29
- wrap?: "wrap" | "nowrap" | "reverse";
34
+ /**
35
+ * Om elementene skal brytes over flere linjer.
36
+ * `true`/`false` setter `wrap`/`nowrap`, `"reverse"` som kortform for
37
+ * `"wrap-reverse"`.
38
+ */
39
+ wrap?: boolean | "wrap" | "nowrap" | "reverse";
30
40
  };
31
- export type FlexProps<As extends React.ElementType = "div"> = PolymorphicPropsWithRef<As, FlexBaseProps>;
32
- export type FlexComponent = <ElementType extends React.ElementType = "div">(props: FlexProps<ElementType> & AsChildProps) => React.ReactElement | null;
41
+ export type FlexProps<As extends React.ElementType = "div"> = PolymorphicPropsWithRef<As, FlexBaseProps> & AsChildProps;
42
+ export type FlexComponent = <ElementType extends React.ElementType = "div">(props: FlexProps<ElementType>) => React.ReactElement | null;
33
43
  export {};
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),s=require("../../../clsx-E3yX_9sL.cjs"),i=require("react"),a=require("../../hooks/useElementDimensions/useElementDimensions.cjs"),r=require("./useImageLoadingStatus.cjs"),t=require("../../utilities/mergeRefs.cjs");require("../../utilities/polymorphism/SlotComponent.cjs");const l=i.forwardRef(({className:i,placeholder:l,alt:m,...o},c)=>{const[n,g]=r.useImageLoadingStatus(),[u,d]=a.useElementDimensions(400),j=t.mergeRefs(c,n);return e.jsxs("div",{ref:u,className:s.clsx("jkl-image",i,{"jkl-image--loading":!g}),children:[e.jsx("img",{className:"jkl-image__placeholder",alt:g?"":m,src:l||o.src}),e.jsx("img",{alt:m,className:"jkl-image__image","data-testid":"jkl-image__image",ref:j,sizes:`${d.width}px`,decoding:"async",loading:"lazy",...o})]})});l.displayName="Image",exports.Image=l;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),s=require("../../../clsx-E3yX_9sL.cjs"),i=require("react"),a=require("../../hooks/useElementDimensions/useElementDimensions.cjs"),r=require("../../utilities/mergeRefs.cjs");require("../../utilities/polymorphism/SlotComponent.cjs");const t=require("./useImageLoadingStatus.cjs"),l=i.forwardRef(({className:i,placeholder:l,alt:m,...o},c)=>{const[n,g]=t.useImageLoadingStatus(),[u,d]=a.useElementDimensions(400),j=r.mergeRefs(c,n);return e.jsxs("div",{ref:u,className:s.clsx("jkl-image",i,{"jkl-image--loading":!g}),children:[e.jsx("img",{className:"jkl-image__placeholder",alt:g?"":m,src:l||o.src}),e.jsx("img",{alt:m,className:"jkl-image__image","data-testid":"jkl-image__image",ref:j,sizes:`${d.width}px`,decoding:"async",loading:"lazy",...o})]})});l.displayName="Image",exports.Image=l;
2
2
  //# sourceMappingURL=Image.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Image.cjs","sources":["../../../../src/components/image/Image.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { forwardRef } from \"react\";\nimport { useElementDimensions } from \"../../hooks/useElementDimensions/useElementDimensions.js\";\nimport { useImageLoadingStatus } from \"./useImageLoadingStatus.js\";\nimport { mergeRefs } from \"../../utilities/index.js\";\nimport type { ImageProps } from \"./types.js\";\n\nexport const Image = forwardRef<HTMLImageElement, ImageProps>(\n ({ className, placeholder, alt, ...imageProperties }, ref) => {\n const [imageRef, imageLoaded] = useImageLoadingStatus();\n const [containerRef, dimensions] =\n useElementDimensions<HTMLDivElement>(400);\n\n const mergedImageRef = mergeRefs(ref, imageRef);\n\n return (\n <div\n ref={containerRef}\n className={clsx(\"jkl-image\", className, {\n \"jkl-image--loading\": !imageLoaded,\n })}\n >\n {/* Placeholder er bevisst uten loading og decoding for å vises umiddelbart */}\n <img\n className=\"jkl-image__placeholder\"\n alt={imageLoaded ? \"\" : alt}\n src={placeholder || imageProperties.src}\n />\n {/* biome-ignore lint/a11y/useAltText: Den har da vitterlig en alt-attributt? */}\n <img\n alt={alt}\n className=\"jkl-image__image\"\n data-testid=\"jkl-image__image\"\n ref={mergedImageRef}\n sizes={`${dimensions.width}px`}\n decoding=\"async\"\n loading=\"lazy\"\n {...imageProperties}\n />\n </div>\n );\n },\n);\n\nImage.displayName = \"Image\";\n"],"names":["Image","forwardRef","className","placeholder","alt","imageProperties","ref","imageRef","imageLoaded","useImageLoadingStatus","containerRef","dimensions","useElementDimensions","mergedImageRef","mergeRefs","jsxs","clsx","children","jsx","src","sizes","width","decoding","loading","displayName"],"mappings":"qYAOO,MAAMA,EAAQC,EAAAA,WACjB,EAAGC,UAAAA,EAAWC,YAAAA,EAAaC,IAAAA,KAAQC,GAAmBC,KAClD,MAAOC,EAAUC,GAAeC,2BACzBC,EAAcC,GACjBC,EAAAA,qBAAqC,KAEnCC,EAAiBC,EAAAA,UAAUR,EAAKC,GAEtC,OACIQ,EAAAA,KAAC,MAAA,CACGT,IAAKI,EACLR,UAAWc,EAAAA,KAAK,YAAad,EAAW,CACpC,sBAAuBM,IAI3BS,SAAA,CAAAC,EAAAA,IAAC,MAAA,CACGhB,UAAU,yBACVE,IAAKI,EAAc,GAAKJ,EACxBe,IAAKhB,GAAeE,EAAgBc,MAGxCD,EAAAA,IAAC,MAAA,CACGd,IAAAA,EACAF,UAAU,mBACV,cAAY,mBACZI,IAAKO,EACLO,MAAO,GAAGT,EAAWU,UACrBC,SAAS,QACTC,QAAQ,UACJlB,SAOxBL,EAAMwB,YAAc"}
1
+ {"version":3,"file":"Image.cjs","sources":["../../../../src/components/image/Image.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { forwardRef } from \"react\";\nimport { useElementDimensions } from \"../../hooks/useElementDimensions/useElementDimensions.js\";\nimport { mergeRefs } from \"../../utilities/index.js\";\nimport type { ImageProps } from \"./types.js\";\nimport { useImageLoadingStatus } from \"./useImageLoadingStatus.js\";\n\nexport const Image = forwardRef<HTMLImageElement, ImageProps>(\n ({ className, placeholder, alt, ...imageProperties }, ref) => {\n const [imageRef, imageLoaded] = useImageLoadingStatus();\n const [containerRef, dimensions] =\n useElementDimensions<HTMLDivElement>(400);\n\n const mergedImageRef = mergeRefs(ref, imageRef);\n\n return (\n <div\n ref={containerRef}\n className={clsx(\"jkl-image\", className, {\n \"jkl-image--loading\": !imageLoaded,\n })}\n >\n {/* Placeholder er bevisst uten loading og decoding for å vises umiddelbart */}\n <img\n className=\"jkl-image__placeholder\"\n alt={imageLoaded ? \"\" : alt}\n src={placeholder || imageProperties.src}\n />\n {/* biome-ignore lint/a11y/useAltText: Den har da vitterlig en alt-attributt? */}\n <img\n alt={alt}\n className=\"jkl-image__image\"\n data-testid=\"jkl-image__image\"\n ref={mergedImageRef}\n sizes={`${dimensions.width}px`}\n decoding=\"async\"\n loading=\"lazy\"\n {...imageProperties}\n />\n </div>\n );\n },\n);\n\nImage.displayName = \"Image\";\n"],"names":["Image","forwardRef","className","placeholder","alt","imageProperties","ref","imageRef","imageLoaded","useImageLoadingStatus","containerRef","dimensions","useElementDimensions","mergedImageRef","mergeRefs","jsxs","clsx","children","jsx","src","sizes","width","decoding","loading","displayName"],"mappings":"2YAOaA,EAAQC,EAAAA,WACjB,EAAGC,UAAAA,EAAWC,YAAAA,EAAaC,IAAAA,KAAQC,GAAmBC,KAClD,MAAOC,EAAUC,GAAeC,2BACzBC,EAAcC,GACjBC,EAAAA,qBAAqC,KAEnCC,EAAiBC,EAAAA,UAAUR,EAAKC,GAEtC,OACIQ,EAAAA,KAAC,MAAA,CACGT,IAAKI,EACLR,UAAWc,EAAAA,KAAK,YAAad,EAAW,CACpC,sBAAuBM,IAI3BS,SAAA,CAAAC,EAAAA,IAAC,MAAA,CACGhB,UAAU,yBACVE,IAAKI,EAAc,GAAKJ,EACxBe,IAAKhB,GAAeE,EAAgBc,MAGxCD,EAAAA,IAAC,MAAA,CACGd,IAAAA,EACAF,UAAU,mBACV,cAAY,mBACZI,IAAKO,EACLO,MAAO,GAAGT,EAAWU,UACrBC,SAAS,QACTC,QAAQ,UACJlB,SAOxBL,EAAMwB,YAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"NumberInput.cjs","sources":["../../../../src/components/number-input/NumberInput.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, {\n type ComponentType,\n forwardRef,\n useRef,\n useState,\n} from \"react\";\nimport { mergeRefs } from \"../../utilities/mergeRefs.js\";\nimport { MinusIcon, PlusIcon } from \"../icon/index.js\";\nimport { InputGroup } from \"../input-group/InputGroup.js\";\nimport type { NumberInputProps } from \"./types.js\";\n\ntype NumberInputValue = string | number | readonly string[] | undefined;\n\ntype StepDirection = \"increment\" | \"decrement\";\n\nconst stepperConfig: Record<\n StepDirection,\n { label: string; Icon: ComponentType }\n> = {\n decrement: { label: \"Senk verdien\", Icon: MinusIcon },\n increment: { label: \"Øk verdien\", Icon: PlusIcon },\n};\n\nfunction toNumeric(value: NumberInputValue): number {\n if (typeof value === \"number\") {\n return value;\n }\n if (typeof value === \"string\" && value.trim() !== \"\") {\n return Number(value);\n }\n return Number.NaN;\n}\n\ntype StepperButtonProps = {\n direction: StepDirection;\n disabled: boolean;\n onClick: () => void;\n};\n\nfunction StepperButton({ direction, disabled, onClick }: StepperButtonProps) {\n const { label, Icon } = stepperConfig[direction];\n\n return (\n <button\n type=\"button\"\n className=\"jkl-button jkl-button--ghost\"\n aria-label={label}\n data-direction={direction}\n onPointerDown={(event) => event.preventDefault()}\n onClick={onClick}\n disabled={disabled}\n >\n <span aria-hidden=\"true\">\n <Icon />\n </span>\n </button>\n );\n}\n\nexport const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(\n (props, ref) => {\n const {\n \"data-size\": dataSize,\n \"data-testautoid\": testAutoId,\n \"data-testid\": dataTestId,\n align = \"left\",\n id,\n label,\n className,\n style,\n errorLabel,\n helpLabel,\n inputClassName,\n labelProps,\n supportLabelProps,\n stepper = false,\n tooltip,\n description,\n width,\n onChange,\n ...rest\n } = props;\n const internalRef = useRef<HTMLInputElement>(null);\n const mergedRef = mergeRefs(internalRef, ref);\n const [uncontrolledValue, setUncontrolledValue] =\n useState<NumberInputValue>(rest.defaultValue);\n\n // I kontrollert bruk må vi lese direkte fra `value` for at disabled-\n // state på stepper-knappene skal følge prop-en i samme render. Bruker\n // intern state som fallback for ukontrollert bruk.\n const effectiveValue =\n rest.value !== undefined ? rest.value : uncontrolledValue;\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n if (rest.value === undefined) {\n setUncontrolledValue(event.target.value);\n }\n onChange?.(event);\n };\n\n const numericValue = toNumeric(effectiveValue);\n const minNumeric =\n rest.min !== undefined ? Number(rest.min) : Number.NaN;\n const maxNumeric =\n rest.max !== undefined ? Number(rest.max) : Number.NaN;\n const isAtOrBelowMin =\n Number.isFinite(numericValue) &&\n Number.isFinite(minNumeric) &&\n numericValue <= minNumeric;\n const isAtOrAboveMax =\n Number.isFinite(numericValue) &&\n Number.isFinite(maxNumeric) &&\n numericValue >= maxNumeric;\n\n const inputWrapperStyle =\n style || width\n ? {\n ...style,\n ...(width ? { width } : undefined),\n }\n : undefined;\n const inputGroupProps = {\n id,\n label,\n errorLabel,\n helpLabel,\n labelProps,\n supportLabelProps,\n tooltip,\n description,\n };\n\n const triggerStep = (direction: StepDirection) => {\n const input = internalRef.current;\n\n if (!input || input.disabled || input.readOnly) {\n return;\n }\n\n const previousValue = input.value;\n input.focus();\n\n try {\n if (direction === \"increment\") {\n input.stepUp();\n } else {\n input.stepDown();\n }\n } catch {\n return;\n }\n\n if (input.value === previousValue) {\n return;\n }\n\n input.dispatchEvent(new Event(\"input\", { bubbles: true }));\n };\n\n const stepperDisabled = rest.disabled || rest.readOnly;\n\n return (\n <InputGroup\n {...inputGroupProps}\n className={clsx(className, \"jkl-number-input\")}\n data-size={dataSize}\n data-testid={dataTestId ?? \"jkl-number-input\"}\n render={(inputProps) => (\n <div\n className={clsx(\"jkl-number-input__wrapper\", {\n \"jkl-number-input__wrapper--stepper\": stepper,\n })}\n data-invalid={inputProps[\"aria-invalid\"]}\n style={inputWrapperStyle}\n >\n {stepper && (\n <StepperButton\n direction=\"decrement\"\n disabled={stepperDisabled || isAtOrBelowMin}\n onClick={() => triggerStep(\"decrement\")}\n />\n )}\n <input\n {...inputProps}\n {...rest}\n ref={mergedRef}\n type=\"number\"\n onChange={handleChange}\n className={clsx(\n \"jkl-number-input__input\",\n {\n \"jkl-number-input__input--stepper\": stepper,\n \"jkl-number-input__input--align-right\":\n !stepper && align === \"right\",\n },\n inputClassName,\n )}\n data-testautoid={testAutoId}\n />\n {stepper && (\n <StepperButton\n direction=\"increment\"\n disabled={stepperDisabled || isAtOrAboveMax}\n onClick={() => triggerStep(\"increment\")}\n />\n )}\n </div>\n )}\n />\n );\n },\n);\n\nNumberInput.displayName = \"NumberInput\";\n"],"names":["stepperConfig","decrement","label","Icon","MinusIcon","increment","PlusIcon","StepperButton","direction","disabled","onClick","jsx","type","className","onPointerDown","event","preventDefault","children","NumberInput","forwardRef","props","ref","dataSize","testAutoId","dataTestId","align","id","style","errorLabel","helpLabel","inputClassName","labelProps","supportLabelProps","stepper","tooltip","description","width","onChange","rest","internalRef","useRef","mergedRef","mergeRefs","uncontrolledValue","setUncontrolledValue","useState","defaultValue","effectiveValue","value","handleChange","target","numericValue","trim","Number","NaN","toNumeric","minNumeric","min","maxNumeric","max","isAtOrBelowMin","isFinite","isAtOrAboveMax","inputWrapperStyle","inputGroupProps","triggerStep","input","current","readOnly","previousValue","focus","stepUp","stepDown","dispatchEvent","Event","bubbles","stepperDisabled","InputGroup","clsx","render","inputProps","jsxs","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"NumberInput.cjs","sources":["../../../../src/components/number-input/NumberInput.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, { type ComponentType, forwardRef, useRef, useState } from \"react\";\nimport { mergeRefs } from \"../../utilities/mergeRefs.js\";\nimport { MinusIcon, PlusIcon } from \"../icon/index.js\";\nimport { InputGroup } from \"../input-group/InputGroup.js\";\nimport type { NumberInputProps } from \"./types.js\";\n\ntype NumberInputValue = string | number | readonly string[] | undefined;\n\ntype StepDirection = \"increment\" | \"decrement\";\n\nconst stepperConfig: Record<\n StepDirection,\n { label: string; Icon: ComponentType }\n> = {\n decrement: { label: \"Senk verdien\", Icon: MinusIcon },\n increment: { label: \"Øk verdien\", Icon: PlusIcon },\n};\n\nfunction toNumeric(value: NumberInputValue): number {\n if (typeof value === \"number\") {\n return value;\n }\n if (typeof value === \"string\" && value.trim() !== \"\") {\n return Number(value);\n }\n return Number.NaN;\n}\n\ntype StepperButtonProps = {\n direction: StepDirection;\n disabled: boolean;\n onClick: () => void;\n};\n\nfunction StepperButton({ direction, disabled, onClick }: StepperButtonProps) {\n const { label, Icon } = stepperConfig[direction];\n\n return (\n <button\n type=\"button\"\n className=\"jkl-button jkl-button--ghost\"\n aria-label={label}\n data-direction={direction}\n onPointerDown={(event) => event.preventDefault()}\n onClick={onClick}\n disabled={disabled}\n >\n <span aria-hidden=\"true\">\n <Icon />\n </span>\n </button>\n );\n}\n\nexport const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(\n (props, ref) => {\n const {\n \"data-size\": dataSize,\n \"data-testautoid\": testAutoId,\n \"data-testid\": dataTestId,\n align = \"left\",\n id,\n label,\n className,\n style,\n errorLabel,\n helpLabel,\n inputClassName,\n labelProps,\n supportLabelProps,\n stepper = false,\n tooltip,\n description,\n width,\n onChange,\n ...rest\n } = props;\n const internalRef = useRef<HTMLInputElement>(null);\n const mergedRef = mergeRefs(internalRef, ref);\n const [uncontrolledValue, setUncontrolledValue] =\n useState<NumberInputValue>(rest.defaultValue);\n\n // I kontrollert bruk må vi lese direkte fra `value` for at disabled-\n // state på stepper-knappene skal følge prop-en i samme render. Bruker\n // intern state som fallback for ukontrollert bruk.\n const effectiveValue =\n rest.value !== undefined ? rest.value : uncontrolledValue;\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n if (rest.value === undefined) {\n setUncontrolledValue(event.target.value);\n }\n onChange?.(event);\n };\n\n const numericValue = toNumeric(effectiveValue);\n const minNumeric =\n rest.min !== undefined ? Number(rest.min) : Number.NaN;\n const maxNumeric =\n rest.max !== undefined ? Number(rest.max) : Number.NaN;\n const isAtOrBelowMin =\n Number.isFinite(numericValue) &&\n Number.isFinite(minNumeric) &&\n numericValue <= minNumeric;\n const isAtOrAboveMax =\n Number.isFinite(numericValue) &&\n Number.isFinite(maxNumeric) &&\n numericValue >= maxNumeric;\n\n const inputWrapperStyle =\n style || width\n ? {\n ...style,\n ...(width ? { width } : undefined),\n }\n : undefined;\n const inputGroupProps = {\n id,\n label,\n errorLabel,\n helpLabel,\n labelProps,\n supportLabelProps,\n tooltip,\n description,\n };\n\n const triggerStep = (direction: StepDirection) => {\n const input = internalRef.current;\n\n if (!input || input.disabled || input.readOnly) {\n return;\n }\n\n const previousValue = input.value;\n input.focus();\n\n try {\n if (direction === \"increment\") {\n input.stepUp();\n } else {\n input.stepDown();\n }\n } catch {\n return;\n }\n\n if (input.value === previousValue) {\n return;\n }\n\n input.dispatchEvent(new Event(\"input\", { bubbles: true }));\n };\n\n const stepperDisabled = rest.disabled || rest.readOnly;\n\n return (\n <InputGroup\n {...inputGroupProps}\n className={clsx(className, \"jkl-number-input\")}\n data-size={dataSize}\n data-testid={dataTestId ?? \"jkl-number-input\"}\n render={(inputProps) => (\n <div\n className={clsx(\"jkl-number-input__wrapper\", {\n \"jkl-number-input__wrapper--stepper\": stepper,\n })}\n data-invalid={inputProps[\"aria-invalid\"]}\n style={inputWrapperStyle}\n >\n {stepper && (\n <StepperButton\n direction=\"decrement\"\n disabled={stepperDisabled || isAtOrBelowMin}\n onClick={() => triggerStep(\"decrement\")}\n />\n )}\n <input\n {...inputProps}\n {...rest}\n ref={mergedRef}\n type=\"number\"\n onChange={handleChange}\n className={clsx(\n \"jkl-number-input__input\",\n {\n \"jkl-number-input__input--stepper\": stepper,\n \"jkl-number-input__input--align-right\":\n !stepper && align === \"right\",\n },\n inputClassName,\n )}\n data-testautoid={testAutoId}\n />\n {stepper && (\n <StepperButton\n direction=\"increment\"\n disabled={stepperDisabled || isAtOrAboveMax}\n onClick={() => triggerStep(\"increment\")}\n />\n )}\n </div>\n )}\n />\n );\n },\n);\n\nNumberInput.displayName = \"NumberInput\";\n"],"names":["stepperConfig","decrement","label","Icon","MinusIcon","increment","PlusIcon","StepperButton","direction","disabled","onClick","jsx","type","className","onPointerDown","event","preventDefault","children","NumberInput","forwardRef","props","ref","dataSize","testAutoId","dataTestId","align","id","style","errorLabel","helpLabel","inputClassName","labelProps","supportLabelProps","stepper","tooltip","description","width","onChange","rest","internalRef","useRef","mergedRef","mergeRefs","uncontrolledValue","setUncontrolledValue","useState","defaultValue","effectiveValue","value","handleChange","target","numericValue","trim","Number","NaN","toNumeric","minNumeric","min","maxNumeric","max","isAtOrBelowMin","isFinite","isAtOrAboveMax","inputWrapperStyle","inputGroupProps","triggerStep","input","current","readOnly","previousValue","focus","stepUp","stepDown","dispatchEvent","Event","bubbles","stepperDisabled","InputGroup","clsx","render","inputProps","jsxs","displayName"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("../../../clsx-E3yX_9sL.cjs");require("react");const t=require("../input-group/FieldGroup.cjs"),s=s=>e.jsx(t.FieldGroup,{...s,className:r.clsx("jkl-segmented-control",s.className)});s.displayName="Segmented Control",exports.SegmentedControl=s;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("../../../clsx-E3yX_9sL.cjs");require("react");const t=require("../input-group/FieldGroup.cjs"),s=s=>e.jsx(t.FieldGroup,{...s,className:r.clsx("jkl-segmented-control",s.className)});s.displayName="SegmentedControl",exports.SegmentedControl=s;
2
2
  //# sourceMappingURL=SegmentedControl.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"SegmentedControl.cjs","sources":["../../../../src/components/segmented-control/SegmentedControl.tsx"],"sourcesContent":["import { clsx } from \"clsx\";\nimport React from \"react\";\nimport { FieldGroup } from \"../input-group/FieldGroup.js\";\nimport type { SegmentedControlProps } from \"./types.js\";\n\nexport const SegmentedControl = (props: SegmentedControlProps) => {\n return (\n <FieldGroup\n {...props}\n className={clsx(\"jkl-segmented-control\", props.className)}\n />\n );\n};\n\nSegmentedControl.displayName = \"Segmented Control\";\n"],"names":["SegmentedControl","props","jsx","FieldGroup","className","clsx","displayName"],"mappings":"+NAKaA,EAAoBC,GAEzBC,EAAAA,IAACC,EAAAA,WAAA,IACOF,EACJG,UAAWC,EAAAA,KAAK,wBAAyBJ,EAAMG,aAK3DJ,EAAiBM,YAAc"}
1
+ {"version":3,"file":"SegmentedControl.cjs","sources":["../../../../src/components/segmented-control/SegmentedControl.tsx"],"sourcesContent":["import { clsx } from \"clsx\";\nimport React from \"react\";\nimport { FieldGroup } from \"../input-group/FieldGroup.js\";\nimport type { SegmentedControlProps } from \"./types.js\";\n\nexport const SegmentedControl = (props: SegmentedControlProps) => {\n return (\n <FieldGroup\n {...props}\n className={clsx(\"jkl-segmented-control\", props.className)}\n />\n );\n};\n\nSegmentedControl.displayName = \"SegmentedControl\";\n"],"names":["SegmentedControl","props","jsx","FieldGroup","className","clsx","displayName"],"mappings":"+NAKaA,EAAoBC,GAEzBC,EAAAA,IAACC,EAAAA,WAAA,IACOF,EACJG,UAAWC,EAAAA,KAAK,wBAAyBJ,EAAMG,aAK3DJ,EAAiBM,YAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"Option.cjs","sources":["../../../../src/components/select/Option.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type RefObject,\n type MouseEvent,\n forwardRef,\n useCallback,\n useEffect,\n useRef,\n} from \"react\";\nimport type { ValuePair } from \"../../utilities/valuePair.js\";\nimport { Flex } from \"../flex/Flex.js\";\nimport { Text } from \"../typography/Text.js\";\n\nexport type OptionProps = Omit<\n ComponentPropsWithoutRef<\"button\">,\n \"aria-selected\" | \"children\" | \"role\" | \"type\" | \"value\"\n> &\n ValuePair & {\n multiple?: boolean;\n selected?: boolean;\n selectRef: RefObject<HTMLSelectElement>;\n };\n\nexport const Option = forwardRef<HTMLButtonElement, OptionProps>(\n function Option(props, ref) {\n const {\n className = \"\",\n multiple = false,\n selected = false,\n selectRef,\n label,\n description,\n media,\n value,\n ...rest\n } = props;\n\n const mediaRef = useRef<HTMLSpanElement>(null);\n const labelRef = useRef<HTMLSpanElement>(null);\n\n const syncValueToSelect = useCallback(\n (event: KeyboardEvent | MouseEvent) => {\n const button = (\n event.target as HTMLElement\n ).closest<HTMLButtonElement>(\"button\");\n if (!button || !selectRef.current || selectRef.current.disabled)\n return;\n\n const option = Array.from(selectRef.current.options).find(\n (option) => option.value === button.value,\n );\n if (!option) return;\n\n option.selected = multiple ? !option.selected : true;\n selectRef.current.dispatchEvent(\n new Event(\"change\", { bubbles: true }),\n );\n },\n [selectRef, multiple],\n );\n\n useEffect(() => {\n if (!media || !labelRef.current || !mediaRef.current) return;\n const labelElement = labelRef.current;\n const mediaElement = mediaRef.current;\n const observer = new ResizeObserver(() => {\n mediaElement.style.setProperty(\n \"--media-size\",\n `${labelElement.offsetHeight}px`,\n );\n });\n observer.observe(labelElement);\n return () => observer.disconnect();\n }, [media]);\n\n return (\n <button\n ref={ref}\n // biome-ignore lint/a11y/useSemanticElements: vi kan ikke style option-elementet\n role=\"option\"\n type=\"button\"\n className={clsx(\"jkl-option\", className)}\n value={value}\n data-multiple={multiple || undefined}\n aria-selected={selected}\n {...rest}\n onClick={(event) => {\n rest.onClick?.(event);\n syncValueToSelect(event);\n }}\n >\n <Flex\n as=\"span\"\n direction=\"column\"\n gap=\"4\"\n className=\"jkl-option__label\"\n ref={labelRef}\n >\n <Text short as=\"span\">\n {label}\n </Text>\n {description && (\n <Text short subdued as=\"span\" size=\"xs\">\n {description}\n </Text>\n )}\n </Flex>\n {media && (\n <span className=\"jkl-option__media\" ref={mediaRef}>\n {media}\n </span>\n )}\n </button>\n );\n },\n);\n"],"names":["Option","forwardRef","props","ref","className","multiple","selected","selectRef","label","description","media","value","rest","mediaRef","useRef","labelRef","syncValueToSelect","useCallback","event","button","target","closest","current","disabled","option","Array","from","options","find","dispatchEvent","Event","bubbles","useEffect","labelElement","mediaElement","observer","ResizeObserver","style","setProperty","offsetHeight","observe","disconnect","jsxs","role","type","clsx","onClick","children","Flex","as","direction","gap","jsx","Text","short","subdued","size"],"mappings":"kPAwBaA,EAASC,EAAAA,WAClB,SAAgBC,EAAOC,GACnB,MACIC,UAAAA,EAAY,GACZC,SAAAA,GAAW,EACXC,SAAAA,GAAW,EACXC,UAAAA,EACAC,MAAAA,EACAC,YAAAA,EACAC,MAAAA,EACAC,MAAAA,KACGC,GACHV,EAEEW,EAAWC,EAAAA,OAAwB,MACnCC,EAAWD,EAAAA,OAAwB,MAEnCE,EAAoBC,EAAAA,YACrBC,IACG,MAAMC,EACFD,EAAME,OACRC,QAA2B,UAC7B,IAAKF,IAAWZ,EAAUe,SAAWf,EAAUe,QAAQC,SACnD,OAEJ,MAAMC,EAASC,MAAMC,KAAKnB,EAAUe,QAAQK,SAASC,KAChDJ,GAAWA,EAAOb,QAAUQ,EAAOR,OAEnCa,IAELA,EAAOlB,UAAWD,IAAYmB,EAAOlB,SACrCC,EAAUe,QAAQO,cACd,IAAIC,MAAM,SAAU,CAAEC,SAAS,OAGvC,CAACxB,EAAWF,IAGhB2B,OAAAA,EAAAA,UAAU,KACN,IAAKtB,IAAUK,EAASO,UAAYT,EAASS,QAAS,OACtD,MAAMW,EAAelB,EAASO,QACxBY,EAAerB,EAASS,QACxBa,EAAW,IAAIC,eAAe,KAChCF,EAAaG,MAAMC,YACf,eACA,GAAGL,EAAaM,oBAGxB,OAAAJ,EAASK,QAAQP,GACV,IAAME,EAASM,cACvB,CAAC/B,IAGAgC,EAAAA,KAAC,SAAA,CACGvC,IAAAA,EAEAwC,KAAK,SACLC,KAAK,SACLxC,UAAWyC,EAAAA,KAAK,aAAczC,GAC9BO,MAAAA,EACA,gBAAeN,QAAY,EAC3B,gBAAeC,KACXM,EACJkC,QAAU5B,IACNN,EAAKkC,UAAU5B,GACfF,EAAkBE,IAGtB6B,SAAA,CAAAL,EAAAA,KAACM,EAAAA,KAAA,CACGC,GAAG,OACHC,UAAU,SACVC,IAAI,IACJ/C,UAAU,oBACVD,IAAKY,EAELgC,SAAA,CAAAK,MAACC,EAAAA,KAAA,CAAKC,OAAK,EAACL,GAAG,OACVF,SAAAvC,IAEJC,GACG2C,EAAAA,IAACC,EAAAA,KAAA,CAAKC,OAAK,EAACC,SAAO,EAACN,GAAG,OAAOO,KAAK,KAC9BT,SAAAtC,OAIZC,GACG0C,EAAAA,IAAC,OAAA,CAAKhD,UAAU,oBAAoBD,IAAKU,EACpCkC,SAAArC,MAKrB"}
1
+ {"version":3,"file":"Option.cjs","sources":["../../../../src/components/select/Option.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type MouseEvent,\n type RefObject,\n forwardRef,\n useCallback,\n useEffect,\n useRef,\n} from \"react\";\nimport type { ValuePair } from \"../../utilities/valuePair.js\";\nimport { Flex } from \"../flex/Flex.js\";\nimport { Text } from \"../typography/Text.js\";\n\nexport type OptionProps = Omit<\n ComponentPropsWithoutRef<\"button\">,\n \"aria-selected\" | \"children\" | \"role\" | \"type\" | \"value\"\n> &\n ValuePair & {\n multiple?: boolean;\n selected?: boolean;\n selectRef: RefObject<HTMLSelectElement>;\n };\n\nexport const Option = forwardRef<HTMLButtonElement, OptionProps>(\n function Option(props, ref) {\n const {\n className = \"\",\n multiple = false,\n selected = false,\n selectRef,\n label,\n description,\n media,\n value,\n ...rest\n } = props;\n\n const mediaRef = useRef<HTMLSpanElement>(null);\n const labelRef = useRef<HTMLSpanElement>(null);\n\n const syncValueToSelect = useCallback(\n (event: KeyboardEvent | MouseEvent) => {\n const button = (\n event.target as HTMLElement\n ).closest<HTMLButtonElement>(\"button\");\n if (!button || !selectRef.current || selectRef.current.disabled)\n return;\n\n const option = Array.from(selectRef.current.options).find(\n (option) => option.value === button.value,\n );\n if (!option) return;\n\n option.selected = multiple ? !option.selected : true;\n selectRef.current.dispatchEvent(\n new Event(\"change\", { bubbles: true }),\n );\n },\n [selectRef, multiple],\n );\n\n useEffect(() => {\n if (!media || !labelRef.current || !mediaRef.current) return;\n const labelElement = labelRef.current;\n const mediaElement = mediaRef.current;\n const observer = new ResizeObserver(() => {\n mediaElement.style.setProperty(\n \"--media-size\",\n `${labelElement.offsetHeight}px`,\n );\n });\n observer.observe(labelElement);\n return () => observer.disconnect();\n }, [media]);\n\n return (\n <button\n ref={ref}\n // biome-ignore lint/a11y/useSemanticElements: vi kan ikke style option-elementet\n role=\"option\"\n type=\"button\"\n className={clsx(\"jkl-option\", className)}\n value={value}\n data-multiple={multiple || undefined}\n aria-selected={selected}\n {...rest}\n onClick={(event) => {\n rest.onClick?.(event);\n syncValueToSelect(event);\n }}\n >\n <Flex\n as=\"span\"\n direction=\"column\"\n gap=\"4\"\n className=\"jkl-option__label\"\n ref={labelRef}\n >\n <Text short as=\"span\">\n {label}\n </Text>\n {description && (\n <Text short subdued as=\"span\" size=\"xs\">\n {description}\n </Text>\n )}\n </Flex>\n {media && (\n <span className=\"jkl-option__media\" ref={mediaRef}>\n {media}\n </span>\n )}\n </button>\n );\n },\n);\n"],"names":["Option","forwardRef","props","ref","className","multiple","selected","selectRef","label","description","media","value","rest","mediaRef","useRef","labelRef","syncValueToSelect","useCallback","event","button","target","closest","current","disabled","option","Array","from","options","find","dispatchEvent","Event","bubbles","useEffect","labelElement","mediaElement","observer","ResizeObserver","style","setProperty","offsetHeight","observe","disconnect","jsxs","role","type","clsx","onClick","children","Flex","as","direction","gap","jsx","Text","short","subdued","size"],"mappings":"kPAwBaA,EAASC,EAAAA,WAClB,SAAgBC,EAAOC,GACnB,MACIC,UAAAA,EAAY,GACZC,SAAAA,GAAW,EACXC,SAAAA,GAAW,EACXC,UAAAA,EACAC,MAAAA,EACAC,YAAAA,EACAC,MAAAA,EACAC,MAAAA,KACGC,GACHV,EAEEW,EAAWC,EAAAA,OAAwB,MACnCC,EAAWD,EAAAA,OAAwB,MAEnCE,EAAoBC,EAAAA,YACrBC,IACG,MAAMC,EACFD,EAAME,OACRC,QAA2B,UAC7B,IAAKF,IAAWZ,EAAUe,SAAWf,EAAUe,QAAQC,SACnD,OAEJ,MAAMC,EAASC,MAAMC,KAAKnB,EAAUe,QAAQK,SAASC,KAChDJ,GAAWA,EAAOb,QAAUQ,EAAOR,OAEnCa,IAELA,EAAOlB,UAAWD,IAAYmB,EAAOlB,SACrCC,EAAUe,QAAQO,cACd,IAAIC,MAAM,SAAU,CAAEC,SAAS,OAGvC,CAACxB,EAAWF,IAGhB2B,OAAAA,EAAAA,UAAU,KACN,IAAKtB,IAAUK,EAASO,UAAYT,EAASS,QAAS,OACtD,MAAMW,EAAelB,EAASO,QACxBY,EAAerB,EAASS,QACxBa,EAAW,IAAIC,eAAe,KAChCF,EAAaG,MAAMC,YACf,eACA,GAAGL,EAAaM,oBAGxB,OAAAJ,EAASK,QAAQP,GACV,IAAME,EAASM,cACvB,CAAC/B,IAGAgC,EAAAA,KAAC,SAAA,CACGvC,IAAAA,EAEAwC,KAAK,SACLC,KAAK,SACLxC,UAAWyC,EAAAA,KAAK,aAAczC,GAC9BO,MAAAA,EACA,gBAAeN,QAAY,EAC3B,gBAAeC,KACXM,EACJkC,QAAU5B,IACNN,EAAKkC,UAAU5B,GACfF,EAAkBE,IAGtB6B,SAAA,CAAAL,EAAAA,KAACM,EAAAA,KAAA,CACGC,GAAG,OACHC,UAAU,SACVC,IAAI,IACJ/C,UAAU,oBACVD,IAAKY,EAELgC,SAAA,CAAAK,MAACC,EAAAA,KAAA,CAAKC,OAAK,EAACL,GAAG,OACVF,SAAAvC,IAEJC,GACG2C,EAAAA,IAACC,EAAAA,KAAA,CAAKC,OAAK,EAACC,SAAO,EAACN,GAAG,OAAOO,KAAK,KAC9BT,SAAAtC,OAIZC,GACG0C,EAAAA,IAAC,OAAA,CAAKhD,UAAU,oBAAoBD,IAAKU,EACpCkC,SAAArC,MAKrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"Select.cjs","sources":["../../../../src/components/select/Select.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport {\n type CSSProperties,\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n type FocusEvent,\n forwardRef,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useListNavigation } from \"../../hooks/index.js\";\nimport { mergeRefs } from \"../../utilities/mergeRefs.js\";\nimport { type ValuePair, getValuePair } from \"../../utilities/valuePair.js\";\nimport { Button } from \"../button/Button.js\";\nimport { Flex } from \"../flex/Flex.js\";\nimport { ArrowDownIcon, CloseIcon } from \"../icon/index.js\";\nimport { InputGroup } from \"../input-group/InputGroup.js\";\nimport type { InputGroupProps } from \"../input-group/types.js\";\nimport { Search } from \"../search/Search.js\";\nimport { Text } from \"../typography/Text.js\";\nimport { Title } from \"../typography/Title.js\";\nimport { Option } from \"./Option.js\";\nimport { autofocus, getButtonText, getReactNodeText } from \"./utils.js\";\nimport type { DataTestAutoId } from \"../../utilities/types.js\";\n\nexport type SelectProps = Omit<InputGroupProps, \"children\" | \"inline\"> &\n DataTestAutoId &\n Omit<ComponentPropsWithoutRef<\"select\">, \"size\" | \"children\"> & {\n width?: string;\n items: (string | ValuePair)[];\n placeholder?: string;\n } & (\n | {\n searchable: true;\n onSearch?: (searchTerm: string) => void;\n filterFunction?: (item: ValuePair, searchTerm: string) => boolean;\n }\n | {\n searchable?: false;\n onSearch?: never;\n filterFunction?: never;\n }\n );\n\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(\n function Select(props, externalRef) {\n const {\n label,\n errorLabel,\n helpLabel,\n labelProps,\n supportLabelProps,\n tooltip,\n description,\n style,\n className,\n id: idProp,\n items: rawItems,\n multiple = false,\n searchable = false,\n onSearch,\n filterFunction,\n placeholder,\n width,\n value,\n \"data-testautoid\": dataTestautoid,\n \"data-size\": size,\n ...elementProps\n } = props;\n\n const popoverRef = useRef<HTMLDivElement>(null);\n const selectRef = useRef<HTMLSelectElement>(null);\n const unifiedRef = mergeRefs(externalRef, selectRef);\n\n const baseId = `jkl-select-${useId()}`;\n const selectId = idProp ?? baseId;\n const popoverId = `${selectId}-popover`;\n\n const [filter, setFilter] = useState(\"\");\n const [selected, setSelected] = useState(() => new Set<string>());\n\n useListNavigation({ ref: popoverRef, disableTypeahead: searchable });\n\n const items = rawItems.map(getValuePair);\n const filteredItems =\n searchable && filter\n ? items.filter((item) =>\n filterFunction\n ? filterFunction(item, filter)\n : item.label\n .toLowerCase()\n .includes(filter.toLowerCase()),\n )\n : items;\n\n const showPlaceholder =\n selected.size === 0 || (selected.size === 1 && placeholder && selected.has(\"\"));\n const placeholderText = placeholder || \"Ingen valgt\";\n const buttonText = getButtonText(selected, items, placeholderText);\n\n /**\n * Setter event-lyttere for å synkronisere verdier i det skjulte select-elementet med\n * visningen i vår komponent, samt nullstilling av filter når menyen lukkes.\n */\n // biome-ignore lint/correctness/useExhaustiveDependencies:\n useLayoutEffect(() => {\n const select = selectRef.current;\n const popover = popoverRef.current;\n if (!select) return;\n\n const syncSelected = () => {\n setSelected(\n new Set(Array.from(select.selectedOptions, (o) => o.value)),\n );\n };\n\n const resetFilterOnClose = (event: ToggleEvent) => {\n if (event.newState === \"closed\") setFilter(\"\");\n };\n\n syncSelected();\n popover?.addEventListener(\"toggle\", resetFilterOnClose);\n select.addEventListener(\"change\", syncSelected);\n\n return () => {\n select.removeEventListener(\"change\", syncSelected);\n popover?.removeEventListener(\"toggle\", resetFilterOnClose);\n };\n }, [multiple, rawItems]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Oppdaterer visning når value settes\n useLayoutEffect(() => {\n setSelected(\n new Set(\n Array.from(\n selectRef.current?.selectedOptions ?? [],\n (o) => o.value,\n ),\n ),\n );\n }, [value, elementProps.defaultValue]);\n\n /**\n * Sørger for at menyen kan åpnes med piltastene slik som i native select\n */\n const openWithArrows = (event: KeyboardEvent) => {\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n popoverRef.current?.showPopover?.();\n }\n };\n\n /**\n * Fyrer av focus- eller blur-event på det skjulte select-elementet når\n * fokus går inn eller ut av komponenten, slik at f.eks. react-hook-form\n * oppdaterer sin state riktig.\n */\n const syncFocus = (event: FocusEvent) => {\n const sel = selectRef.current;\n if (!popoverRef.current?.contains(event.relatedTarget)) {\n if (!sel) return;\n if ([\"focus\", \"focusin\"].includes(event.type)) {\n sel.dispatchEvent(new Event(\"focusin\", { bubbles: true }));\n sel.dispatchEvent(new Event(\"focus\", { bubbles: true }));\n } else if ([\"blur\", \"focusout\"].includes(event.type)) {\n sel.dispatchEvent(new Event(\"focusout\", { bubbles: true }));\n sel.dispatchEvent(new Event(\"blur\", { bubbles: true }));\n }\n }\n };\n\n return (\n <InputGroup\n id={selectId}\n label={label}\n errorLabel={errorLabel}\n helpLabel={helpLabel}\n labelProps={labelProps}\n supportLabelProps={supportLabelProps}\n tooltip={tooltip}\n description={description}\n style={style}\n data-testautoid={dataTestautoid}\n data-size={size}\n className={clsx(\"jkl-select\", className)}\n render={(inputProps) => (\n <>\n <button\n aria-label={`${showPlaceholder ? placeholderText : buttonText}, ${getReactNodeText(label)}`}\n className=\"jkl-select__button\"\n data-testid=\"jkl-select__button\"\n disabled={elementProps.disabled}\n type=\"button\"\n // @ts-ignore\n popovertarget={popoverId}\n style={{ \"--width\": width } as CSSProperties}\n onKeyDown={openWithArrows}\n onFocus={syncFocus}\n onBlur={syncFocus}\n {...inputProps}\n >\n {showPlaceholder ? placeholderText : buttonText}\n <ArrowDownIcon />\n </button>\n <Flex\n direction=\"column\"\n gap=\"16\"\n ref={popoverRef}\n // @ts-ignore\n popover=\"auto\"\n id={popoverId}\n className=\"jkl-select__popover\"\n aria-label={getReactNodeText(label)}\n >\n <Flex\n as=\"header\"\n alignItems=\"start\"\n justifyContent=\"space-between\"\n gap=\"8\"\n >\n <Title\n size=\"m\"\n as=\"h3\"\n id={`${selectId}-title`}\n >\n {label}\n </Title>\n <Button\n type=\"button\"\n variant=\"ghost\"\n icon={<CloseIcon />}\n aria-label=\"Lukk\"\n // @ts-ignore\n popovertarget={popoverId}\n popovertargetaction=\"hide\"\n />\n </Flex>\n {searchable && (\n <Search\n value={filter}\n onChange={(e) => {\n setFilter(e.target.value);\n onSearch?.(e.target.value);\n }}\n ref={autofocus(searchable)}\n autoComplete=\"off\"\n labelProps={{ srOnly: true }}\n label=\"Søk\"\n placeholder=\"Søk...\"\n width=\"100%\"\n className=\"jkl-spacing-8--bottom\"\n />\n )}\n <Flex\n direction=\"column\"\n gap=\"8\"\n // biome-ignore lint/a11y/useSemanticElements: Vi reimplementerer select\n role=\"listbox\"\n aria-multiselectable={multiple}\n aria-labelledby={`${selectId}-title`}\n >\n {filteredItems.map((pair, index) => (\n <Option\n {...pair}\n key={pair.value}\n selected={selected.has(pair.value)}\n multiple={multiple}\n selectRef={selectRef}\n // @ts-ignore\n popovertarget={\n multiple ? undefined : popoverId\n }\n popovertargetaction={\n multiple ? undefined : \"hide\"\n }\n ref={autofocus(() => {\n if (searchable) return false;\n if (showPlaceholder)\n return index === 0;\n return (\n selected.has(pair.value) &&\n filteredItems.findIndex((p) =>\n selected.has(p.value),\n ) === index\n );\n })}\n />\n ))}\n {searchable && !filteredItems.length && (\n <Text short>Ingen treff</Text>\n )}\n </Flex>\n {multiple && (\n <Button\n type=\"button\"\n variant=\"primary\"\n // @ts-ignore\n popovertarget={popoverId}\n popovertargetaction=\"hide\"\n >\n Bekreft\n </Button>\n )}\n </Flex>\n <select\n defaultValue={\n !multiple && value === undefined && placeholder\n ? \"\"\n : undefined\n }\n {...elementProps}\n tabIndex={-1}\n value={value}\n multiple={multiple}\n ref={unifiedRef}\n aria-labelledby={inputProps.id}\n >\n {!multiple && placeholder && (\n <option value=\"\" disabled>\n {placeholder}\n </option>\n )}\n {items.map((item) => (\n <option key={item.value} value={item.value}>\n {item.label}\n </option>\n ))}\n </select>\n </>\n )}\n />\n );\n },\n);\n\nSelect.displayName = \"Select\";\n"],"names":["Select","forwardRef","props","externalRef","label","errorLabel","helpLabel","labelProps","supportLabelProps","tooltip","description","style","className","id","idProp","items","rawItems","multiple","searchable","onSearch","filterFunction","placeholder","width","value","dataTestautoid","size","elementProps","popoverRef","useRef","selectRef","unifiedRef","mergeRefs","baseId","useId","selectId","popoverId","filter","setFilter","useState","selected","setSelected","Set","useListNavigation","ref","disableTypeahead","map","getValuePair","filteredItems","item","toLowerCase","includes","showPlaceholder","has","placeholderText","buttonText","getButtonText","useLayoutEffect","select","current","popover","syncSelected","Array","from","selectedOptions","o","resetFilterOnClose","event","newState","addEventListener","removeEventListener","defaultValue","openWithArrows","key","preventDefault","showPopover","syncFocus","sel","contains","relatedTarget","type","dispatchEvent","Event","bubbles","jsx","InputGroup","clsx","render","inputProps","jsxs","Fragment","children","getReactNodeText","disabled","popovertarget","onKeyDown","onFocus","onBlur","ArrowDownIcon","Flex","direction","gap","as","alignItems","justifyContent","Title","Button","variant","icon","CloseIcon","popovertargetaction","Search","onChange","e","target","autofocus","autoComplete","srOnly","role","pair","index","createElement","Option","findIndex","p","length","Text","short","tabIndex","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"Select.cjs","sources":["../../../../src/components/select/Select.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport {\n type CSSProperties,\n type ComponentPropsWithoutRef,\n type FocusEvent,\n type KeyboardEvent,\n forwardRef,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useListNavigation } from \"../../hooks/index.js\";\nimport { mergeRefs } from \"../../utilities/mergeRefs.js\";\nimport type { DataTestAutoId } from \"../../utilities/types.js\";\nimport { type ValuePair, getValuePair } from \"../../utilities/valuePair.js\";\nimport { Button } from \"../button/Button.js\";\nimport { Flex } from \"../flex/Flex.js\";\nimport { ArrowDownIcon, CloseIcon } from \"../icon/index.js\";\nimport { InputGroup } from \"../input-group/InputGroup.js\";\nimport type { InputGroupProps } from \"../input-group/types.js\";\nimport { Search } from \"../search/Search.js\";\nimport { Text } from \"../typography/Text.js\";\nimport { Title } from \"../typography/Title.js\";\nimport { Option } from \"./Option.js\";\nimport { autofocus, getButtonText, getReactNodeText } from \"./utils.js\";\n\nexport type SelectProps = Omit<InputGroupProps, \"children\" | \"inline\"> &\n DataTestAutoId &\n Omit<ComponentPropsWithoutRef<\"select\">, \"size\" | \"children\"> & {\n width?: string;\n items: (string | ValuePair)[];\n placeholder?: string;\n } & (\n | {\n searchable: true;\n onSearch?: (searchTerm: string) => void;\n filterFunction?: (item: ValuePair, searchTerm: string) => boolean;\n }\n | {\n searchable?: false;\n onSearch?: never;\n filterFunction?: never;\n }\n );\n\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(\n function Select(props, externalRef) {\n const {\n label,\n errorLabel,\n helpLabel,\n labelProps,\n supportLabelProps,\n tooltip,\n description,\n style,\n className,\n id: idProp,\n items: rawItems,\n multiple = false,\n searchable = false,\n onSearch,\n filterFunction,\n placeholder,\n width,\n value,\n \"data-testautoid\": dataTestautoid,\n \"data-size\": size,\n ...elementProps\n } = props;\n\n const popoverRef = useRef<HTMLDivElement>(null);\n const selectRef = useRef<HTMLSelectElement>(null);\n const unifiedRef = mergeRefs(externalRef, selectRef);\n\n const baseId = `jkl-select-${useId()}`;\n const selectId = idProp ?? baseId;\n const popoverId = `${selectId}-popover`;\n\n const [filter, setFilter] = useState(\"\");\n const [selected, setSelected] = useState(() => new Set<string>());\n\n useListNavigation({ ref: popoverRef, disableTypeahead: searchable });\n\n const items = rawItems.map(getValuePair);\n const filteredItems =\n searchable && filter\n ? items.filter((item) =>\n filterFunction\n ? filterFunction(item, filter)\n : item.label\n .toLowerCase()\n .includes(filter.toLowerCase()),\n )\n : items;\n\n const showPlaceholder =\n selected.size === 0 ||\n (selected.size === 1 && placeholder && selected.has(\"\"));\n const placeholderText = placeholder || \"Ingen valgt\";\n const buttonText = getButtonText(selected, items, placeholderText);\n\n /**\n * Setter event-lyttere for å synkronisere verdier i det skjulte select-elementet med\n * visningen i vår komponent, samt nullstilling av filter når menyen lukkes.\n */\n // biome-ignore lint/correctness/useExhaustiveDependencies:\n useLayoutEffect(() => {\n const select = selectRef.current;\n const popover = popoverRef.current;\n if (!select) return;\n\n const syncSelected = () => {\n setSelected(\n new Set(Array.from(select.selectedOptions, (o) => o.value)),\n );\n };\n\n const resetFilterOnClose = (event: ToggleEvent) => {\n if (event.newState === \"closed\") setFilter(\"\");\n };\n\n syncSelected();\n popover?.addEventListener(\"toggle\", resetFilterOnClose);\n select.addEventListener(\"change\", syncSelected);\n\n return () => {\n select.removeEventListener(\"change\", syncSelected);\n popover?.removeEventListener(\"toggle\", resetFilterOnClose);\n };\n }, [multiple, rawItems]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Oppdaterer visning når value settes\n useLayoutEffect(() => {\n setSelected(\n new Set(\n Array.from(\n selectRef.current?.selectedOptions ?? [],\n (o) => o.value,\n ),\n ),\n );\n }, [value, elementProps.defaultValue]);\n\n /**\n * Sørger for at menyen kan åpnes med piltastene slik som i native select\n */\n const openWithArrows = (event: KeyboardEvent) => {\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n popoverRef.current?.showPopover?.();\n }\n };\n\n /**\n * Fyrer av focus- eller blur-event på det skjulte select-elementet når\n * fokus går inn eller ut av komponenten, slik at f.eks. react-hook-form\n * oppdaterer sin state riktig.\n */\n const syncFocus = (event: FocusEvent) => {\n const sel = selectRef.current;\n if (!popoverRef.current?.contains(event.relatedTarget)) {\n if (!sel) return;\n if ([\"focus\", \"focusin\"].includes(event.type)) {\n sel.dispatchEvent(new Event(\"focusin\", { bubbles: true }));\n sel.dispatchEvent(new Event(\"focus\", { bubbles: true }));\n } else if ([\"blur\", \"focusout\"].includes(event.type)) {\n sel.dispatchEvent(new Event(\"focusout\", { bubbles: true }));\n sel.dispatchEvent(new Event(\"blur\", { bubbles: true }));\n }\n }\n };\n\n return (\n <InputGroup\n id={selectId}\n label={label}\n errorLabel={errorLabel}\n helpLabel={helpLabel}\n labelProps={labelProps}\n supportLabelProps={supportLabelProps}\n tooltip={tooltip}\n description={description}\n style={style}\n data-testautoid={dataTestautoid}\n data-size={size}\n className={clsx(\"jkl-select\", className)}\n render={(inputProps) => (\n <>\n <button\n aria-label={`${showPlaceholder ? placeholderText : buttonText}, ${getReactNodeText(label)}`}\n className=\"jkl-select__button\"\n data-testid=\"jkl-select__button\"\n disabled={elementProps.disabled}\n type=\"button\"\n // @ts-ignore\n popovertarget={popoverId}\n style={{ \"--width\": width } as CSSProperties}\n onKeyDown={openWithArrows}\n onFocus={syncFocus}\n onBlur={syncFocus}\n {...inputProps}\n >\n {showPlaceholder ? placeholderText : buttonText}\n <ArrowDownIcon />\n </button>\n <Flex\n direction=\"column\"\n gap=\"16\"\n ref={popoverRef}\n // @ts-ignore\n popover=\"auto\"\n id={popoverId}\n className=\"jkl-select__popover\"\n aria-label={getReactNodeText(label)}\n >\n <Flex\n as=\"header\"\n alignItems=\"start\"\n justifyContent=\"space-between\"\n gap=\"8\"\n >\n <Title\n size=\"m\"\n as=\"h3\"\n id={`${selectId}-title`}\n >\n {label}\n </Title>\n <Button\n type=\"button\"\n variant=\"ghost\"\n icon={<CloseIcon />}\n aria-label=\"Lukk\"\n // @ts-ignore\n popovertarget={popoverId}\n popovertargetaction=\"hide\"\n />\n </Flex>\n {searchable && (\n <Search\n value={filter}\n onChange={(e) => {\n setFilter(e.target.value);\n onSearch?.(e.target.value);\n }}\n ref={autofocus(searchable)}\n autoComplete=\"off\"\n labelProps={{ srOnly: true }}\n label=\"Søk\"\n placeholder=\"Søk...\"\n width=\"100%\"\n className=\"jkl-spacing-8--bottom\"\n />\n )}\n <Flex\n direction=\"column\"\n gap=\"8\"\n // biome-ignore lint/a11y/useSemanticElements: Vi reimplementerer select\n role=\"listbox\"\n aria-multiselectable={multiple}\n aria-labelledby={`${selectId}-title`}\n >\n {filteredItems.map((pair, index) => (\n <Option\n {...pair}\n key={pair.value}\n selected={selected.has(pair.value)}\n multiple={multiple}\n selectRef={selectRef}\n // @ts-ignore\n popovertarget={\n multiple ? undefined : popoverId\n }\n popovertargetaction={\n multiple ? undefined : \"hide\"\n }\n ref={autofocus(() => {\n if (searchable) return false;\n if (showPlaceholder)\n return index === 0;\n return (\n selected.has(pair.value) &&\n filteredItems.findIndex((p) =>\n selected.has(p.value),\n ) === index\n );\n })}\n />\n ))}\n {searchable && !filteredItems.length && (\n <Text short>Ingen treff</Text>\n )}\n </Flex>\n {multiple && (\n <Button\n type=\"button\"\n variant=\"primary\"\n // @ts-ignore\n popovertarget={popoverId}\n popovertargetaction=\"hide\"\n >\n Bekreft\n </Button>\n )}\n </Flex>\n <select\n defaultValue={\n !multiple && value === undefined && placeholder\n ? \"\"\n : undefined\n }\n {...elementProps}\n tabIndex={-1}\n value={value}\n multiple={multiple}\n ref={unifiedRef}\n aria-labelledby={inputProps.id}\n >\n {!multiple && placeholder && (\n <option value=\"\" disabled>\n {placeholder}\n </option>\n )}\n {items.map((item) => (\n <option key={item.value} value={item.value}>\n {item.label}\n </option>\n ))}\n </select>\n </>\n )}\n />\n );\n },\n);\n\nSelect.displayName = \"Select\";\n"],"names":["Select","forwardRef","props","externalRef","label","errorLabel","helpLabel","labelProps","supportLabelProps","tooltip","description","style","className","id","idProp","items","rawItems","multiple","searchable","onSearch","filterFunction","placeholder","width","value","dataTestautoid","size","elementProps","popoverRef","useRef","selectRef","unifiedRef","mergeRefs","baseId","useId","selectId","popoverId","filter","setFilter","useState","selected","setSelected","Set","useListNavigation","ref","disableTypeahead","map","getValuePair","filteredItems","item","toLowerCase","includes","showPlaceholder","has","placeholderText","buttonText","getButtonText","useLayoutEffect","select","current","popover","syncSelected","Array","from","selectedOptions","o","resetFilterOnClose","event","newState","addEventListener","removeEventListener","defaultValue","openWithArrows","key","preventDefault","showPopover","syncFocus","sel","contains","relatedTarget","type","dispatchEvent","Event","bubbles","jsx","InputGroup","clsx","render","inputProps","jsxs","Fragment","children","getReactNodeText","disabled","popovertarget","onKeyDown","onFocus","onBlur","ArrowDownIcon","Flex","direction","gap","as","alignItems","justifyContent","Title","Button","variant","icon","CloseIcon","popovertargetaction","Search","onChange","e","target","autofocus","autoComplete","srOnly","role","pair","index","createElement","Option","findIndex","p","length","Text","short","tabIndex","displayName"],"mappings":"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"}