@fremtind/jokul 6.0.0-next.4 → 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 (33) hide show
  1. package/build/cjs/components/autosuggest/Autosuggest.cjs.map +1 -1
  2. package/build/cjs/components/autosuggest/Autosuggest.d.cts +5 -0
  3. package/build/cjs/components/combobox/Combobox.cjs.map +1 -1
  4. package/build/cjs/components/combobox/Combobox.d.cts +4 -0
  5. package/build/es/components/autosuggest/Autosuggest.d.ts +5 -0
  6. package/build/es/components/autosuggest/Autosuggest.js.map +1 -1
  7. package/build/es/components/combobox/Combobox.d.ts +4 -0
  8. package/build/es/components/combobox/Combobox.js.map +1 -1
  9. package/package.json +1 -1
  10. package/styles/components/countdown/countdown.css +2 -2
  11. package/styles/components/countdown/countdown.min.css +1 -1
  12. package/styles/components/feedback/feedback.css +2 -2
  13. package/styles/components/feedback/feedback.min.css +1 -1
  14. package/styles/components/file-input/file-input.css +9 -9
  15. package/styles/components/file-input/file-input.min.css +1 -1
  16. package/styles/components/input-group/input-group.css +2 -2
  17. package/styles/components/input-group/input-group.min.css +1 -1
  18. package/styles/components/loader/loader.css +6 -6
  19. package/styles/components/loader/loader.min.css +1 -1
  20. package/styles/components/loader/skeleton-loader.css +3 -3
  21. package/styles/components/loader/skeleton-loader.min.css +1 -1
  22. package/styles/components/message/message.css +2 -2
  23. package/styles/components/message/message.min.css +1 -1
  24. package/styles/components/progress-bar/progress-bar.css +1 -1
  25. package/styles/components/progress-bar/progress-bar.min.css +1 -1
  26. package/styles/components/segmented-control/segmented-control.css +2 -2
  27. package/styles/components/segmented-control/segmented-control.min.css +1 -1
  28. package/styles/components/system-message/system-message.css +2 -2
  29. package/styles/components/system-message/system-message.min.css +1 -1
  30. package/styles/components/toast/toast.css +4 -4
  31. package/styles/components/toast/toast.min.css +1 -1
  32. package/styles/components.css +24 -24
  33. package/styles/components.min.css +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,7 @@
1
1
  import { AutosuggestProps } from './types.js';
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":"Autosuggest.js","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":["Autosuggest","allItems","onChange","onConfirm","onInputValueChange","onStateChange","value","isOpen","rest","hits","setHits","useState","useEffect","jsx","BaseAutosuggest","items","itemToString","item","downshiftProps","selectedItem","changes","inputValue","filter"],"mappings":"gKAMO,MAAMA,EAAc,EACvBC,SAAAA,EACAC,SAAAA,EAAW,OAGXC,UAAAA,EAAY,OAGZC,mBAAAA,EACAC,cAAAA,EACAC,MAAAA,EACAC,OAAAA,KACGC,MAEH,MAAOC,EAAMC,GAAWC,EAASV,GAEjC,OAAAW,EAAU,IAAMF,EAAQT,GAAW,CAACA,IAiBhCY,EAACC,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,EAAOrB,EAAUmB,EAAQC,cAgB7Bd,OAAAA"}
1
+ {"version":3,"file":"Autosuggest.js","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":["Autosuggest","allItems","onChange","onConfirm","onInputValueChange","onStateChange","value","isOpen","rest","hits","setHits","useState","useEffect","jsx","BaseAutosuggest","items","itemToString","item","downshiftProps","selectedItem","changes","inputValue","filter"],"mappings":"gKAWO,MAAMA,EAAc,EACvBC,SAAAA,EACAC,SAAAA,EAAW,OAGXC,UAAAA,EAAY,OAGZC,mBAAAA,EACAC,cAAAA,EACAC,MAAAA,EACAC,OAAAA,KACGC,MAEH,MAAOC,EAAMC,GAAWC,EAASV,GAEjC,OAAAW,EAAU,IAAMF,EAAQT,GAAW,CAACA,IAiBhCY,EAACC,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,EAAOrB,EAAUmB,EAAQC,cAgB7Bd,OAAAA"}
@@ -1,4 +1,8 @@
1
1
  import { FC } from 'react';
2
2
  import { ComboboxProps, ComboboxValuePair } from './types.js';
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 +1 @@
1
- {"version":3,"file":"Combobox.js","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.js","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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fremtind/jokul",
3
- "version": "6.0.0-next.4",
3
+ "version": "6.0.0-next.5",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": "^22.22.2 || ^24.15.0 || ^26.0.0"
@@ -26,10 +26,10 @@
26
26
  }
27
27
  }
28
28
  .jkl-countdown__tracker {
29
- animation: jkl-downcount-uk2kl2p var(--duration) linear forwards;
29
+ animation: jkl-downcount-uvdoup5 var(--duration) linear forwards;
30
30
  animation-play-state: var(--play-state, running);
31
31
  }
