@digdir/designsystemet-react 0.58.0 → 0.59.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/Alert/Alert.js +2 -2
- package/dist/cjs/components/Button/Button.js +1 -2
- package/dist/cjs/components/DropdownMenu/DropdownMenuContent.js +4 -4
- package/dist/cjs/components/DropdownMenu/DropdownMenuTrigger.js +1 -1
- package/dist/cjs/components/Modal/ModalDialog.js +1 -1
- package/dist/cjs/components/Popover/PopoverContent.js +6 -6
- package/dist/cjs/components/Popover/PopoverTrigger.js +1 -1
- package/dist/cjs/components/SkipLink/SkipLink.js +1 -2
- package/dist/cjs/components/Tooltip/Tooltip.js +6 -6
- package/dist/cjs/components/form/Checkbox/Checkbox.js +1 -1
- package/dist/cjs/components/form/Combobox/Combobox.js +60 -177
- package/dist/cjs/components/form/Combobox/ComboboxContext.js +8 -0
- package/dist/cjs/components/form/Combobox/ComboboxIdContext.js +42 -0
- package/dist/cjs/components/form/Combobox/Custom/Custom.js +14 -9
- package/dist/cjs/components/form/Combobox/Empty/Empty.js +4 -4
- package/dist/cjs/components/form/Combobox/Option/Option.js +15 -33
- package/dist/cjs/components/form/Combobox/Option/useComboboxOption.js +47 -0
- package/dist/cjs/components/form/Combobox/internal/ComboboxChips.js +14 -6
- package/dist/cjs/components/form/Combobox/internal/ComboboxClearButton.js +4 -4
- package/dist/cjs/components/form/Combobox/internal/ComboboxInput.js +40 -35
- package/dist/cjs/components/form/Combobox/internal/ComboboxNative.js +2 -2
- package/dist/cjs/components/form/Combobox/useCombobox.js +46 -32
- package/dist/cjs/components/form/Combobox/useComboboxKeyboard.js +79 -0
- package/dist/cjs/components/form/Combobox/useFloatingCombobox.js +78 -0
- package/dist/cjs/components/form/Search/Search.js +1 -1
- package/dist/cjs/node_modules/@floating-ui/utils/{dom/dist → dist}/floating-ui.utils.dom.js +7 -4
- package/dist/cjs/node_modules/@floating-ui/utils/dist/floating-ui.utils.js +5 -0
- package/dist/cjs/{node_modules → packages/react/node_modules}/@floating-ui/core/dist/floating-ui.core.js +40 -16
- package/dist/cjs/{node_modules → packages/react/node_modules}/@floating-ui/dom/dist/floating-ui.dom.js +83 -31
- package/dist/cjs/{node_modules → packages/react/node_modules}/@floating-ui/react/dist/floating-ui.react.js +307 -157
- package/dist/cjs/{node_modules/@floating-ui/react/utils → packages/react/node_modules/@floating-ui/react}/dist/floating-ui.react.utils.js +9 -4
- package/dist/cjs/{node_modules → packages/react/node_modules}/@floating-ui/react-dom/dist/floating-ui.react-dom.js +22 -18
- package/dist/{esm → cjs/packages/react}/node_modules/tabbable/dist/index.esm.js +59 -13
- package/dist/cjs/react-css-modules.css +0 -315
- package/dist/cjs/utilities/RovingTabIndex/RovingTabindexItem.js +1 -1
- package/dist/cjs/utilities/RovingTabIndex/RovingTabindexRoot.js +1 -1
- package/dist/esm/components/Alert/Alert.js +2 -2
- package/dist/esm/components/Button/Button.js +1 -2
- package/dist/esm/components/DropdownMenu/DropdownMenuContent.js +3 -3
- package/dist/esm/components/DropdownMenu/DropdownMenuTrigger.js +1 -1
- package/dist/esm/components/Modal/ModalDialog.js +1 -1
- package/dist/esm/components/Popover/PopoverContent.js +4 -4
- package/dist/esm/components/Popover/PopoverTrigger.js +1 -1
- package/dist/esm/components/SkipLink/SkipLink.js +1 -2
- package/dist/esm/components/Tooltip/Tooltip.js +4 -4
- package/dist/esm/components/form/Checkbox/Checkbox.js +1 -1
- package/dist/esm/components/form/Combobox/Combobox.js +65 -182
- package/dist/esm/components/form/Combobox/ComboboxContext.js +6 -0
- package/dist/esm/components/form/Combobox/ComboboxIdContext.js +35 -0
- package/dist/esm/components/form/Combobox/Custom/Custom.js +13 -8
- package/dist/esm/components/form/Combobox/Empty/Empty.js +3 -3
- package/dist/esm/components/form/Combobox/Option/Option.js +15 -33
- package/dist/esm/components/form/Combobox/Option/useComboboxOption.js +45 -0
- package/dist/esm/components/form/Combobox/internal/ComboboxChips.js +13 -5
- package/dist/esm/components/form/Combobox/internal/ComboboxClearButton.js +3 -3
- package/dist/esm/components/form/Combobox/internal/ComboboxInput.js +39 -34
- package/dist/esm/components/form/Combobox/internal/ComboboxNative.js +2 -2
- package/dist/esm/components/form/Combobox/useCombobox.js +46 -32
- package/dist/esm/components/form/Combobox/useComboboxKeyboard.js +77 -0
- package/dist/esm/components/form/Combobox/useFloatingCombobox.js +76 -0
- package/dist/esm/components/form/Search/Search.js +1 -1
- package/dist/esm/node_modules/@floating-ui/utils/{dom/dist → dist}/floating-ui.utils.dom.js +7 -4
- package/dist/esm/node_modules/@floating-ui/utils/dist/floating-ui.utils.js +5 -0
- package/dist/esm/{node_modules → packages/react/node_modules}/@floating-ui/core/dist/floating-ui.core.js +40 -16
- package/dist/esm/{node_modules → packages/react/node_modules}/@floating-ui/dom/dist/floating-ui.dom.js +82 -30
- package/dist/esm/{node_modules → packages/react/node_modules}/@floating-ui/react/dist/floating-ui.react.js +282 -135
- package/dist/esm/{node_modules/@floating-ui/react/utils → packages/react/node_modules/@floating-ui/react}/dist/floating-ui.react.utils.js +9 -5
- package/dist/esm/{node_modules → packages/react/node_modules}/@floating-ui/react-dom/dist/floating-ui.react-dom.js +19 -14
- package/dist/{cjs → esm/packages/react}/node_modules/tabbable/dist/index.esm.js +55 -15
- package/dist/esm/react-css-modules.css +0 -315
- package/dist/esm/utilities/RovingTabIndex/RovingTabindexItem.js +1 -1
- package/dist/esm/utilities/RovingTabIndex/RovingTabindexRoot.js +1 -1
- package/dist/types/components/Alert/Alert.d.ts +12 -0
- package/dist/types/components/Alert/Alert.d.ts.map +1 -1
- package/dist/types/components/Button/Button.d.ts.map +1 -1
- package/dist/types/components/SkipLink/SkipLink.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/Combobox.d.ts +104 -39
- package/dist/types/components/form/Combobox/Combobox.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/ComboboxContext.d.ts +48 -0
- package/dist/types/components/form/Combobox/ComboboxContext.d.ts.map +1 -0
- package/dist/types/components/form/Combobox/ComboboxIdContext.d.ts +19 -0
- package/dist/types/components/form/Combobox/ComboboxIdContext.d.ts.map +1 -0
- package/dist/types/components/form/Combobox/Custom/Custom.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/Option/Option.d.ts +2 -2
- package/dist/types/components/form/Combobox/Option/Option.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/Option/useComboboxOption.d.ts +14 -0
- package/dist/types/components/form/Combobox/Option/useComboboxOption.d.ts.map +1 -0
- package/dist/types/components/form/Combobox/internal/ComboboxChips.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/internal/ComboboxInput.d.ts +0 -1
- package/dist/types/components/form/Combobox/internal/ComboboxInput.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/internal/ComboboxNative.d.ts +3 -1
- package/dist/types/components/form/Combobox/internal/ComboboxNative.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/useCombobox.d.ts +13 -5
- package/dist/types/components/form/Combobox/useCombobox.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/useComboboxKeyboard.d.ts +20 -0
- package/dist/types/components/form/Combobox/useComboboxKeyboard.d.ts.map +1 -0
- package/dist/types/components/form/Combobox/useFloatingCombobox.d.ts +41 -0
- package/dist/types/components/form/Combobox/useFloatingCombobox.d.ts.map +1 -0
- package/package.json +3 -3
- package/dist/cjs/components/Button/Button.module.css.js +0 -6
- package/dist/cjs/components/SkipLink/SkipLink.module.css.js +0 -6
- package/dist/cjs/node_modules/@floating-ui/react/node_modules/@floating-ui/utils/dist/floating-ui.utils.js +0 -6
- package/dist/cjs/node_modules/@floating-ui/react/node_modules/@floating-ui/utils/dom/dist/floating-ui.utils.dom.js +0 -68
- package/dist/esm/components/Button/Button.module.css.js +0 -4
- package/dist/esm/components/SkipLink/SkipLink.module.css.js +0 -4
- package/dist/esm/node_modules/@floating-ui/react/node_modules/@floating-ui/utils/dist/floating-ui.utils.js +0 -4
- package/dist/esm/node_modules/@floating-ui/react/node_modules/@floating-ui/utils/dom/dist/floating-ui.utils.dom.js +0 -57
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { forwardRef, useContext, useRef } from 'react';
|
|
5
|
-
import { useFloating, useInteractions, useFocus, useClick, useDismiss, useRole, useMergeRefs, FloatingFocusManager, FloatingPortal } from '../../node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
5
|
+
import { useFloating, useInteractions, useFocus, useClick, useDismiss, useRole, useMergeRefs, FloatingFocusManager, FloatingPortal } from '../../packages/react/node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
6
6
|
import { clsx } from '../../node_modules/clsx/dist/clsx.js';
|
|
7
7
|
import classes from './DropdownMenu.module.css.js';
|
|
8
8
|
import { DropdownMenuContext } from './DropdownMenu.js';
|
|
9
|
-
import { autoUpdate } from '../../node_modules/@floating-ui/dom/dist/floating-ui.dom.js';
|
|
10
|
-
import { offset
|
|
9
|
+
import { autoUpdate, shift } from '../../packages/react/node_modules/@floating-ui/dom/dist/floating-ui.dom.js';
|
|
10
|
+
import { offset } from '../../packages/react/node_modules/@floating-ui/core/dist/floating-ui.core.js';
|
|
11
11
|
import { useIsomorphicLayoutEffect } from '../../hooks/useIsomorphicLayoutEffect.js';
|
|
12
12
|
|
|
13
13
|
const GAP = 4;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { forwardRef, useContext } from 'react';
|
|
4
|
-
import { useMergeRefs } from '../../node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
4
|
+
import { useMergeRefs } from '../../packages/react/node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
5
5
|
import { Slot as $5e63c961fc1ce211$export$8c6ed5c666ac1360 } from '../../node_modules/@radix-ui/react-slot/dist/index.js';
|
|
6
6
|
import { DropdownMenuContext } from './DropdownMenu.js';
|
|
7
7
|
import { Button } from '../Button/Button.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
3
|
-
import { useFloating, useMergeRefs, FloatingFocusManager } from '../../node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
3
|
+
import { useFloating, useMergeRefs, FloatingFocusManager } from '../../packages/react/node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
4
4
|
import { forwardRef, useRef, useContext, useEffect } from 'react';
|
|
5
5
|
import { Slot as $5e63c961fc1ce211$export$8c6ed5c666ac1360 } from '../../node_modules/@radix-ui/react-slot/dist/index.js';
|
|
6
6
|
import { clsx } from '../../node_modules/clsx/dist/clsx.js';
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { forwardRef, useContext, useRef, useEffect, useMemo } from 'react';
|
|
5
|
-
import { useFloating, useInteractions, useFocus, useClick, useDismiss, useRole, useMergeRefs, FloatingPortal } from '../../node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
5
|
+
import { useFloating, useInteractions, useFocus, useClick, useDismiss, useRole, useMergeRefs, FloatingPortal } from '../../packages/react/node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
6
6
|
import { clsx } from '../../node_modules/clsx/dist/clsx.js';
|
|
7
7
|
import { PopoverContext } from './Popover.js';
|
|
8
8
|
import classes from './Popover.module.css.js';
|
|
9
|
-
import { autoUpdate } from '../../node_modules/@floating-ui/dom/dist/floating-ui.dom.js';
|
|
10
|
-
import { offset
|
|
11
|
-
import { arrow } from '../../node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.js';
|
|
9
|
+
import { autoUpdate, flip, shift } from '../../packages/react/node_modules/@floating-ui/dom/dist/floating-ui.dom.js';
|
|
10
|
+
import { offset } from '../../packages/react/node_modules/@floating-ui/core/dist/floating-ui.core.js';
|
|
11
|
+
import { arrow } from '../../packages/react/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.js';
|
|
12
12
|
import { useIsomorphicLayoutEffect } from '../../hooks/useIsomorphicLayoutEffect.js';
|
|
13
13
|
import { Paragraph } from '../Typography/Paragraph/Paragraph.js';
|
|
14
14
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { forwardRef, useContext, useEffect } from 'react';
|
|
4
|
-
import { useMergeRefs } from '../../node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
4
|
+
import { useMergeRefs } from '../../packages/react/node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
5
5
|
import { Slot as $5e63c961fc1ce211$export$8c6ed5c666ac1360 } from '../../node_modules/@radix-ui/react-slot/dist/index.js';
|
|
6
6
|
import { PopoverContext } from './Popover.js';
|
|
7
7
|
import { Button } from '../Button/Button.js';
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { clsx } from '../../node_modules/clsx/dist/clsx.js';
|
|
4
|
-
import classes from './SkipLink.module.css.js';
|
|
5
4
|
|
|
6
5
|
const SkipLink = ({ href, children, className, ...rest }) => {
|
|
7
|
-
return (jsx("a", { href: href, className: clsx(`fds-sr-only`,
|
|
6
|
+
return (jsx("a", { href: href, className: clsx(`fds-sr-only`, 'fds-skiplink', className), ...rest, children: children }));
|
|
8
7
|
};
|
|
9
8
|
SkipLink.displayName = 'SkipLink';
|
|
10
9
|
|
|
@@ -3,11 +3,11 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { forwardRef, useState, cloneElement } from 'react';
|
|
5
5
|
import { clsx } from '../../node_modules/clsx/dist/clsx.js';
|
|
6
|
-
import { useFloating, useTransitionStyles, useInteractions, useHover, useFocus, useDismiss, useRole, useMergeRefs, FloatingPortal, FloatingArrow } from '../../node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
6
|
+
import { useFloating, useTransitionStyles, useInteractions, useHover, useFocus, useDismiss, useRole, useMergeRefs, FloatingPortal, FloatingArrow } from '../../packages/react/node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
7
7
|
import classes from './Tooltip.module.css.js';
|
|
8
|
-
import { autoUpdate } from '../../node_modules/@floating-ui/dom/dist/floating-ui.dom.js';
|
|
9
|
-
import { offset
|
|
10
|
-
import { arrow } from '../../node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.js';
|
|
8
|
+
import { autoUpdate, flip, shift } from '../../packages/react/node_modules/@floating-ui/dom/dist/floating-ui.dom.js';
|
|
9
|
+
import { offset } from '../../packages/react/node_modules/@floating-ui/core/dist/floating-ui.core.js';
|
|
10
|
+
import { arrow } from '../../packages/react/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.js';
|
|
11
11
|
|
|
12
12
|
const ARROW_HEIGHT = 7;
|
|
13
13
|
const ARROW_GAP = 4;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import { forwardRef } from 'react';
|
|
4
4
|
import { clsx } from '../../../node_modules/clsx/dist/clsx.js';
|
|
5
|
-
import { useMergeRefs } from '../../../node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
5
|
+
import { useMergeRefs } from '../../../packages/react/node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
6
6
|
import classes from './Checkbox.module.css.js';
|
|
7
7
|
import { useCheckbox } from './useCheckbox.js';
|
|
8
8
|
import { Paragraph } from '../../Typography/Paragraph/Paragraph.js';
|
|
@@ -1,150 +1,105 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
|
-
import { forwardRef, useRef, useId, useState, useEffect
|
|
4
|
-
import {
|
|
3
|
+
import { forwardRef, useRef, useId, useState, useEffect } from 'react';
|
|
4
|
+
import { FloatingPortal, FloatingFocusManager } from '../../../packages/react/node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
5
5
|
import { clsx } from '../../../node_modules/clsx/dist/clsx.js';
|
|
6
6
|
import { useVirtualizer } from '../../../node_modules/@tanstack/react-virtual/dist/esm/index.js';
|
|
7
|
-
import { flushSync } from 'react-dom';
|
|
8
7
|
import { useFormField } from '../useFormField.js';
|
|
9
8
|
import useDebounce from '../../../utilities/useDebounce.js';
|
|
10
|
-
import useCombobox
|
|
9
|
+
import useCombobox from './useCombobox.js';
|
|
11
10
|
import classes from './Combobox.module.css.js';
|
|
12
11
|
import ComboboxInput from './internal/ComboboxInput.js';
|
|
13
12
|
import ComboboxLabel from './internal/ComboboxLabel.js';
|
|
14
13
|
import ComboboxError from './internal/ComboboxError.js';
|
|
15
14
|
import ComboboxNative from './internal/ComboboxNative.js';
|
|
16
15
|
import ComboboxCustom from './Custom/Custom.js';
|
|
16
|
+
import { useFloatingCombobox } from './useFloatingCombobox.js';
|
|
17
|
+
import { useComboboxKeyboard } from './useComboboxKeyboard.js';
|
|
18
|
+
import { ComboboxIdProvider } from './ComboboxIdContext.js';
|
|
19
|
+
import { ComboboxContext } from './ComboboxContext.js';
|
|
17
20
|
import { Box } from '../../Box/Box.js';
|
|
18
21
|
import { Spinner } from '../../Spinner/Spinner.js';
|
|
19
|
-
import { autoUpdate } from '../../../node_modules/@floating-ui/dom/dist/floating-ui.dom.js';
|
|
20
|
-
import { flip, size, offset } from '../../../node_modules/@floating-ui/core/dist/floating-ui.core.js';
|
|
21
22
|
import { omit } from '../../../utilities/objectUtils.js';
|
|
22
23
|
|
|
23
|
-
const
|
|
24
|
-
return option.label.toLowerCase().startsWith(inputValue.toLowerCase());
|
|
25
|
-
}, chipSrLabel = (option) => 'Slett ' + option.label, className, ...rest }, forwareddRef) => {
|
|
24
|
+
const ComboboxComponent = forwardRef(({ value, initialValue = [], onValueChange, label, hideLabel = false, description, multiple = false, size = 'medium', disabled = false, readOnly = false, hideChips = false, cleanButtonLabel = 'Fjern alt', clearButtonLabel = 'Fjern alt', hideClearButton = false, error, errorId, id, name, portal = true, htmlSize = 0, virtual = false, children, style, loading, loadingLabel = 'Laster...', filter, chipSrLabel = (option) => 'Slett ' + option.label, className, ...rest }, forwareddRef) => {
|
|
26
25
|
const inputRef = useRef(null);
|
|
27
26
|
const portalRef = useRef(null);
|
|
27
|
+
const listRef = useRef([]);
|
|
28
28
|
const listId = useId();
|
|
29
|
-
const [open, setOpen] = useState(false);
|
|
30
29
|
const [inputValue, setInputValue] = useState(rest.inputValue || '');
|
|
31
|
-
const
|
|
32
|
-
const { selectedOptions,
|
|
30
|
+
/* const idDispatch = useComboboxIdDispatch(); */
|
|
31
|
+
const { selectedOptions, options, restChildren, interactiveChildren, optionValues, customIds, filteredOptionsChildren, filteredOptions, prevSelectedHash, setSelectedOptions, setPrevSelectedHash, } = useCombobox({
|
|
33
32
|
children,
|
|
34
33
|
inputValue,
|
|
35
34
|
filter,
|
|
36
35
|
multiple,
|
|
37
36
|
initialValue,
|
|
38
37
|
});
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
setInputValue(rest.inputValue);
|
|
43
|
-
}
|
|
44
|
-
}, [rest.inputValue]);
|
|
38
|
+
const { open, setOpen, refs, floatingStyles, context, getReferenceProps, getFloatingProps, getItemProps, } = useFloatingCombobox({
|
|
39
|
+
listRef,
|
|
40
|
+
});
|
|
45
41
|
const formFieldProps = useFormField({
|
|
46
42
|
disabled,
|
|
47
43
|
readOnly,
|
|
48
44
|
error,
|
|
49
45
|
errorId,
|
|
50
|
-
size
|
|
46
|
+
size,
|
|
51
47
|
description,
|
|
52
48
|
id,
|
|
53
49
|
}, 'combobox');
|
|
54
|
-
const listRef = useRef([]);
|
|
55
50
|
// if value is set, set input value to the label of the value
|
|
56
51
|
useEffect(() => {
|
|
57
|
-
if (value && value.length
|
|
58
|
-
const option = options
|
|
52
|
+
if (value && value.length >= 0 && !multiple) {
|
|
53
|
+
const option = options[value[0]];
|
|
59
54
|
setInputValue(option?.label || '');
|
|
60
55
|
}
|
|
61
56
|
}, [multiple, value, options]);
|
|
62
|
-
// floating UI
|
|
63
|
-
const { refs, floatingStyles, context } = useFloating({
|
|
64
|
-
open,
|
|
65
|
-
onOpenChange: (newOpen) => {
|
|
66
|
-
flushSync(() => {
|
|
67
|
-
if (refs.floating.current && !newOpen) {
|
|
68
|
-
refs.floating.current.scrollTop = 0;
|
|
69
|
-
}
|
|
70
|
-
setTimeout(() => {
|
|
71
|
-
setOpen(newOpen);
|
|
72
|
-
}, 1);
|
|
73
|
-
});
|
|
74
|
-
},
|
|
75
|
-
whileElementsMounted: (reference, floating, update) => {
|
|
76
|
-
autoUpdate(reference, floating, update);
|
|
77
|
-
return () => {
|
|
78
|
-
floating.scrollTop = 0;
|
|
79
|
-
};
|
|
80
|
-
},
|
|
81
|
-
middleware: [
|
|
82
|
-
flip({ padding: 10 }),
|
|
83
|
-
size({
|
|
84
|
-
apply({ rects, elements }) {
|
|
85
|
-
requestAnimationFrame(() => {
|
|
86
|
-
Object.assign(elements.floating.style, {
|
|
87
|
-
width: `calc(${rects.reference.width}px - calc(var(--fds-spacing-2) * 2))`,
|
|
88
|
-
maxHeight: `200px`,
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
},
|
|
92
|
-
}),
|
|
93
|
-
offset(10),
|
|
94
|
-
],
|
|
95
|
-
});
|
|
96
|
-
const role = useRole(context, { role: 'listbox' });
|
|
97
|
-
const dismiss = useDismiss(context);
|
|
98
|
-
const listNav = useListNavigation(context, {
|
|
99
|
-
listRef,
|
|
100
|
-
activeIndex,
|
|
101
|
-
virtual: true,
|
|
102
|
-
scrollItemIntoView: true,
|
|
103
|
-
enabled: open,
|
|
104
|
-
});
|
|
105
|
-
const { getReferenceProps, getFloatingProps } = useInteractions([
|
|
106
|
-
role,
|
|
107
|
-
dismiss,
|
|
108
|
-
listNav,
|
|
109
|
-
]);
|
|
110
|
-
// remove active index if combobox is closed
|
|
111
|
-
useEffect(() => {
|
|
112
|
-
if (!open) {
|
|
113
|
-
setActiveIndex(null);
|
|
114
|
-
}
|
|
115
|
-
}, [open]);
|
|
116
57
|
// Send new value if option was clicked
|
|
117
58
|
useEffect(() => {
|
|
118
59
|
const selectedHash = JSON.stringify(selectedOptions);
|
|
119
60
|
if (prevSelectedHash === selectedHash)
|
|
120
61
|
return;
|
|
121
|
-
const values =
|
|
62
|
+
const values = Object.keys(selectedOptions);
|
|
122
63
|
onValueChange?.(values);
|
|
123
64
|
setPrevSelectedHash(selectedHash);
|
|
124
65
|
}, [onValueChange, selectedOptions, prevSelectedHash, setPrevSelectedHash]);
|
|
125
66
|
useEffect(() => {
|
|
126
|
-
if (value && options.length
|
|
67
|
+
if (value && Object.keys(options).length >= 0) {
|
|
127
68
|
const updatedSelectedOptions = value.map((option) => {
|
|
128
|
-
const value = options
|
|
69
|
+
const value = options[option];
|
|
129
70
|
return value;
|
|
130
71
|
});
|
|
131
|
-
setSelectedOptions(updatedSelectedOptions)
|
|
72
|
+
setSelectedOptions(updatedSelectedOptions.reduce((acc, value) => {
|
|
73
|
+
acc[value.value] = value;
|
|
74
|
+
return acc;
|
|
75
|
+
}, {}));
|
|
132
76
|
}
|
|
133
77
|
}, [multiple, prevSelectedHash, value, options, setSelectedOptions]);
|
|
134
78
|
// handle click on option, either select or deselect - Handles single or multiple
|
|
135
79
|
const handleSelectOption = (option) => {
|
|
136
80
|
// if option is already selected, remove it
|
|
137
81
|
if (value && value.includes(option.value)) {
|
|
138
|
-
setSelectedOptions((prev) =>
|
|
82
|
+
setSelectedOptions((prev) => {
|
|
83
|
+
const updated = { ...prev };
|
|
84
|
+
delete updated[option.value];
|
|
85
|
+
return updated;
|
|
86
|
+
});
|
|
139
87
|
return;
|
|
140
88
|
}
|
|
141
89
|
if (multiple) {
|
|
142
|
-
setSelectedOptions([...selectedOptions, option]);
|
|
90
|
+
/* setSelectedOptions([...selectedOptions, option]); */
|
|
91
|
+
setSelectedOptions((prev) => {
|
|
92
|
+
const updated = { ...prev };
|
|
93
|
+
updated[option.value] = option;
|
|
94
|
+
return updated;
|
|
95
|
+
});
|
|
143
96
|
setInputValue('');
|
|
144
97
|
inputRef.current?.focus();
|
|
145
98
|
}
|
|
146
99
|
else {
|
|
147
|
-
setSelectedOptions(
|
|
100
|
+
setSelectedOptions({
|
|
101
|
+
[option.value]: option,
|
|
102
|
+
});
|
|
148
103
|
setInputValue(option?.label || '');
|
|
149
104
|
// move cursor to the end of the input
|
|
150
105
|
setTimeout(() => {
|
|
@@ -155,87 +110,24 @@ const Combobox = forwardRef(({ value, initialValue = [], onValueChange, label, h
|
|
|
155
110
|
refs.domReference.current?.focus();
|
|
156
111
|
};
|
|
157
112
|
const debouncedHandleSelectOption = useDebounce(handleSelectOption, 50);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
return Math.min(prevActiveIndex + 1, navigateable - 1);
|
|
175
|
-
});
|
|
176
|
-
break;
|
|
177
|
-
case 'ArrowUp':
|
|
178
|
-
event.preventDefault();
|
|
179
|
-
/* If we are on the first item, close */
|
|
180
|
-
setActiveIndex((prevActiveIndex) => {
|
|
181
|
-
if (prevActiveIndex === 0) {
|
|
182
|
-
setOpen(false);
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
if (prevActiveIndex === null) {
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
|
-
return Math.max(prevActiveIndex - 1, 0);
|
|
189
|
-
});
|
|
190
|
-
break;
|
|
191
|
-
case 'Enter':
|
|
192
|
-
event.preventDefault();
|
|
193
|
-
if (activeIndex !== null &&
|
|
194
|
-
(optionsChildren[activeIndex] || customIds.length > 0)) {
|
|
195
|
-
// check if we are in the custom components
|
|
196
|
-
if (activeIndex <= customIds.length) {
|
|
197
|
-
// send `onSelect` event to the custom component
|
|
198
|
-
const selectedId = customIds[activeIndex];
|
|
199
|
-
const selectedComponent = restChildren.find((component) => isInteractiveComboboxCustom(component) &&
|
|
200
|
-
component.props?.id === selectedId);
|
|
201
|
-
if (isInteractiveComboboxCustom(selectedComponent) &&
|
|
202
|
-
selectedComponent.props.onSelect) {
|
|
203
|
-
selectedComponent.props.onSelect();
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
// if we are in the options, find the actual index
|
|
207
|
-
const valueIndex = activeIndex - customIds.length;
|
|
208
|
-
const child = optionsChildren[valueIndex];
|
|
209
|
-
if (isComboboxOption(child)) {
|
|
210
|
-
const props = child.props;
|
|
211
|
-
const option = options.find((option) => option.value === props.value);
|
|
212
|
-
if (!multiple) {
|
|
213
|
-
// check if option is already selected, if so, deselect it
|
|
214
|
-
if (selectedOptions.find((i) => i.value === option?.value)) {
|
|
215
|
-
setSelectedOptions([]);
|
|
216
|
-
setInputValue('');
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
debouncedHandleSelectOption(option);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
break;
|
|
224
|
-
case 'Backspace':
|
|
225
|
-
if (inputValue === '' && multiple && selectedOptions.length > 0) {
|
|
226
|
-
setSelectedOptions((prev) => prev.slice(0, prev.length - 1));
|
|
227
|
-
}
|
|
228
|
-
// if we are in single mode, we need to set activeValue to null
|
|
229
|
-
if (!multiple) {
|
|
230
|
-
setSelectedOptions([]);
|
|
231
|
-
}
|
|
232
|
-
break;
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
const handleKeyDown = useDebounce(handleKeyDownFunc, 20);
|
|
113
|
+
const handleKeyDown = useComboboxKeyboard({
|
|
114
|
+
filteredOptions,
|
|
115
|
+
selectedOptions,
|
|
116
|
+
readOnly: formFieldProps.readOnly || false,
|
|
117
|
+
disabled: disabled,
|
|
118
|
+
multiple,
|
|
119
|
+
inputValue,
|
|
120
|
+
options,
|
|
121
|
+
open,
|
|
122
|
+
interactiveChildren,
|
|
123
|
+
setOpen,
|
|
124
|
+
setInputValue,
|
|
125
|
+
setSelectedOptions,
|
|
126
|
+
handleSelectOption: debouncedHandleSelectOption,
|
|
127
|
+
});
|
|
236
128
|
const rowVirtualizer = useVirtualizer({
|
|
237
|
-
count:
|
|
238
|
-
getScrollElement: () => refs.floating.current,
|
|
129
|
+
count: Object.keys(filteredOptionsChildren).length,
|
|
130
|
+
getScrollElement: () => (virtual ? refs.floating.current : null),
|
|
239
131
|
estimateSize: () => 70,
|
|
240
132
|
measureElement: (elem) => {
|
|
241
133
|
return elem.getBoundingClientRect().height;
|
|
@@ -243,18 +135,16 @@ const Combobox = forwardRef(({ value, initialValue = [], onValueChange, label, h
|
|
|
243
135
|
overscan: 1,
|
|
244
136
|
});
|
|
245
137
|
return (jsxs(ComboboxContext.Provider, { value: {
|
|
246
|
-
size
|
|
138
|
+
size,
|
|
247
139
|
options,
|
|
248
140
|
selectedOptions,
|
|
249
141
|
multiple,
|
|
250
|
-
activeIndex,
|
|
251
142
|
disabled,
|
|
252
143
|
readOnly,
|
|
253
144
|
open,
|
|
254
145
|
inputRef,
|
|
255
146
|
refs,
|
|
256
147
|
inputValue,
|
|
257
|
-
activeDescendant,
|
|
258
148
|
error,
|
|
259
149
|
formFieldProps,
|
|
260
150
|
name,
|
|
@@ -264,40 +154,33 @@ const Combobox = forwardRef(({ value, initialValue = [], onValueChange, label, h
|
|
|
264
154
|
clearButtonLabel: cleanButtonLabel || clearButtonLabel,
|
|
265
155
|
hideClearButton,
|
|
266
156
|
listId,
|
|
157
|
+
customIds,
|
|
158
|
+
filteredOptions,
|
|
267
159
|
setInputValue,
|
|
268
|
-
setActiveIndex,
|
|
269
160
|
handleKeyDown,
|
|
270
161
|
setOpen,
|
|
271
162
|
getReferenceProps,
|
|
163
|
+
getItemProps,
|
|
272
164
|
setSelectedOptions,
|
|
273
|
-
/* Recieves index of option, and the ID of the button element */
|
|
274
|
-
setActiveOption: (index, id) => {
|
|
275
|
-
if (readOnly)
|
|
276
|
-
return;
|
|
277
|
-
if (disabled)
|
|
278
|
-
return;
|
|
279
|
-
setActiveIndex(index);
|
|
280
|
-
setActiveDescendant(id);
|
|
281
|
-
},
|
|
282
165
|
/* Recieves the value of the option, and searches for it in our values lookup */
|
|
283
166
|
onOptionClick: (value) => {
|
|
284
167
|
if (readOnly)
|
|
285
168
|
return;
|
|
286
169
|
if (disabled)
|
|
287
170
|
return;
|
|
288
|
-
const option = options
|
|
171
|
+
const option = options[value];
|
|
289
172
|
debouncedHandleSelectOption(option);
|
|
290
173
|
},
|
|
291
174
|
handleSelectOption: debouncedHandleSelectOption,
|
|
292
175
|
chipSrLabel,
|
|
293
176
|
listRef,
|
|
294
177
|
forwareddRef,
|
|
295
|
-
}, children: [jsxs(Box, { className: clsx(classes.combobox, disabled && classes.disabled, className), style: style, ref: portalRef, children: [name && (jsx(ComboboxNative, { name: name, selectedOptions: selectedOptions, multiple: multiple })), jsx(ComboboxLabel, { label: label, description: description, size: size
|
|
178
|
+
}, children: [jsxs(Box, { className: clsx(classes.combobox, disabled && classes.disabled, className), style: style, ref: portalRef, children: [name && (jsx(ComboboxNative, { name: name, selectedOptions: selectedOptions, multiple: multiple })), jsx(ComboboxLabel, { label: label, description: description, size: size, readOnly: readOnly, hideLabel: hideLabel, formFieldProps: formFieldProps }), jsx(ComboboxInput, { ...omit(['inputValue'], rest), "aria-busy": loading }), jsx(ComboboxError, { size: size, error: error, formFieldProps: formFieldProps })] }), open && (jsx(FloatingPortal, { root: portal ? null : portalRef, children: jsx(FloatingFocusManager, { context: context, initialFocus: -1, visuallyHiddenDismiss: true, children: jsxs(Box, { id: listId, shadow: 'medium', borderRadius: 'medium', borderColor: 'default', "aria-labelledby": formFieldProps.inputProps.id, "aria-autocomplete": 'list', tabIndex: -1, ...getFloatingProps({
|
|
296
179
|
ref: refs.setFloating,
|
|
297
180
|
style: {
|
|
298
181
|
...floatingStyles,
|
|
299
182
|
},
|
|
300
|
-
}), className: clsx(classes.optionsWrapper, classes[size
|
|
183
|
+
}), className: clsx(classes.optionsWrapper, classes[size]), children: [virtual && (jsx("div", { style: {
|
|
301
184
|
height: `${rowVirtualizer.getTotalSize()}px`,
|
|
302
185
|
width: '100%',
|
|
303
186
|
position: 'relative',
|
|
@@ -307,9 +190,9 @@ const Combobox = forwardRef(({ value, initialValue = [], onValueChange, label, h
|
|
|
307
190
|
left: 0,
|
|
308
191
|
width: '100%',
|
|
309
192
|
transform: `translateY(${virtualRow.start}px)`,
|
|
310
|
-
}, children:
|
|
193
|
+
}, children: filteredOptionsChildren[virtualRow.index] }, virtualRow.index))) })), loading ? (jsxs(ComboboxCustom, { className: classes.loading, children: [jsx(Spinner, { title: 'Laster', size: 'small' }), loadingLabel] })) : (jsxs(Fragment, { children: [restChildren, !virtual && filteredOptionsChildren] }))] }) }) }))] }));
|
|
311
194
|
});
|
|
312
|
-
const
|
|
195
|
+
const Combobox = forwardRef((props, ref) => (jsx(ComboboxIdProvider, { children: jsx(ComboboxComponent, { ...props, ref: ref }) })));
|
|
313
196
|
Combobox.displayName = 'Combobox';
|
|
314
197
|
|
|
315
|
-
export { Combobox,
|
|
198
|
+
export { Combobox, ComboboxComponent };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { createContext, useContext, useReducer } from 'react';
|
|
4
|
+
|
|
5
|
+
const ComboboxIdContext = createContext({
|
|
6
|
+
activeIndex: 0,
|
|
7
|
+
});
|
|
8
|
+
const ComboboxIdReducer = (state, action) => {
|
|
9
|
+
switch (action.type) {
|
|
10
|
+
case 'SET_ACTIVE_INDEX':
|
|
11
|
+
return {
|
|
12
|
+
...state,
|
|
13
|
+
activeIndex: action.payload,
|
|
14
|
+
};
|
|
15
|
+
default:
|
|
16
|
+
return state;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const ComboboxIdDispatch = createContext(() => {
|
|
20
|
+
throw new Error('ComboboxIdDispatch must be used within a provider');
|
|
21
|
+
});
|
|
22
|
+
const ComboboxIdProvider = ({ children, }) => {
|
|
23
|
+
const [state, dispatch] = useReducer(ComboboxIdReducer, {
|
|
24
|
+
activeIndex: 0,
|
|
25
|
+
});
|
|
26
|
+
return (jsx(ComboboxIdContext.Provider, { value: state, children: jsx(ComboboxIdDispatch.Provider, { value: dispatch, children: children }) }));
|
|
27
|
+
};
|
|
28
|
+
function useComboboxIdDispatch() {
|
|
29
|
+
return useContext(ComboboxIdDispatch);
|
|
30
|
+
}
|
|
31
|
+
function useComboboxId() {
|
|
32
|
+
return useContext(ComboboxIdContext);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { ComboboxIdContext, ComboboxIdDispatch, ComboboxIdProvider, ComboboxIdReducer, useComboboxId, useComboboxIdDispatch };
|
|
@@ -3,7 +3,9 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import { forwardRef, useId, useContext, useMemo } from 'react';
|
|
4
4
|
import { clsx } from '../../../../node_modules/clsx/dist/clsx.js';
|
|
5
5
|
import { Slot as $5e63c961fc1ce211$export$8c6ed5c666ac1360 } from '../../../../node_modules/@radix-ui/react-slot/dist/index.js';
|
|
6
|
-
import {
|
|
6
|
+
import { useMergeRefs } from '../../../../packages/react/node_modules/@floating-ui/react/dist/floating-ui.react.js';
|
|
7
|
+
import { ComboboxContext } from '../ComboboxContext.js';
|
|
8
|
+
import { useComboboxId } from '../ComboboxIdContext.js';
|
|
7
9
|
import classes from './Custom.module.css.js';
|
|
8
10
|
import { omit } from '../../../../utilities/objectUtils.js';
|
|
9
11
|
|
|
@@ -13,17 +15,20 @@ const ComboboxCustom = forwardRef(({ asChild, interactive, id, className, ...res
|
|
|
13
15
|
}
|
|
14
16
|
const Component = asChild ? $5e63c961fc1ce211$export$8c6ed5c666ac1360 : 'div';
|
|
15
17
|
const randomId = useId();
|
|
18
|
+
const { activeIndex } = useComboboxId();
|
|
16
19
|
const context = useContext(ComboboxContext);
|
|
17
20
|
if (!context) {
|
|
18
21
|
throw new Error('ComboboxCustom must be used within a Combobox');
|
|
19
22
|
}
|
|
20
|
-
const { size,
|
|
21
|
-
const index = useMemo(() => id &&
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
const { size, customIds, listRef, getItemProps } = context;
|
|
24
|
+
const index = useMemo(() => (id && customIds.indexOf(id)) || 0, [id, customIds]);
|
|
25
|
+
const combinedRef = useMergeRefs([
|
|
26
|
+
(node) => {
|
|
27
|
+
listRef.current[index] = node;
|
|
28
|
+
},
|
|
29
|
+
ref,
|
|
30
|
+
]);
|
|
31
|
+
return (jsx(Component, { ref: combinedRef, tabIndex: -1, className: clsx(classes.custom, classes[size], className), id: id || randomId, role: 'option', "aria-selected": activeIndex === index, "data-active": activeIndex === index, ...omit(['interactive'], rest), ...omit(['onClick', 'onPointerLeave'], getItemProps()) }));
|
|
27
32
|
});
|
|
28
33
|
var ComboboxCustom$1 = ComboboxCustom;
|
|
29
34
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { forwardRef, useContext } from 'react';
|
|
4
4
|
import { clsx } from '../../../../node_modules/clsx/dist/clsx.js';
|
|
5
|
-
import { ComboboxContext } from '../
|
|
5
|
+
import { ComboboxContext } from '../ComboboxContext.js';
|
|
6
6
|
import classes from './Empty.module.css.js';
|
|
7
7
|
|
|
8
8
|
const ComboboxEmpty = forwardRef(({ children, className, ...rest }, ref) => {
|
|
@@ -10,8 +10,8 @@ const ComboboxEmpty = forwardRef(({ children, className, ...rest }, ref) => {
|
|
|
10
10
|
if (!context) {
|
|
11
11
|
throw new Error('ComboboxEmpty must be used within a Combobox');
|
|
12
12
|
}
|
|
13
|
-
const {
|
|
14
|
-
return (
|
|
13
|
+
const { filteredOptions, size } = context;
|
|
14
|
+
return (filteredOptions.length === 0 && (jsx("div", { ref: ref, className: clsx(classes.empty, classes[size], className), ...rest, children: children })));
|
|
15
15
|
});
|
|
16
16
|
ComboboxEmpty.displayName = 'ComboboxEmpty';
|
|
17
17
|
|