32
- @keyframes jkl-downcount-uk2kl2p {
32
+ @keyframes jkl-downcount-uvdoup5 {
33
33
  from {
34
34
  width: 100%;
35
35
  }
@@ -1 +1 @@
1
- @layer jokul.components{.jkl-countdown{--track-color:var(--jkl-color-border-subdued);--bar-color:var(--jkl-color-border-strong);--bar-height:0.25rem;background-color:var(--track-color);border-radius:6.25rem;height:var(--bar-height);width:100%;overflow:hidden}.jkl-countdown__tracker{display:block;height:var(--bar-height);background-color:var(--bar-color)}@media screen and (forced-colors:active){.jkl-countdown{background-color:Canvas}.jkl-countdown__tracker{background-color:CanvasText}}.jkl-countdown__tracker{animation:jkl-downcount-uk2kl2p var(--duration) linear forwards;animation-play-state:var(--play-state,running)}@keyframes jkl-downcount-uk2kl2p{0%{width:100%}to{width:0}}}
1
+ @layer jokul.components{.jkl-countdown{--track-color:var(--jkl-color-border-subdued);--bar-color:var(--jkl-color-border-strong);--bar-height:0.25rem;background-color:var(--track-color);border-radius:6.25rem;height:var(--bar-height);width:100%;overflow:hidden}.jkl-countdown__tracker{display:block;height:var(--bar-height);background-color:var(--bar-color)}@media screen and (forced-colors:active){.jkl-countdown{background-color:Canvas}.jkl-countdown__tracker{background-color:CanvasText}}.jkl-countdown__tracker{animation:jkl-downcount-uvdoup5 var(--duration) linear forwards;animation-play-state:var(--play-state,running)}@keyframes jkl-downcount-uvdoup5{0%{width:100%}to{width:0}}}
@@ -20,12 +20,12 @@
20
20
  font: var(--jkl-text-style-paragraph-small);
21
21
  }
22
22
  .jkl-feedback__fade-in {
23
- animation: jkl-show-un3pvyv 0.25s ease-out;
23
+ animation: jkl-show-u0pwu4j 0.25s ease-out;
24
24
  }
25
25
  .jkl-feedback__buttons {
26
26
  display: flex;
27
27
  }
28
- @keyframes jkl-show-un3pvyv {
28
+ @keyframes jkl-show-u0pwu4j {
29
29
  from {
30
30
  transform: translate3d(0, 0.5rem, 0);
31
31
  opacity: 0;
@@ -1 +1 @@
1
- @layer jokul.components{.jkl-feedback{max-width:34.375rem}.jkl-feedback__submit-wrapper{width:100%;transition-property:height;transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-expressive)}.jkl-feedback__submit-wrapper--hidden{display:none}.jkl-feedback__step-counter{color:var(--jkl-color-text-subdued);margin-bottom:var(--jkl-unit-20);font:var(--jkl-text-style-paragraph-small)}.jkl-feedback__fade-in{animation:jkl-show-un3pvyv .25s ease-out}.jkl-feedback__buttons{display:flex}@keyframes jkl-show-un3pvyv{0%{transform:translate3d(0,.5rem,0);opacity:0}}.jkl-feedback-smileys{margin-top:var(--jkl-unit-10);display:flex;justify-content:space-between;width:100%;max-width:22.5rem;flex-wrap:nowrap;gap:var(--jkl-spacing-12)}.jkl-feedback-smiley-option{display:inline-block;position:relative;cursor:pointer;height:2.5rem;width:2.5rem;color:var(--jkl-color-text-subdued);transform:translateZ(0);transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-productive);transition-property:transform,color}@media screen and (forced-colors:active){.jkl-feedback-smiley-option,.jkl-feedback-smiley-option path,.jkl-feedback-smiley-option svg{stroke:ButtonFace;fill:ButtonText}}.jkl-feedback-smiley-option:after,.jkl-feedback-smiley-option:before{content:"";position:absolute;border-radius:50%;opacity:0;transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-productive);transition-property:opacity}.jkl-feedback-smiley-option:before{inset:0;box-shadow:0 .125rem 1.875rem #0000001a}.jkl-feedback-smiley-option:hover{color:var(--jkl-color-text-default)}input:checked+.jkl-feedback-smiley-option{color:var(--jkl-color-text-default);transform:translate3d(0,-20%,0)}input:checked+.jkl-feedback-smiley-option:before{opacity:1}input:focus-visible+.jkl-feedback-smiley-option{border-radius:var(--jkl-border-radius-full);outline:3px solid var(--jkl-color-border-strong);outline-offset:3px}}
1
+ @layer jokul.components{.jkl-feedback{max-width:34.375rem}.jkl-feedback__submit-wrapper{width:100%;transition-property:height;transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-expressive)}.jkl-feedback__submit-wrapper--hidden{display:none}.jkl-feedback__step-counter{color:var(--jkl-color-text-subdued);margin-bottom:var(--jkl-unit-20);font:var(--jkl-text-style-paragraph-small)}.jkl-feedback__fade-in{animation:jkl-show-u0pwu4j .25s ease-out}.jkl-feedback__buttons{display:flex}@keyframes jkl-show-u0pwu4j{0%{transform:translate3d(0,.5rem,0);opacity:0}}.jkl-feedback-smileys{margin-top:var(--jkl-unit-10);display:flex;justify-content:space-between;width:100%;max-width:22.5rem;flex-wrap:nowrap;gap:var(--jkl-spacing-12)}.jkl-feedback-smiley-option{display:inline-block;position:relative;cursor:pointer;height:2.5rem;width:2.5rem;color:var(--jkl-color-text-subdued);transform:translateZ(0);transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-productive);transition-property:transform,color}@media screen and (forced-colors:active){.jkl-feedback-smiley-option,.jkl-feedback-smiley-option path,.jkl-feedback-smiley-option svg{stroke:ButtonFace;fill:ButtonText}}.jkl-feedback-smiley-option:after,.jkl-feedback-smiley-option:before{content:"";position:absolute;border-radius:50%;opacity:0;transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-productive);transition-property:opacity}.jkl-feedback-smiley-option:before{inset:0;box-shadow:0 .125rem 1.875rem #0000001a}.jkl-feedback-smiley-option:hover{color:var(--jkl-color-text-default)}input:checked+.jkl-feedback-smiley-option{color:var(--jkl-color-text-default);transform:translate3d(0,-20%,0)}input:checked+.jkl-feedback-smiley-option:before{opacity:1}input:focus-visible+.jkl-feedback-smiley-option{border-radius:var(--jkl-border-radius-full);outline:3px solid var(--jkl-color-border-strong);outline-offset:3px}}
@@ -340,22 +340,22 @@
340
340
  animation: 2500ms linear infinite;
341
341
  }
342
342
  .jkl-loader__dot--left {
343
- animation-name: jkl-loader-left-spin-umjmj0n;
343
+ animation-name: jkl-loader-left-spin-uiocd7e;
344
344
  margin-right: calc(var(--jkl-loader-spacing) * 0.9);
345
345
  }
346
346
  .jkl-loader__dot--middle {
347
- animation-name: jkl-loader-middle-spin-umjmj19;
347
+ animation-name: jkl-loader-middle-spin-uiocd83;
348
348
  margin-right: var(--jkl-loader-spacing);
349
349
  }
350
350
  .jkl-loader__dot--right {
351
- animation-name: jkl-loader-right-spin-umjmj1p;
351
+ animation-name: jkl-loader-right-spin-uiocd8x;
352
352
  }
353
353
  @media screen and (forced-colors: active) {
354
354
  .jkl-loader__dot {
355
355
  background-color: CanvasText;
356
356
  }
357
357
  }
358
- @keyframes jkl-loader-left-spin-umjmj0n {
358
+ @keyframes jkl-loader-left-spin-uiocd7e {
359
359
  0% {
360
360
  transform: rotate(0) scale(0);
361
361
  }
@@ -369,7 +369,7 @@
369
369
  transform: rotate(180deg) scale(0);
370
370
  }
371
371
  }
372
- @keyframes jkl-loader-middle-spin-umjmj19 {
372
+ @keyframes jkl-loader-middle-spin-uiocd83 {
373
373
  0% {
374
374
  transform: rotate(20deg) scale(0);
375
375
  }
@@ -386,7 +386,7 @@
386
386
  transform: rotate(200deg) scale(0);
387
387
  }
388
388
  }
389
- @keyframes jkl-loader-right-spin-umjmj1p {
389
+ @keyframes jkl-loader-right-spin-uiocd8x {
390
390
  0% {
391
391
  transform: rotate(40deg) scale(0);
392
392
  }
@@ -426,7 +426,7 @@
426
426
  @media screen and (forced-colors: active) {
427
427
  .jkl-skeleton-element {
428
428
  border: 1px solid CanvasText;
429
- animation: 2s ease infinite jkl-blink-umjmj2n;
429
+ animation: 2s ease infinite jkl-blink-uiocd9t;
430
430
  }
431
431
  }
432
432
  .jkl-skeleton-input {
@@ -474,10 +474,10 @@
474
474
  }
475
475
  @media screen and (forced-colors: active) {
476
476
  .jkl-skeleton-table {
477
- animation: 2s ease-in-out infinite jkl-blink-umjmj2n;
477
+ animation: 2s ease-in-out infinite jkl-blink-uiocd9t;
478
478
  }
479
479
  }
480
- @keyframes jkl-blink-umjmj2n {
480
+ @keyframes jkl-blink-uiocd9t {
481
481
  0% {
482
482
  opacity: 1;
483
483
  }
@@ -1 +1 @@
1
- @charset "UTF-8";@layer jokul.components{.jkl-file{--jkl-file-padding:var(--jkl-unit-10);--jkl-file-thumbnail-max-height:var(--jkl-unit-210);--jkl-file-thumbnail-width:var(--jkl-unit-60);--jkl-file-thumbnail-aspect-ratio:1;--jkl-file-gap:var(--jkl-unit-10);--jkl-file-button-width:var(--jkl-unit-50);--text-color:var(--jkl-color-text-default);--border:1px solid var(--jkl-color-border-subdued);--border-radius:var(--jkl-border-radius-s);--bg:#0000;--transition-time:var(--jkl-motion-timing-expressive)}.jkl-file__thumbnail{flex-shrink:0;aspect-ratio:var(--jkl-file-thumbnail-aspect-ratio);width:var(--jkl-file-thumbnail-width);height:auto;max-height:var(--jkl-file-thumbnail-max-height);position:relative;display:flex;align-items:center;justify-content:center;background:var(--jkl-color-background-page);border-radius:var(--jkl-border-radius-xs);overflow:hidden;anchor-name:--thumb;anchor-scope:all;outline:1px solid color-mix(in srgb,currentColor 3%,#0000)}.jkl-file__thumbnail:after{position:absolute;z-index:1;content:""/"Laster opp";position-anchor:--thumb;position-area:center;height:25%;border-radius:1px;aspect-ratio:1;scale:0;background:var(--text-color);animation:spin 5s linear infinite forwards;transition:display var(--transition-time) allow-discrete ease-in,scale var(--transition-time) ease-in}@starting-style{.jkl-file__thumbnail:after{scale:0}}.jkl-file__thumbnail img{opacity:1;transition:opacity var(--transition-time) ease-in-out}.jkl-file__thumbnail img[src]{min-width:100%;min-height:100%;object-fit:cover;object-position:center}.jkl-file__content{transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-snappy);transition-property:background-color,border-color,color;color:var(--text-color);padding:var(--jkl-file-padding);border:var(--border);border-radius:var(--border-radius);background:var(--bg);height:-webkit-fit-content;height:fit-content}.jkl-file__content:not(:has(.jkl-file__thumbnail)):has(.jkl-file__button){--jkl-file-padding:0 var(--jkl-unit-10)}.jkl-file__info{flex-grow:999}.jkl-file__name{word-break:break-word}.jkl-file__size{word-break:keep-all}.jkl-file__button{aspect-ratio:1;flex-shrink:0}.jkl-file[class*=card]{--jkl-file-thumbnail-width:100%;--jkl-file-thumbnail-aspect-ratio:16/10}.jkl-file:not([data-state*=loading]) .jkl-file__thumbnail:not(:has(img[src])):before{font:var(--jkl-text-style-paragraph-small);position:absolute;z-index:1;content:attr(data-filetype)}.jkl-file[data-state=loading]:not(:has(.jkl-file__support-label)) .jkl-file__thumbnail img{opacity:0}.jkl-file[data-state=loading]:not(:has(.jkl-file__support-label)) .jkl-file__thumbnail:after{display:block;scale:1}.jkl-file[data-state=error],.jkl-file[data-state=error] a,.jkl-file[data-state=error] a:hover,.jkl-file[data-state=error] button,.jkl-file[data-state=error] span{--text-color:var(--jkl-color-error-text-default)}.jkl-file[data-state=error] .jkl-file__content{border-color:var(--jkl-color-error-border-default)}@keyframes spin{0%{transform:rotate(0turn)}to{transform:rotate(1turn)}}}@layer jokul.components{.jkl-link{--link-color:var(--jkl-color-text-accent);color:var(--link-color);outline:none;text-decoration:none;transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-energetic);transition-property:color}.jkl-link__content{text-decoration:underline;text-underline-offset:.08lh;text-decoration-thickness:.05em;-webkit-text-decoration-color:rgb(from currentColor r g b/70%);text-decoration-color:rgb(from currentColor r g b/70%)}.jkl-link:after{--jkl-icon-fill:0;--jkl-icon-size:1em;-webkit-margin-before:-.1em;margin-block-start:-.1em;-webkit-padding-start:.2em;padding-inline-start:.2em;vertical-align:middle;font-family:var(--jkl-font-family-icons);font-variation-settings:"FILL" var(--jkl-icon-fill,0);font-feature-settings:"liga";-webkit-font-feature-settings:"liga";font-size:1.3em;font-weight:400;line-height:1;display:inline-block;flex-shrink:0;-webkit-font-smoothing:antialiased;transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-energetic);transition-property:font-variation-settings,transform;display:inline}.jkl-link--external:after,.jkl-link[target=_blank]:after{content:"\e89e"/"(Åpnes i ny fane)"}.jkl-link[download]:after{content:"\f090"/"(Last ned fil)"}.jkl-link:hover:not(:focus){--link-color:var(--jkl-color-text-subdued)}.jkl-link:focus-visible{outline:3px solid var(--jkl-color-border-strong);outline-offset:0}@media screen and (forced-colors:active){.jkl-link:hover:not(:focus){--link-color:HighLight}}button.jkl-link{-webkit-appearance:none;appearance:none;border:0;padding:0;margin:0;background:none;font:inherit;text-align:inherit}.jkl-button{--jkl-button-font-size:var(--jkl-typography-body-base-font-size);--jkl-button-line-height:var(--jkl-typography-body-base-line-height);--jkl-button-padding-block:var(--jkl-unit-10);--jkl-button-padding-text:var(--jkl-unit-30);--jkl-button-padding-icon:var(--jkl-unit-20);--jkl-button-padding-icon-button:var(--jkl-unit-10);--jkl-button-tertiary-padding-icon:var(--jkl-unit-05);--jkl-button-text-ink-offset:0.1em;--button-min-width:9ch;--jkl-icon-weight:var(--jkl-icon-weight-bold);--text-color:var(--jkl-color-text-default);--background-color:#0000;--border-radius:0;--border-width:0.0625rem;display:inline-block;font:var(--jkl-text-style-text-medium);font-weight:var(--jkl-font-weight-bold);-webkit-user-select:none;user-select:none;background:var(--background-color);color:var(--text-color);border:unset;text-decoration:none;-webkit-tap-highlight-color:transparent;border-radius:var(--border-radius);padding-inline:var(--jkl-button-padding-text);padding-block:var(--jkl-button-padding-block);position:relative;overflow:hidden;max-width:100%;animation:a .3s linear;transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-productive);transition-property:background-color}}@layer jokul.components{.jkl-button:has(.jkl-button__text){min-width:var(--button-min-width)}.jkl-button:has(.jkl-button__text):has(.jkl-icon){min-width:auto}.jkl-button:has(.jkl-icon:first-child){-webkit-padding-start:var(--jkl-button-padding-icon);padding-inline-start:var(--jkl-button-padding-icon)}.jkl-button:has(.jkl-icon:last-child){-webkit-padding-end:var(--jkl-button-padding-icon);padding-inline-end:var(--jkl-button-padding-icon)}.jkl-button:has(.jkl-icon:first-child):has(.jkl-icon:last-child){padding-inline:var(--jkl-button-padding-icon-button)}.jkl-button__label{transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-expressive);transition-property:translate;width:100%;display:flex;flex-direction:row;align-items:center;justify-content:center;gap:var(--jkl-unit-02);pointer-events:none}.jkl-button__loader{transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-expressive);transition-property:opacity,translate;position:absolute;top:50%;left:50%;translate:-50% 350%;opacity:0;pointer-events:none}.jkl-button__text{display:block;min-width:0;max-width:100%;-webkit-padding-before:var(--jkl-button-text-ink-offset);padding-block-start:var(--jkl-button-text-ink-offset);-webkit-margin-before:calc(var(--jkl-button-text-ink-offset)*-1);margin-block-start:calc(var(--jkl-button-text-ink-offset)*-1);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jkl-button[data-loading=true] .jkl-button__label{--button-loading-offset:calc(-100% - var(--jkl-button-padding-block)*2 - var(--jkl-button-text-ink-offset));translate:0 var(--button-loading-offset)}.jkl-button[data-loading=true] .jkl-button__loader{translate:-50% -50%;opacity:1}.jkl-button:focus-visible{outline:3px solid var(--jkl-color-border-strong);outline-offset:3px}.jkl-button:hover{background-color:color-mix(in srgb,var(--background-color),var(--text-color) 15%)}@media (forced-colors:active){.jkl-button:hover{outline:3px solid var(--jkl-color-border-strong);outline-offset:3px}}.jkl-button--ghost,.jkl-button--primary,.jkl-button--secondary{--border-radius:999px}.jkl-button--primary{--background-color:var(--jkl-color-background-contrast);--text-color:var(--jkl-color-text-on-contrast)}@media (forced-colors:active){.jkl-button--primary{border:calc(var(--border-width)*2) solid Highlight}}.jkl-button--secondary{border:var(--border-width) solid var(--text-color)}.jkl-button--tertiary{border-bottom:var(--border-width) solid var(--text-color);padding-inline:var(--jkl-button-tertiary-padding-icon)}.jkl-button--tertiary:has(.jkl-icon:first-child){padding-inline:var(--jkl-button-tertiary-padding-icon) calc(var(--jkl-button-tertiary-padding-icon)*2)}.jkl-button--tertiary:has(.jkl-icon:last-child){padding-inline:calc(var(--jkl-button-tertiary-padding-icon)*2) var(--jkl-button-tertiary-padding-icon)}}@layer jokul.components{.jkl-loader{--jkl-loader-dot-size:var(--jkl-unit-10);--jkl-loader-spacing:var(--jkl-unit-20);display:flex}.jkl-loader--inline{display:inline-flex}.jkl-loader__dot{display:block;transform-origin:center;background-color:currentColor;height:var(--jkl-loader-dot-size);width:var(--jkl-loader-dot-size);animation:2.5s linear infinite}.jkl-loader__dot--left{animation-name:jkl-loader-left-spin-umjmj0n;margin-right:calc(var(--jkl-loader-spacing)*.9)}.jkl-loader__dot--middle{animation-name:jkl-loader-middle-spin-umjmj19;margin-right:var(--jkl-loader-spacing)}.jkl-loader__dot--right{animation-name:jkl-loader-right-spin-umjmj1p}@media screen and (forced-colors:active){.jkl-loader__dot{background-color:CanvasText}}@keyframes jkl-loader-left-spin-umjmj0n{0%{transform:rotate(0) scale(0)}30%{transform:rotate(90deg) scale(1)}70%{transform:rotate(180deg) scale(0)}to{transform:rotate(180deg) scale(0)}}@keyframes jkl-loader-middle-spin-umjmj19{0%{transform:rotate(20deg) scale(0)}10%{transform:rotate(20deg) scale(0)}40%{transform:rotate(110deg) scale(1.4)}85%{transform:rotate(200deg) scale(0)}to{transform:rotate(200deg) scale(0)}}@keyframes jkl-loader-right-spin-umjmj1p{0%{transform:rotate(40deg) scale(0)}20%{transform:rotate(40deg) scale(0)}50%{transform:rotate(130deg) scale(1)}to{transform:rotate(220deg) scale(0)}}}@layer jokul.components{@property --jkl-skeleton-sweeper-position{syntax:"<percentage>";initial-value:0%;inherits:true}.jkl-skeleton-animation{--jkl-skeleton-element-color:var(--jkl-color-background-page);--jkl-skeleton-sweep-duration:4500ms;--jkl-skeleton-sweeper-width:40%;-webkit-mask-image:linear-gradient(to right,#000 calc(var(--jkl-skeleton-sweeper-position) - var(--jkl-skeleton-sweeper-width)),#0000 calc(var(--jkl-skeleton-sweeper-position) - var(--jkl-skeleton-sweeper-width)/2),#000 var(--jkl-skeleton-sweeper-position));mask-image:linear-gradient(to right,#000 calc(var(--jkl-skeleton-sweeper-position) - var(--jkl-skeleton-sweeper-width)),#0000 calc(var(--jkl-skeleton-sweeper-position) - var(--jkl-skeleton-sweeper-width)/2),#000 var(--jkl-skeleton-sweeper-position));-webkit-mask-size:100dvi 100dvb;mask-size:100dvi 100dvb;-webkit-mask-position:center;mask-position:center;animation:var(--jkl-skeleton-sweep-duration) ease-in-out infinite --jkl-skeleton-sweep}.jkl-skeleton-element{border-radius:.125rem;background-color:var(--jkl-skeleton-element-color)}.jkl-skeleton-element--circle{border-radius:50%}@media screen and (forced-colors:active){.jkl-skeleton-element{border:1px solid CanvasText;animation:jkl-blink-umjmj2n 2s ease infinite}}.jkl-skeleton-input{display:flex;flex-direction:column;gap:var(--jkl-spacing-12)}.jkl-skeleton-input__checkbox{display:flex;flex-direction:row;flex-wrap:nowrap;gap:var(--jkl-spacing-8)}@media (width >= 0) and (max-width:679px){.jkl-skeleton-input{gap:var(--jkl-spacing-8)}}.jkl-skeleton-input--compact:after{gap:var(--jkl-spacing-8)}.jkl-skeleton-table{display:flex;flex-direction:column}.jkl-skeleton-table__header,.jkl-skeleton-table__row{display:flex;flex-direction:row;justify-content:space-between;border-bottom:1px solid var(--jkl-skeleton-element-color)}.jkl-skeleton-table__header,.jkl-skeleton-table__row{padding:var(--jkl-unit-20) var(--jkl-unit-10)}@media (width >= 0) and (max-width:679px){.jkl-skeleton-table__header{padding:var(--jkl-unit-10) var(--jkl-unit-05)}.jkl-skeleton-table__row{padding:var(--jkl-unit-20) var(--jkl-unit-05)}}@media screen and (forced-colors:active){.jkl-skeleton-table{animation:jkl-blink-umjmj2n 2s ease-in-out infinite}}@keyframes jkl-blink-umjmj2n{0%{opacity:1}40%,50%{opacity:.3}70%,to{opacity:1}}@keyframes --jkl-skeleton-sweep{0%,67%{--jkl-skeleton-sweeper-position:0%}to{--jkl-skeleton-sweeper-position:calc(100% + var(--jkl-skeleton-sweeper-width))}}}@layer jokul.components{.jkl-file-input{--jkl-file-input-dropzone-padding:var(--jkl-unit-30);--jkl-file-input-dropzone-gap:var(--jkl-unit-30);--jkl-file-cta-gap:var(--jkl-unit-30);--jkl-file-cta-with-files-gap:var(--jkl-unit-15);--jkl-file-list-gap:var(--jkl-unit-10)}.jkl-file-input__dropzone{--border-color:var(--jkl-color-border-default);--background-color:#0000;border:1px dashed var(--border-color);border-radius:.25rem;padding:var(--jkl-file-input-dropzone-padding);display:flex;justify-content:center;align-items:center;flex-direction:column;flex-wrap:nowrap;gap:var(--jkl-file-input-dropzone-gap);transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-productive);transition-property:background-color;background-color:var(--background-color)}.jkl-file-input__dropzone--enter{--border-color:var(--jkl-color-border-strong);--background-color:var(--jkl-color-background-container);border-style:solid}.jkl-file-input__dropzone__drag-text{font:var(--jkl-text-style-paragraph-small)}@media (width >= 0) and (max-width:679px){.jkl-file-input__dropzone__drag-text{display:none}}.jkl-file-input__call-to-action{display:flex;justify-content:center;align-items:center;flex-direction:column;flex-wrap:nowrap}.jkl-file-input__call-to-action:has(:focus-visible) .jkl-button{transform:scale(1.05);outline:3px solid var(--jkl-color-border-strong);outline-offset:3px}.jkl-file-input__call-to-action:has(:focus-visible) .jkl-button:active{transform:scale(1)}.jkl-file-input__dropzone-hint{margin-top:var(--jkl-unit-30)}.jkl-file-input--has-files .jkl-file-input__dropzone-hint{display:none}.jkl-file-input__max-size-text{font:var(--jkl-text-style-text-small);color:var(--jkl-color-text-subdued);margin-top:var(--jkl-unit-30)}.jkl-file-input__files{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--jkl-file-list-gap)}.jkl-file-input--small .jkl-file-input__dropzone-hint{margin:0;display:block}.jkl-file-input--small .jkl-file-input__dropzone{padding:var(--jkl-unit-20);gap:var(--jkl-unit-20);margin-bottom:var(--jkl-unit-20);justify-content:flex-start;flex-direction:row;max-width:-webkit-fit-content;max-width:fit-content}.jkl-file-input--small .jkl-file-input__call-to-action{font:var(--jkl-text-style-text-small);gap:var(--jkl-unit-15);flex-direction:row;justify-content:flex-start}.jkl-file-input--small .jkl-file-input__max-size-text{margin-top:calc(var(--jkl-unit-15)*-1);margin-bottom:var(--jkl-unit-20)}}
1
+ @charset "UTF-8";@layer jokul.components{.jkl-file{--jkl-file-padding:var(--jkl-unit-10);--jkl-file-thumbnail-max-height:var(--jkl-unit-210);--jkl-file-thumbnail-width:var(--jkl-unit-60);--jkl-file-thumbnail-aspect-ratio:1;--jkl-file-gap:var(--jkl-unit-10);--jkl-file-button-width:var(--jkl-unit-50);--text-color:var(--jkl-color-text-default);--border:1px solid var(--jkl-color-border-subdued);--border-radius:var(--jkl-border-radius-s);--bg:#0000;--transition-time:var(--jkl-motion-timing-expressive)}.jkl-file__thumbnail{flex-shrink:0;aspect-ratio:var(--jkl-file-thumbnail-aspect-ratio);width:var(--jkl-file-thumbnail-width);height:auto;max-height:var(--jkl-file-thumbnail-max-height);position:relative;display:flex;align-items:center;justify-content:center;background:var(--jkl-color-background-page);border-radius:var(--jkl-border-radius-xs);overflow:hidden;anchor-name:--thumb;anchor-scope:all;outline:1px solid color-mix(in srgb,currentColor 3%,#0000)}.jkl-file__thumbnail:after{position:absolute;z-index:1;content:""/"Laster opp";position-anchor:--thumb;position-area:center;height:25%;border-radius:1px;aspect-ratio:1;scale:0;background:var(--text-color);animation:spin 5s linear infinite forwards;transition:display var(--transition-time) allow-discrete ease-in,scale var(--transition-time) ease-in}@starting-style{.jkl-file__thumbnail:after{scale:0}}.jkl-file__thumbnail img{opacity:1;transition:opacity var(--transition-time) ease-in-out}.jkl-file__thumbnail img[src]{min-width:100%;min-height:100%;object-fit:cover;object-position:center}.jkl-file__content{transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-snappy);transition-property:background-color,border-color,color;color:var(--text-color);padding:var(--jkl-file-padding);border:var(--border);border-radius:var(--border-radius);background:var(--bg);height:-webkit-fit-content;height:fit-content}.jkl-file__content:not(:has(.jkl-file__thumbnail)):has(.jkl-file__button){--jkl-file-padding:0 var(--jkl-unit-10)}.jkl-file__info{flex-grow:999}.jkl-file__name{word-break:break-word}.jkl-file__size{word-break:keep-all}.jkl-file__button{aspect-ratio:1;flex-shrink:0}.jkl-file[class*=card]{--jkl-file-thumbnail-width:100%;--jkl-file-thumbnail-aspect-ratio:16/10}.jkl-file:not([data-state*=loading]) .jkl-file__thumbnail:not(:has(img[src])):before{font:var(--jkl-text-style-paragraph-small);position:absolute;z-index:1;content:attr(data-filetype)}.jkl-file[data-state=loading]:not(:has(.jkl-file__support-label)) .jkl-file__thumbnail img{opacity:0}.jkl-file[data-state=loading]:not(:has(.jkl-file__support-label)) .jkl-file__thumbnail:after{display:block;scale:1}.jkl-file[data-state=error],.jkl-file[data-state=error] a,.jkl-file[data-state=error] a:hover,.jkl-file[data-state=error] button,.jkl-file[data-state=error] span{--text-color:var(--jkl-color-error-text-default)}.jkl-file[data-state=error] .jkl-file__content{border-color:var(--jkl-color-error-border-default)}@keyframes spin{0%{transform:rotate(0turn)}to{transform:rotate(1turn)}}}@layer jokul.components{.jkl-link{--link-color:var(--jkl-color-text-accent);color:var(--link-color);outline:none;text-decoration:none;transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-energetic);transition-property:color}.jkl-link__content{text-decoration:underline;text-underline-offset:.08lh;text-decoration-thickness:.05em;-webkit-text-decoration-color:rgb(from currentColor r g b/70%);text-decoration-color:rgb(from currentColor r g b/70%)}.jkl-link:after{--jkl-icon-fill:0;--jkl-icon-size:1em;-webkit-margin-before:-.1em;margin-block-start:-.1em;-webkit-padding-start:.2em;padding-inline-start:.2em;vertical-align:middle;font-family:var(--jkl-font-family-icons);font-variation-settings:"FILL" var(--jkl-icon-fill,0);font-feature-settings:"liga";-webkit-font-feature-settings:"liga";font-size:1.3em;font-weight:400;line-height:1;display:inline-block;flex-shrink:0;-webkit-font-smoothing:antialiased;transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-energetic);transition-property:font-variation-settings,transform;display:inline}.jkl-link--external:after,.jkl-link[target=_blank]:after{content:"\e89e"/"(Åpnes i ny fane)"}.jkl-link[download]:after{content:"\f090"/"(Last ned fil)"}.jkl-link:hover:not(:focus){--link-color:var(--jkl-color-text-subdued)}.jkl-link:focus-visible{outline:3px solid var(--jkl-color-border-strong);outline-offset:0}@media screen and (forced-colors:active){.jkl-link:hover:not(:focus){--link-color:HighLight}}button.jkl-link{-webkit-appearance:none;appearance:none;border:0;padding:0;margin:0;background:none;font:inherit;text-align:inherit}.jkl-button{--jkl-button-font-size:var(--jkl-typography-body-base-font-size);--jkl-button-line-height:var(--jkl-typography-body-base-line-height);--jkl-button-padding-block:var(--jkl-unit-10);--jkl-button-padding-text:var(--jkl-unit-30);--jkl-button-padding-icon:var(--jkl-unit-20);--jkl-button-padding-icon-button:var(--jkl-unit-10);--jkl-button-tertiary-padding-icon:var(--jkl-unit-05);--jkl-button-text-ink-offset:0.1em;--button-min-width:9ch;--jkl-icon-weight:var(--jkl-icon-weight-bold);--text-color:var(--jkl-color-text-default);--background-color:#0000;--border-radius:0;--border-width:0.0625rem;display:inline-block;font:var(--jkl-text-style-text-medium);font-weight:var(--jkl-font-weight-bold);-webkit-user-select:none;user-select:none;background:var(--background-color);color:var(--text-color);border:unset;text-decoration:none;-webkit-tap-highlight-color:transparent;border-radius:var(--border-radius);padding-inline:var(--jkl-button-padding-text);padding-block:var(--jkl-button-padding-block);position:relative;overflow:hidden;max-width:100%;animation:a .3s linear;transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-productive);transition-property:background-color}}@layer jokul.components{.jkl-button:has(.jkl-button__text){min-width:var(--button-min-width)}.jkl-button:has(.jkl-button__text):has(.jkl-icon){min-width:auto}.jkl-button:has(.jkl-icon:first-child){-webkit-padding-start:var(--jkl-button-padding-icon);padding-inline-start:var(--jkl-button-padding-icon)}.jkl-button:has(.jkl-icon:last-child){-webkit-padding-end:var(--jkl-button-padding-icon);padding-inline-end:var(--jkl-button-padding-icon)}.jkl-button:has(.jkl-icon:first-child):has(.jkl-icon:last-child){padding-inline:var(--jkl-button-padding-icon-button)}.jkl-button__label{transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-expressive);transition-property:translate;width:100%;display:flex;flex-direction:row;align-items:center;justify-content:center;gap:var(--jkl-unit-02);pointer-events:none}.jkl-button__loader{transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-expressive);transition-property:opacity,translate;position:absolute;top:50%;left:50%;translate:-50% 350%;opacity:0;pointer-events:none}.jkl-button__text{display:block;min-width:0;max-width:100%;-webkit-padding-before:var(--jkl-button-text-ink-offset);padding-block-start:var(--jkl-button-text-ink-offset);-webkit-margin-before:calc(var(--jkl-button-text-ink-offset)*-1);margin-block-start:calc(var(--jkl-button-text-ink-offset)*-1);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jkl-button[data-loading=true] .jkl-button__label{--button-loading-offset:calc(-100% - var(--jkl-button-padding-block)*2 - var(--jkl-button-text-ink-offset));translate:0 var(--button-loading-offset)}.jkl-button[data-loading=true] .jkl-button__loader{translate:-50% -50%;opacity:1}.jkl-button:focus-visible{outline:3px solid var(--jkl-color-border-strong);outline-offset:3px}.jkl-button:hover{background-color:color-mix(in srgb,var(--background-color),var(--text-color) 15%)}@media (forced-colors:active){.jkl-button:hover{outline:3px solid var(--jkl-color-border-strong);outline-offset:3px}}.jkl-button--ghost,.jkl-button--primary,.jkl-button--secondary{--border-radius:999px}.jkl-button--primary{--background-color:var(--jkl-color-background-contrast);--text-color:var(--jkl-color-text-on-contrast)}@media (forced-colors:active){.jkl-button--primary{border:calc(var(--border-width)*2) solid Highlight}}.jkl-button--secondary{border:var(--border-width) solid var(--text-color)}.jkl-button--tertiary{border-bottom:var(--border-width) solid var(--text-color);padding-inline:var(--jkl-button-tertiary-padding-icon)}.jkl-button--tertiary:has(.jkl-icon:first-child){padding-inline:var(--jkl-button-tertiary-padding-icon) calc(var(--jkl-button-tertiary-padding-icon)*2)}.jkl-button--tertiary:has(.jkl-icon:last-child){padding-inline:calc(var(--jkl-button-tertiary-padding-icon)*2) var(--jkl-button-tertiary-padding-icon)}}@layer jokul.components{.jkl-loader{--jkl-loader-dot-size:var(--jkl-unit-10);--jkl-loader-spacing:var(--jkl-unit-20);display:flex}.jkl-loader--inline{display:inline-flex}.jkl-loader__dot{display:block;transform-origin:center;background-color:currentColor;height:var(--jkl-loader-dot-size);width:var(--jkl-loader-dot-size);animation:2.5s linear infinite}.jkl-loader__dot--left{animation-name:jkl-loader-left-spin-uiocd7e;margin-right:calc(var(--jkl-loader-spacing)*.9)}.jkl-loader__dot--middle{animation-name:jkl-loader-middle-spin-uiocd83;margin-right:var(--jkl-loader-spacing)}.jkl-loader__dot--right{animation-name:jkl-loader-right-spin-uiocd8x}@media screen and (forced-colors:active){.jkl-loader__dot{background-color:CanvasText}}@keyframes jkl-loader-left-spin-uiocd7e{0%{transform:rotate(0) scale(0)}30%{transform:rotate(90deg) scale(1)}70%{transform:rotate(180deg) scale(0)}to{transform:rotate(180deg) scale(0)}}@keyframes jkl-loader-middle-spin-uiocd83{0%{transform:rotate(20deg) scale(0)}10%{transform:rotate(20deg) scale(0)}40%{transform:rotate(110deg) scale(1.4)}85%{transform:rotate(200deg) scale(0)}to{transform:rotate(200deg) scale(0)}}@keyframes jkl-loader-right-spin-uiocd8x{0%{transform:rotate(40deg) scale(0)}20%{transform:rotate(40deg) scale(0)}50%{transform:rotate(130deg) scale(1)}to{transform:rotate(220deg) scale(0)}}}@layer jokul.components{@property --jkl-skeleton-sweeper-position{syntax:"<percentage>";initial-value:0%;inherits:true}.jkl-skeleton-animation{--jkl-skeleton-element-color:var(--jkl-color-background-page);--jkl-skeleton-sweep-duration:4500ms;--jkl-skeleton-sweeper-width:40%;-webkit-mask-image:linear-gradient(to right,#000 calc(var(--jkl-skeleton-sweeper-position) - var(--jkl-skeleton-sweeper-width)),#0000 calc(var(--jkl-skeleton-sweeper-position) - var(--jkl-skeleton-sweeper-width)/2),#000 var(--jkl-skeleton-sweeper-position));mask-image:linear-gradient(to right,#000 calc(var(--jkl-skeleton-sweeper-position) - var(--jkl-skeleton-sweeper-width)),#0000 calc(var(--jkl-skeleton-sweeper-position) - var(--jkl-skeleton-sweeper-width)/2),#000 var(--jkl-skeleton-sweeper-position));-webkit-mask-size:100dvi 100dvb;mask-size:100dvi 100dvb;-webkit-mask-position:center;mask-position:center;animation:var(--jkl-skeleton-sweep-duration) ease-in-out infinite --jkl-skeleton-sweep}.jkl-skeleton-element{border-radius:.125rem;background-color:var(--jkl-skeleton-element-color)}.jkl-skeleton-element--circle{border-radius:50%}@media screen and (forced-colors:active){.jkl-skeleton-element{border:1px solid CanvasText;animation:jkl-blink-uiocd9t 2s ease infinite}}.jkl-skeleton-input{display:flex;flex-direction:column;gap:var(--jkl-spacing-12)}.jkl-skeleton-input__checkbox{display:flex;flex-direction:row;flex-wrap:nowrap;gap:var(--jkl-spacing-8)}@media (width >= 0) and (max-width:679px){.jkl-skeleton-input{gap:var(--jkl-spacing-8)}}.jkl-skeleton-input--compact:after{gap:var(--jkl-spacing-8)}.jkl-skeleton-table{display:flex;flex-direction:column}.jkl-skeleton-table__header,.jkl-skeleton-table__row{display:flex;flex-direction:row;justify-content:space-between;border-bottom:1px solid var(--jkl-skeleton-element-color)}.jkl-skeleton-table__header,.jkl-skeleton-table__row{padding:var(--jkl-unit-20) var(--jkl-unit-10)}@media (width >= 0) and (max-width:679px){.jkl-skeleton-table__header{padding:var(--jkl-unit-10) var(--jkl-unit-05)}.jkl-skeleton-table__row{padding:var(--jkl-unit-20) var(--jkl-unit-05)}}@media screen and (forced-colors:active){.jkl-skeleton-table{animation:jkl-blink-uiocd9t 2s ease-in-out infinite}}@keyframes jkl-blink-uiocd9t{0%{opacity:1}40%,50%{opacity:.3}70%,to{opacity:1}}@keyframes --jkl-skeleton-sweep{0%,67%{--jkl-skeleton-sweeper-position:0%}to{--jkl-skeleton-sweeper-position:calc(100% + var(--jkl-skeleton-sweeper-width))}}}@layer jokul.components{.jkl-file-input{--jkl-file-input-dropzone-padding:var(--jkl-unit-30);--jkl-file-input-dropzone-gap:var(--jkl-unit-30);--jkl-file-cta-gap:var(--jkl-unit-30);--jkl-file-cta-with-files-gap:var(--jkl-unit-15);--jkl-file-list-gap:var(--jkl-unit-10)}.jkl-file-input__dropzone{--border-color:var(--jkl-color-border-default);--background-color:#0000;border:1px dashed var(--border-color);border-radius:.25rem;padding:var(--jkl-file-input-dropzone-padding);display:flex;justify-content:center;align-items:center;flex-direction:column;flex-wrap:nowrap;gap:var(--jkl-file-input-dropzone-gap);transition-timing-function:var(--jkl-motion-easing-standard);transition-duration:var(--jkl-motion-timing-productive);transition-property:background-color;background-color:var(--background-color)}.jkl-file-input__dropzone--enter{--border-color:var(--jkl-color-border-strong);--background-color:var(--jkl-color-background-container);border-style:solid}.jkl-file-input__dropzone__drag-text{font:var(--jkl-text-style-paragraph-small)}@media (width >= 0) and (max-width:679px){.jkl-file-input__dropzone__drag-text{display:none}}.jkl-file-input__call-to-action{display:flex;justify-content:center;align-items:center;flex-direction:column;flex-wrap:nowrap}.jkl-file-input__call-to-action:has(:focus-visible) .jkl-button{transform:scale(1.05);outline:3px solid var(--jkl-color-border-strong);outline-offset:3px}.jkl-file-input__call-to-action:has(:focus-visible) .jkl-button:active{transform:scale(1)}.jkl-file-input__dropzone-hint{margin-top:var(--jkl-unit-30)}.jkl-file-input--has-files .jkl-file-input__dropzone-hint{display:none}.jkl-file-input__max-size-text{font:var(--jkl-text-style-text-small);color:var(--jkl-color-text-subdued);margin-top:var(--jkl-unit-30)}.jkl-file-input__files{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--jkl-file-list-gap)}.jkl-file-input--small .jkl-file-input__dropzone-hint{margin:0;display:block}.jkl-file-input--small .jkl-file-input__dropzone{padding:var(--jkl-unit-20);gap:var(--jkl-unit-20);margin-bottom:var(--jkl-unit-20);justify-content:flex-start;flex-direction:row;max-width:-webkit-fit-content;max-width:fit-content}.jkl-file-input--small .jkl-file-input__call-to-action{font:var(--jkl-text-style-text-small);gap:var(--jkl-unit-15);flex-direction:row;justify-content:flex-start}.jkl-file-input--small .jkl-file-input__max-size-text{margin-top:calc(var(--jkl-unit-15)*-1);margin-bottom:var(--jkl-unit-20)}}
@@ -74,7 +74,7 @@
74
74
  display: inline-flex;
75
75
  }
76
76
  .jkl-form-support-label--error .jkl-form-support-label__icon, .jkl-form-support-label--warning .jkl-form-support-label__icon, .jkl-form-support-label--success .jkl-form-support-label__icon {
77
- animation: var(--jkl-motion-timing-lazy) cubic-bezier(0, 0, 0.3, 1) var(--jkl-motion-timing-expressive) jkl-support-icon-entrance-us22tmt forwards;
77
+ animation: var(--jkl-motion-timing-lazy) cubic-bezier(0, 0, 0.3, 1) var(--jkl-motion-timing-expressive) jkl-support-icon-entrance-uws6grz forwards;
78
78
  }
79
79
  .jkl-form-support-label--sr-only {
80
80
  border: 0 !important;
@@ -128,7 +128,7 @@
128
128
  .jkl-label:has(+ .jkl-input-group-description) {
129
129
  margin-block-end: var(--jkl-spacing-4);
130
130
  }
131
- @keyframes jkl-support-icon-entrance-us22tmt {
131
+ @keyframes jkl-support-icon-entrance-uws6grz {
132
132
  0% {
133
133
  margin-right: 0;
134
134
  opacity: 0;