@digdir/designsystemet-react 0.59.1-alpha.0 → 0.59.1-alpha.1
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/Accordion/Accordion.js +1 -4
- package/dist/cjs/components/Accordion/AccordionContent/AccordionContent.js +1 -2
- package/dist/cjs/components/Accordion/AccordionHeader/AccordionHeader.js +1 -2
- package/dist/cjs/components/Accordion/AccordionItem/AccordionItem.js +1 -4
- package/dist/cjs/components/Button/Button.js +2 -2
- package/dist/cjs/components/Modal/ModalHeader/ModalHeader.js +1 -1
- package/dist/cjs/components/Modal/ModalHeader/ModalHeader.module.css.js +1 -1
- package/dist/cjs/components/form/Combobox/Combobox.js +33 -43
- package/dist/cjs/components/form/Combobox/Combobox.module.css.js +1 -1
- package/dist/cjs/components/form/Combobox/internal/ComboboxChips.js +7 -12
- package/dist/cjs/components/form/Combobox/internal/ComboboxClearButton.js +3 -6
- package/dist/cjs/components/form/Combobox/internal/ComboboxInput.js +6 -40
- package/dist/cjs/components/form/Combobox/useCombobox.js +48 -60
- package/dist/cjs/components/form/Combobox/useComboboxKeyboard.js +25 -28
- package/dist/cjs/node_modules/clsx/dist/clsx.js +1 -1
- package/dist/cjs/node_modules/clsx/dist/lite.js +9 -0
- package/dist/cjs/react-css-modules.css +2 -136
- package/dist/esm/components/Accordion/Accordion.js +1 -4
- package/dist/esm/components/Accordion/AccordionContent/AccordionContent.js +1 -2
- package/dist/esm/components/Accordion/AccordionHeader/AccordionHeader.js +1 -2
- package/dist/esm/components/Accordion/AccordionItem/AccordionItem.js +1 -4
- package/dist/esm/components/Button/Button.js +2 -2
- package/dist/esm/components/Modal/ModalHeader/ModalHeader.js +1 -1
- package/dist/esm/components/Modal/ModalHeader/ModalHeader.module.css.js +1 -1
- package/dist/esm/components/form/Combobox/Combobox.js +33 -43
- package/dist/esm/components/form/Combobox/Combobox.module.css.js +1 -1
- package/dist/esm/components/form/Combobox/internal/ComboboxChips.js +7 -12
- package/dist/esm/components/form/Combobox/internal/ComboboxClearButton.js +3 -6
- package/dist/esm/components/form/Combobox/internal/ComboboxInput.js +7 -41
- package/dist/esm/components/form/Combobox/useCombobox.js +48 -60
- package/dist/esm/components/form/Combobox/useComboboxKeyboard.js +25 -28
- package/dist/esm/node_modules/clsx/dist/clsx.js +1 -1
- package/dist/esm/node_modules/clsx/dist/lite.js +4 -0
- package/dist/esm/react-css-modules.css +2 -136
- package/dist/types/components/Accordion/Accordion.d.ts.map +1 -1
- package/dist/types/components/Accordion/AccordionContent/AccordionContent.d.ts.map +1 -1
- package/dist/types/components/Accordion/AccordionHeader/AccordionHeader.d.ts.map +1 -1
- package/dist/types/components/Accordion/AccordionItem/AccordionItem.d.ts.map +1 -1
- package/dist/types/components/Modal/ModalHeader/ModalHeader.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/Combobox.d.ts +0 -18
- package/dist/types/components/form/Combobox/Combobox.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/ComboboxContext.d.ts +6 -13
- package/dist/types/components/form/Combobox/ComboboxContext.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/internal/ComboboxChips.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/internal/ComboboxClearButton.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/internal/ComboboxInput.d.ts +9 -1
- package/dist/types/components/form/Combobox/internal/ComboboxInput.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/useCombobox.d.ts +1 -4
- package/dist/types/components/form/Combobox/useCombobox.d.ts.map +1 -1
- package/dist/types/components/form/Combobox/useComboboxKeyboard.d.ts +3 -4
- package/dist/types/components/form/Combobox/useComboboxKeyboard.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/cjs/components/Accordion/Accordion.module.css.js +0 -6
- package/dist/esm/components/Accordion/Accordion.module.css.js +0 -4
|
@@ -4,11 +4,8 @@
|
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
var React = require('react');
|
|
6
6
|
var clsx = require('../../node_modules/clsx/dist/clsx.js');
|
|
7
|
-
var Accordion_module = require('./Accordion.module.css.js');
|
|
8
7
|
|
|
9
|
-
const Accordion = React.forwardRef(({ border = false, color = 'neutral', className, ...rest }, ref) => (jsxRuntime.jsx("div", { className: clsx.clsx(
|
|
10
|
-
[Accordion_module.border]: border,
|
|
11
|
-
}, className), ref: ref, ...rest })));
|
|
8
|
+
const Accordion = React.forwardRef(({ border = false, color = 'neutral', className, ...rest }, ref) => (jsxRuntime.jsx("div", { className: clsx.clsx('fds-accordion', border && 'fds-accordion--border', color && `fds-accordion--${color}`, className), ref: ref, ...rest })));
|
|
12
9
|
Accordion.displayName = 'Accordion';
|
|
13
10
|
|
|
14
11
|
exports.Accordion = Accordion;
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
var clsx = require('../../../node_modules/clsx/dist/clsx.js');
|
|
6
6
|
var React = require('react');
|
|
7
|
-
var Accordion_module = require('../Accordion.module.css.js');
|
|
8
7
|
var AccordionItem = require('../AccordionItem/AccordionItem.js');
|
|
9
8
|
var AnimateHeight = require('../../../utilities/AnimateHeight/AnimateHeight.js');
|
|
10
9
|
var Paragraph = require('../../Typography/Paragraph/Paragraph.js');
|
|
@@ -15,7 +14,7 @@ const AccordionContent = React.forwardRef(({ children, className, ...rest }, ref
|
|
|
15
14
|
console.error('<Accordion.Content> has to be used within an <Accordion.Item>');
|
|
16
15
|
return null;
|
|
17
16
|
}
|
|
18
|
-
return (jsxRuntime.jsx(AnimateHeight.AnimateHeight, { id: context.contentId, open: context.open, children: jsxRuntime.jsx(Paragraph.Paragraph, { asChild: true, size: 'small', children: jsxRuntime.jsx("div", { ref: ref, className: clsx.clsx(
|
|
17
|
+
return (jsxRuntime.jsx(AnimateHeight.AnimateHeight, { id: context.contentId, open: context.open, children: jsxRuntime.jsx(Paragraph.Paragraph, { asChild: true, size: 'small', children: jsxRuntime.jsx("div", { ref: ref, className: clsx.clsx('fds-accordion__content', className), ...rest, children: children }) }) }));
|
|
19
18
|
});
|
|
20
19
|
AccordionContent.displayName = 'AccordionContent';
|
|
21
20
|
|
|
@@ -5,7 +5,6 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
5
5
|
var akselIcons = require('@navikt/aksel-icons');
|
|
6
6
|
var clsx = require('../../../node_modules/clsx/dist/clsx.js');
|
|
7
7
|
var React = require('react');
|
|
8
|
-
var Accordion_module = require('../Accordion.module.css.js');
|
|
9
8
|
var AccordionItem = require('../AccordionItem/AccordionItem.js');
|
|
10
9
|
var Heading = require('../../Typography/Heading/Heading.js');
|
|
11
10
|
var Paragraph = require('../../Typography/Paragraph/Paragraph.js');
|
|
@@ -20,7 +19,7 @@ const AccordionHeader = React.forwardRef(({ level = 1, children, className, onHe
|
|
|
20
19
|
context.toggleOpen();
|
|
21
20
|
onHeaderClick && onHeaderClick(e);
|
|
22
21
|
};
|
|
23
|
-
return (jsxRuntime.jsx(Heading.Heading, { ref: ref, size: 'xsmall', level: level, className: clsx.clsx(
|
|
22
|
+
return (jsxRuntime.jsx(Heading.Heading, { ref: ref, size: 'xsmall', level: level, className: clsx.clsx('fds-accordion__header', className), ...rest, children: jsxRuntime.jsxs("button", { type: 'button', className: clsx.clsx('fds-accordion__button', `fds-focus`), onClick: handleClick, "aria-expanded": context.open, "aria-controls": context.contentId, children: [jsxRuntime.jsx(akselIcons.ChevronDownIcon, { "aria-hidden": true, className: 'fds-accordion__expand-icon', fontSize: '1.5rem' }), jsxRuntime.jsx(Paragraph.Paragraph, { asChild: true, size: 'small', children: jsxRuntime.jsx("span", { children: children }) })] }) }));
|
|
24
23
|
});
|
|
25
24
|
AccordionHeader.displayName = 'AccordionHeader';
|
|
26
25
|
|
|
@@ -4,15 +4,12 @@
|
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
var clsx = require('../../../node_modules/clsx/dist/clsx.js');
|
|
6
6
|
var React = require('react');
|
|
7
|
-
var Accordion_module = require('../Accordion.module.css.js');
|
|
8
7
|
|
|
9
8
|
const AccordionItemContext = React.createContext(null);
|
|
10
9
|
const AccordionItem = React.forwardRef(({ children, className, open, defaultOpen = false, ...rest }, ref) => {
|
|
11
10
|
const [internalOpen, setInternalOpen] = React.useState(defaultOpen);
|
|
12
11
|
const contentId = React.useId();
|
|
13
|
-
return (jsxRuntime.jsx("div", { className: clsx.clsx(
|
|
14
|
-
[Accordion_module.open]: open ?? internalOpen,
|
|
15
|
-
}, className), ref: ref, ...rest, children: jsxRuntime.jsx(AccordionItemContext.Provider, { value: {
|
|
12
|
+
return (jsxRuntime.jsx("div", { className: clsx.clsx('fds-accordion__item', (open ?? internalOpen) && 'fds-accordion__item--open', className), ref: ref, ...rest, children: jsxRuntime.jsx(AccordionItemContext.Provider, { value: {
|
|
16
13
|
open: open ?? internalOpen,
|
|
17
14
|
toggleOpen: () => {
|
|
18
15
|
if (open === undefined) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
var React = require('react');
|
|
6
|
-
var
|
|
6
|
+
var lite = require('../../node_modules/clsx/dist/lite.js');
|
|
7
7
|
var index = require('../../node_modules/@radix-ui/react-slot/dist/index.js');
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -11,7 +11,7 @@ var index = require('../../node_modules/@radix-ui/react-slot/dist/index.js');
|
|
|
11
11
|
*/
|
|
12
12
|
const Button = React.forwardRef(({ children, color = 'first', variant = 'primary', size = 'medium', fullWidth = false, icon = false, type = 'button', className, as = 'button', asChild, ...rest }, ref) => {
|
|
13
13
|
const Component = asChild ? index.Slot : as;
|
|
14
|
-
return (jsxRuntime.jsx(Component, { ref: ref, type: type, className:
|
|
14
|
+
return (jsxRuntime.jsx(Component, { ref: ref, type: type, className: lite.clsx('fds-btn', `fds-focus`, `fds-btn--${size}`, `fds-btn--${variant}`, `fds-btn--${color}`, fullWidth && 'fds-btn--full-width', icon && 'fds-btn--icon-only', className), ...rest, children: children }));
|
|
15
15
|
});
|
|
16
16
|
Button.displayName = 'Button';
|
|
17
17
|
|
|
@@ -15,7 +15,7 @@ var Heading = require('../../Typography/Heading/Heading.js');
|
|
|
15
15
|
const ModalHeader = React.forwardRef(({ closeButton = true, children, subtitle, asChild, className, ...rest }, ref) => {
|
|
16
16
|
const Component = asChild ? index.Slot : 'div';
|
|
17
17
|
const context = React.useContext(ModalRoot.ModalContext);
|
|
18
|
-
return (jsxRuntime.jsxs(Component, { ref: ref, className: clsx.clsx(ModalHeader_module.modalHeader, !closeButton && ModalHeader_module.noCloseButton, className), ...rest, children: [subtitle && (jsxRuntime.jsx(Paragraph.Paragraph, { size: 'small', variant: 'short', children: subtitle })), jsxRuntime.jsx(Heading.Heading, { level: 2, size: 'xsmall', children: children }), closeButton && (jsxRuntime.jsx(Button.Button, { name: 'close', variant: 'tertiary', color: 'second', size: 'medium', onClick: context?.closeModal, autoFocus: true, icon: true, children: jsxRuntime.jsx(akselIcons.XMarkIcon, { title: 'close modal', fontSize: '1.5em' }) }))] }));
|
|
18
|
+
return (jsxRuntime.jsxs(Component, { ref: ref, className: clsx.clsx(ModalHeader_module.modalHeader, !closeButton && ModalHeader_module.noCloseButton, className), ...rest, children: [subtitle && (jsxRuntime.jsx(Paragraph.Paragraph, { size: 'small', variant: 'short', children: subtitle })), jsxRuntime.jsx(Heading.Heading, { level: 2, size: 'xsmall', children: children }), closeButton && (jsxRuntime.jsx(Button.Button, { name: 'close', variant: 'tertiary', color: 'second', size: 'medium', onClick: context?.closeModal, autoFocus: true, icon: true, className: ModalHeader_module.modalHeaderButton, children: jsxRuntime.jsx(akselIcons.XMarkIcon, { title: 'close modal', fontSize: '1.5em' }) }))] }));
|
|
19
19
|
});
|
|
20
20
|
ModalHeader.displayName = 'ModalHeader';
|
|
21
21
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var classes = {"modalHeader":"fds-modalheader-modalHeader-47e4ee5b","noCloseButton":"fds-modalheader-noCloseButton-47e4ee5b"};
|
|
4
|
+
var classes = {"modalHeader":"fds-modalheader-modalHeader-47e4ee5b","modalHeaderButton":"fds-modalheader-modalHeaderButton-47e4ee5b","noCloseButton":"fds-modalheader-noCloseButton-47e4ee5b"};
|
|
5
5
|
|
|
6
6
|
module.exports = classes;
|
|
@@ -23,14 +23,13 @@ var Box = require('../../Box/Box.js');
|
|
|
23
23
|
var Spinner = require('../../Spinner/Spinner.js');
|
|
24
24
|
var objectUtils = require('../../../utilities/objectUtils.js');
|
|
25
25
|
|
|
26
|
-
const ComboboxComponent = React.forwardRef(({ value, initialValue = [], onValueChange, label, hideLabel = false, description, multiple = false, size = 'medium', disabled = false, readOnly = false, hideChips = false,
|
|
26
|
+
const ComboboxComponent = React.forwardRef(({ value, initialValue = [], onValueChange, label, hideLabel = false, description, multiple = false, size = 'medium', disabled = false, readOnly = false, hideChips = false, 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) => {
|
|
27
27
|
const inputRef = React.useRef(null);
|
|
28
28
|
const portalRef = React.useRef(null);
|
|
29
29
|
const listRef = React.useRef([]);
|
|
30
30
|
const listId = React.useId();
|
|
31
31
|
const [inputValue, setInputValue] = React.useState(rest.inputValue || '');
|
|
32
|
-
|
|
33
|
-
const { selectedOptions, options, restChildren, interactiveChildren, optionValues, customIds, filteredOptionsChildren, filteredOptions, prevSelectedHash, setSelectedOptions, setPrevSelectedHash, } = useCombobox.default({
|
|
32
|
+
const { selectedOptions, options, restChildren, interactiveChildren, customIds, filteredOptionsChildren, filteredOptions, setSelectedOptions, } = useCombobox.default({
|
|
34
33
|
children,
|
|
35
34
|
inputValue,
|
|
36
35
|
filter,
|
|
@@ -51,20 +50,11 @@ const ComboboxComponent = React.forwardRef(({ value, initialValue = [], onValueC
|
|
|
51
50
|
}, 'combobox');
|
|
52
51
|
// if value is set, set input value to the label of the value
|
|
53
52
|
React.useEffect(() => {
|
|
54
|
-
if (value && value.length
|
|
53
|
+
if (value && value.length > 0 && !multiple) {
|
|
55
54
|
const option = options[value[0]];
|
|
56
55
|
setInputValue(option?.label || '');
|
|
57
56
|
}
|
|
58
57
|
}, [multiple, value, options]);
|
|
59
|
-
// Send new value if option was clicked
|
|
60
|
-
React.useEffect(() => {
|
|
61
|
-
const selectedHash = JSON.stringify(selectedOptions);
|
|
62
|
-
if (prevSelectedHash === selectedHash)
|
|
63
|
-
return;
|
|
64
|
-
const values = Object.keys(selectedOptions);
|
|
65
|
-
onValueChange?.(values);
|
|
66
|
-
setPrevSelectedHash(selectedHash);
|
|
67
|
-
}, [onValueChange, selectedOptions, prevSelectedHash, setPrevSelectedHash]);
|
|
68
58
|
React.useEffect(() => {
|
|
69
59
|
if (value && Object.keys(options).length >= 0) {
|
|
70
60
|
const updatedSelectedOptions = value.map((option) => {
|
|
@@ -76,38 +66,47 @@ const ComboboxComponent = React.forwardRef(({ value, initialValue = [], onValueC
|
|
|
76
66
|
return acc;
|
|
77
67
|
}, {}));
|
|
78
68
|
}
|
|
79
|
-
}, [multiple,
|
|
69
|
+
}, [multiple, value, options, setSelectedOptions]);
|
|
80
70
|
// handle click on option, either select or deselect - Handles single or multiple
|
|
81
|
-
const handleSelectOption = (
|
|
82
|
-
|
|
83
|
-
if (
|
|
84
|
-
setSelectedOptions(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return updated;
|
|
88
|
-
});
|
|
71
|
+
const handleSelectOption = (args) => {
|
|
72
|
+
const { option, clear, remove } = args;
|
|
73
|
+
if (clear) {
|
|
74
|
+
setSelectedOptions({});
|
|
75
|
+
setInputValue('');
|
|
76
|
+
onValueChange?.([]);
|
|
89
77
|
return;
|
|
90
78
|
}
|
|
79
|
+
if (!option)
|
|
80
|
+
return;
|
|
81
|
+
if (remove) {
|
|
82
|
+
const newSelectedOptions = { ...selectedOptions };
|
|
83
|
+
delete newSelectedOptions[option.value];
|
|
84
|
+
setSelectedOptions(newSelectedOptions);
|
|
85
|
+
onValueChange?.(Object.keys(newSelectedOptions));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const newSelectedOptions = { ...selectedOptions };
|
|
91
89
|
if (multiple) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
90
|
+
if (newSelectedOptions[option.value]) {
|
|
91
|
+
delete newSelectedOptions[option.value];
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
newSelectedOptions[option.value] = option;
|
|
95
|
+
}
|
|
98
96
|
setInputValue('');
|
|
99
97
|
inputRef.current?.focus();
|
|
100
98
|
}
|
|
101
99
|
else {
|
|
102
|
-
|
|
103
|
-
[option.value]: option,
|
|
104
|
-
});
|
|
100
|
+
newSelectedOptions[option.value] = option;
|
|
105
101
|
setInputValue(option?.label || '');
|
|
106
102
|
// move cursor to the end of the input
|
|
107
103
|
setTimeout(() => {
|
|
108
104
|
inputRef.current?.setSelectionRange(option?.label?.length || 0, option?.label?.length || 0);
|
|
109
105
|
}, 0);
|
|
110
106
|
}
|
|
107
|
+
setSelectedOptions(newSelectedOptions);
|
|
108
|
+
console.log('calling new value with: ', Object.keys(newSelectedOptions));
|
|
109
|
+
onValueChange?.(Object.keys(newSelectedOptions));
|
|
111
110
|
!multiple && setOpen(false);
|
|
112
111
|
refs.domReference.current?.focus();
|
|
113
112
|
};
|
|
@@ -124,7 +123,6 @@ const ComboboxComponent = React.forwardRef(({ value, initialValue = [], onValueC
|
|
|
124
123
|
interactiveChildren,
|
|
125
124
|
setOpen,
|
|
126
125
|
setInputValue,
|
|
127
|
-
setSelectedOptions,
|
|
128
126
|
handleSelectOption: debouncedHandleSelectOption,
|
|
129
127
|
});
|
|
130
128
|
const rowVirtualizer = index.useVirtualizer({
|
|
@@ -147,23 +145,15 @@ const ComboboxComponent = React.forwardRef(({ value, initialValue = [], onValueC
|
|
|
147
145
|
inputRef,
|
|
148
146
|
refs,
|
|
149
147
|
inputValue,
|
|
150
|
-
error,
|
|
151
148
|
formFieldProps,
|
|
152
|
-
name,
|
|
153
149
|
htmlSize,
|
|
154
|
-
|
|
155
|
-
hideChips,
|
|
156
|
-
clearButtonLabel: cleanButtonLabel || clearButtonLabel,
|
|
157
|
-
hideClearButton,
|
|
158
|
-
listId,
|
|
150
|
+
clearButtonLabel,
|
|
159
151
|
customIds,
|
|
160
152
|
filteredOptions,
|
|
161
153
|
setInputValue,
|
|
162
|
-
handleKeyDown,
|
|
163
154
|
setOpen,
|
|
164
155
|
getReferenceProps,
|
|
165
156
|
getItemProps,
|
|
166
|
-
setSelectedOptions,
|
|
167
157
|
/* Recieves the value of the option, and searches for it in our values lookup */
|
|
168
158
|
onOptionClick: (value) => {
|
|
169
159
|
if (readOnly)
|
|
@@ -171,13 +161,13 @@ const ComboboxComponent = React.forwardRef(({ value, initialValue = [], onValueC
|
|
|
171
161
|
if (disabled)
|
|
172
162
|
return;
|
|
173
163
|
const option = options[value];
|
|
174
|
-
debouncedHandleSelectOption(option);
|
|
164
|
+
debouncedHandleSelectOption({ option: option });
|
|
175
165
|
},
|
|
176
166
|
handleSelectOption: debouncedHandleSelectOption,
|
|
177
167
|
chipSrLabel,
|
|
178
168
|
listRef,
|
|
179
169
|
forwareddRef,
|
|
180
|
-
}, children: [jsxRuntime.jsxs(Box.Box, { className: clsx.clsx(Combobox_module.combobox, disabled && Combobox_module.disabled, className), style: style, ref: portalRef, children: [name && (jsxRuntime.jsx(ComboboxNative.default, { name: name, selectedOptions: selectedOptions, multiple: multiple })), jsxRuntime.jsx(ComboboxLabel.default, { label: label, description: description, size: size, readOnly: readOnly, hideLabel: hideLabel, formFieldProps: formFieldProps }), jsxRuntime.jsx(ComboboxInput.default, { ...objectUtils.omit(['inputValue'], rest), "aria-busy": loading }), jsxRuntime.jsx(ComboboxError.default, { size: size, error: error, formFieldProps: formFieldProps })] }), open && (jsxRuntime.jsx(floatingUi_react.FloatingPortal, { root: portal ? null : portalRef, children: jsxRuntime.jsx(floatingUi_react.FloatingFocusManager, { context: context, initialFocus: -1, visuallyHiddenDismiss: true, children: jsxRuntime.jsxs(Box.Box, { id: listId, shadow: 'medium', borderRadius: 'medium', borderColor: 'default', "aria-labelledby": formFieldProps.inputProps.id, "aria-autocomplete": 'list', tabIndex: -1, ...getFloatingProps({
|
|
170
|
+
}, children: [jsxRuntime.jsxs(Box.Box, { className: clsx.clsx(Combobox_module.combobox, disabled && Combobox_module.disabled, className), style: style, ref: portalRef, children: [name && (jsxRuntime.jsx(ComboboxNative.default, { name: name, selectedOptions: selectedOptions, multiple: multiple })), jsxRuntime.jsx(ComboboxLabel.default, { label: label, description: description, size: size, readOnly: readOnly, hideLabel: hideLabel, formFieldProps: formFieldProps }), jsxRuntime.jsx(ComboboxInput.default, { ...objectUtils.omit(['inputValue'], rest), hideClearButton: hideClearButton, listId: listId, error: error, hideChips: hideChips, handleKeyDown: handleKeyDown, "aria-busy": loading }), jsxRuntime.jsx(ComboboxError.default, { size: size, error: error, formFieldProps: formFieldProps })] }), open && (jsxRuntime.jsx(floatingUi_react.FloatingPortal, { root: portal ? null : portalRef, children: jsxRuntime.jsx(floatingUi_react.FloatingFocusManager, { context: context, initialFocus: -1, visuallyHiddenDismiss: true, children: jsxRuntime.jsxs(Box.Box, { id: listId, shadow: 'medium', borderRadius: 'medium', borderColor: 'default', "aria-labelledby": formFieldProps.inputProps.id, "aria-autocomplete": 'list', tabIndex: -1, ...getFloatingProps({
|
|
181
171
|
ref: refs.setFloating,
|
|
182
172
|
style: {
|
|
183
173
|
...floatingStyles,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var classes = {"combobox":"fds-combobox-combobox-249a725c","optionsWrapper":"fds-combobox-optionsWrapper-249a725c","readOnly":"fds-combobox-readOnly-249a725c","inputWrapper":"fds-combobox-inputWrapper-249a725c","small":"fds-combobox-small-249a725c","medium":"fds-combobox-medium-249a725c","large":"fds-combobox-large-249a725c","error":"fds-combobox-error-249a725c","chipAndInput":"fds-combobox-chipAndInput-249a725c","chips":"fds-combobox-chips-249a725c","arrow":"fds-combobox-arrow-249a725c","readonly":"fds-combobox-readonly-249a725c","label":"fds-combobox-label-249a725c","description":"fds-combobox-description-249a725c","clearButton":"fds-combobox-clearButton-249a725c","disabled":"fds-combobox-disabled-249a725c","padlock":"fds-combobox-padlock-249a725c","errorMessage":"fds-combobox-errorMessage-249a725c","loading":"fds-combobox-loading-249a725c","
|
|
4
|
+
var classes = {"combobox":"fds-combobox-combobox-249a725c","optionsWrapper":"fds-combobox-optionsWrapper-249a725c","readOnly":"fds-combobox-readOnly-249a725c","inputWrapper":"fds-combobox-inputWrapper-249a725c","small":"fds-combobox-small-249a725c","medium":"fds-combobox-medium-249a725c","large":"fds-combobox-large-249a725c","error":"fds-combobox-error-249a725c","chipAndInput":"fds-combobox-chipAndInput-249a725c","chips":"fds-combobox-chips-249a725c","arrow":"fds-combobox-arrow-249a725c","readonly":"fds-combobox-readonly-249a725c","label":"fds-combobox-label-249a725c","description":"fds-combobox-description-249a725c","clearButton":"fds-combobox-clearButton-249a725c","disabled":"fds-combobox-disabled-249a725c","padlock":"fds-combobox-padlock-249a725c","errorMessage":"fds-combobox-errorMessage-249a725c","loading":"fds-combobox-loading-249a725c","showChecked":"fds-combobox-showChecked-249a725c"};
|
|
5
5
|
|
|
6
6
|
module.exports = classes;
|
|
@@ -14,7 +14,7 @@ const ComboboxChips = () => {
|
|
|
14
14
|
if (!context) {
|
|
15
15
|
throw new Error('ComboboxContext is missing');
|
|
16
16
|
}
|
|
17
|
-
const { size, readOnly, disabled, selectedOptions,
|
|
17
|
+
const { size, readOnly, disabled, selectedOptions, chipSrLabel, handleSelectOption, inputRef, } = context;
|
|
18
18
|
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: Object.keys(selectedOptions).map((value) => {
|
|
19
19
|
return (jsxRuntime.jsx(Removable.RemovableChip, { size: size, disabled: disabled, onKeyDown: (e) => {
|
|
20
20
|
if (readOnly)
|
|
@@ -23,10 +23,9 @@ const ComboboxChips = () => {
|
|
|
23
23
|
return;
|
|
24
24
|
if (e.key === 'Enter') {
|
|
25
25
|
e.stopPropagation();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return rest;
|
|
26
|
+
handleSelectOption({
|
|
27
|
+
option: selectedOptions[value],
|
|
28
|
+
remove: true,
|
|
30
29
|
});
|
|
31
30
|
inputRef.current?.focus();
|
|
32
31
|
}
|
|
@@ -36,14 +35,10 @@ const ComboboxChips = () => {
|
|
|
36
35
|
if (disabled)
|
|
37
36
|
return;
|
|
38
37
|
/* If we click a chip, filter the active values and remove the one we clicked */
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return rest;
|
|
38
|
+
handleSelectOption({
|
|
39
|
+
option: selectedOptions[value],
|
|
40
|
+
remove: true,
|
|
43
41
|
});
|
|
44
|
-
}, style: {
|
|
45
|
-
/* We already set the opacity on Combobox */
|
|
46
|
-
opacity: 1,
|
|
47
42
|
}, "aria-label": chipSrLabel(selectedOptions[value]), children: selectedOptions[value].label }, value));
|
|
48
43
|
}) }));
|
|
49
44
|
};
|
|
@@ -15,14 +15,13 @@ const ComboboxClearButton = () => {
|
|
|
15
15
|
if (!context) {
|
|
16
16
|
throw new Error('ComboboxContext is missing');
|
|
17
17
|
}
|
|
18
|
-
const { size, readOnly, disabled, clearButtonLabel,
|
|
18
|
+
const { size, readOnly, disabled, clearButtonLabel, handleSelectOption } = context;
|
|
19
19
|
return (jsxRuntime.jsx("button", { disabled: disabled, className: clsx.clsx(Combobox_module.clearButton, Combobox_module[size], `fds-focus`), onClick: () => {
|
|
20
20
|
if (readOnly)
|
|
21
21
|
return;
|
|
22
22
|
if (disabled)
|
|
23
23
|
return;
|
|
24
|
-
|
|
25
|
-
setInputValue('');
|
|
24
|
+
handleSelectOption({ option: null, clear: true });
|
|
26
25
|
}, onKeyDown: (e) => {
|
|
27
26
|
if (readOnly)
|
|
28
27
|
return;
|
|
@@ -30,9 +29,7 @@ const ComboboxClearButton = () => {
|
|
|
30
29
|
return;
|
|
31
30
|
if (e.key === 'Enter') {
|
|
32
31
|
e.stopPropagation();
|
|
33
|
-
|
|
34
|
-
setInputValue('');
|
|
35
|
-
inputRef.current?.focus();
|
|
32
|
+
handleSelectOption({ option: null, clear: true });
|
|
36
33
|
}
|
|
37
34
|
}, type: 'button', "aria-label": clearButtonLabel, children: jsxRuntime.jsx(akselIcons.XMarkIcon, { fontSize: '1.5em', title: 'Clear selection' }) }));
|
|
38
35
|
};
|
|
@@ -17,7 +17,7 @@ var ComboboxClearButton = require('./ComboboxClearButton.js');
|
|
|
17
17
|
var Box = require('../../../Box/Box.js');
|
|
18
18
|
var objectUtils = require('../../../../utilities/objectUtils.js');
|
|
19
19
|
|
|
20
|
-
const ComboboxInput = ({ ...rest }) => {
|
|
20
|
+
const ComboboxInput = ({ hideClearButton, listId, error, hideChips, handleKeyDown, ...rest }) => {
|
|
21
21
|
const context = React.useContext(ComboboxContext.ComboboxContext);
|
|
22
22
|
const idDispatch = ComboboxIdContext.useComboboxIdDispatch();
|
|
23
23
|
if (!context) {
|
|
@@ -26,52 +26,20 @@ const ComboboxInput = ({ ...rest }) => {
|
|
|
26
26
|
const setActiveIndex = (id) => {
|
|
27
27
|
idDispatch?.({ type: 'SET_ACTIVE_INDEX', payload: id });
|
|
28
28
|
};
|
|
29
|
-
const { forwareddRef,
|
|
29
|
+
const { forwareddRef, size, readOnly, disabled, open, inputRef, refs, inputValue, multiple, selectedOptions, formFieldProps, htmlSize, options, setOpen, getReferenceProps, setInputValue, handleSelectOption, } = context;
|
|
30
30
|
const mergedRefs = floatingUi_react.useMergeRefs([forwareddRef, inputRef]);
|
|
31
|
-
// we need to check if input is in focus, to add focus styles to the wrapper
|
|
32
|
-
const [inputInFocus, setInputInFocus] = React.useState(false);
|
|
33
|
-
React.useEffect(() => {
|
|
34
|
-
const input = inputRef.current;
|
|
35
|
-
const onFocus = () => {
|
|
36
|
-
setInputInFocus(true);
|
|
37
|
-
};
|
|
38
|
-
const onBlur = () => {
|
|
39
|
-
setInputInFocus(false);
|
|
40
|
-
};
|
|
41
|
-
input?.addEventListener('focus', onFocus);
|
|
42
|
-
input?.addEventListener('blur', onBlur);
|
|
43
|
-
return () => {
|
|
44
|
-
input?.removeEventListener('focus', onFocus);
|
|
45
|
-
input?.removeEventListener('blur', onBlur);
|
|
46
|
-
};
|
|
47
|
-
}, [inputRef]);
|
|
48
31
|
// onChange function for the input
|
|
49
32
|
const onChange = (event) => {
|
|
50
33
|
const value = event.target.value;
|
|
51
34
|
setInputValue(value);
|
|
52
35
|
setActiveIndex(0);
|
|
53
|
-
if (typeof value === 'string') {
|
|
54
|
-
setOpen(true);
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
setOpen(false);
|
|
58
|
-
}
|
|
59
36
|
// check if input value is the same as a label, if so, select it
|
|
60
|
-
const option = options[value];
|
|
37
|
+
const option = options[value.toLowerCase()];
|
|
61
38
|
if (!option)
|
|
62
39
|
return;
|
|
63
40
|
if (selectedOptions[option.value])
|
|
64
41
|
return;
|
|
65
|
-
handleSelectOption(option);
|
|
66
|
-
if (multiple) {
|
|
67
|
-
inputRef.current?.focus();
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
// move cursor to the end of the input
|
|
71
|
-
setTimeout(() => {
|
|
72
|
-
inputRef.current?.setSelectionRange(option?.label?.length || 0, option?.label?.length || 0);
|
|
73
|
-
}, 0);
|
|
74
|
-
}
|
|
42
|
+
handleSelectOption({ option: option });
|
|
75
43
|
};
|
|
76
44
|
const showClearButton = multiple && !hideClearButton && Object.keys(selectedOptions).length > 0;
|
|
77
45
|
/* Props from floating-ui */
|
|
@@ -92,9 +60,7 @@ const ComboboxInput = ({ ...rest }) => {
|
|
|
92
60
|
inputRef.current?.focus();
|
|
93
61
|
},
|
|
94
62
|
/* Handles list navigation */
|
|
95
|
-
onKeyDown
|
|
96
|
-
handleKeyDown(event);
|
|
97
|
-
},
|
|
63
|
+
onKeyDown: handleKeyDown,
|
|
98
64
|
// preventDefault on keydown to avoid sending in form
|
|
99
65
|
onKeyPress(event) {
|
|
100
66
|
if (event.key === 'Enter') {
|
|
@@ -102,7 +68,7 @@ const ComboboxInput = ({ ...rest }) => {
|
|
|
102
68
|
}
|
|
103
69
|
},
|
|
104
70
|
});
|
|
105
|
-
return (jsxRuntime.jsxs(Box.Box, { ...props, "aria-disabled": disabled, className: clsx.clsx(Textfield_module.input, Combobox_module.inputWrapper, Combobox_module[size],
|
|
71
|
+
return (jsxRuntime.jsxs(Box.Box, { ...props, "aria-disabled": disabled, className: clsx.clsx(Textfield_module.input, Combobox_module.inputWrapper, Combobox_module[size], readOnly && Combobox_module.readonly, error && Combobox_module.error), children: [jsxRuntime.jsxs("div", { className: Combobox_module.chipAndInput, children: [multiple && !hideChips && jsxRuntime.jsx(ComboboxChips.default, {}), jsxRuntime.jsx("input", { ref: mergedRefs, "aria-activedescendant": props['aria-activedescendant'], readOnly: readOnly, "aria-autocomplete": 'list', role: 'combobox', "aria-expanded": open, "aria-controls": listId, autoComplete: 'off', size: htmlSize, value: inputValue, ...objectUtils.omit(['style', 'className'], rest), ...formFieldProps.inputProps, onChange: (e) => {
|
|
106
72
|
onChange(e);
|
|
107
73
|
rest.onChange && rest.onChange(e);
|
|
108
74
|
} })] }), showClearButton && jsxRuntime.jsx(ComboboxClearButton.default, {}), jsxRuntime.jsx("div", { className: Combobox_module.arrow, children: open ? (jsxRuntime.jsx(akselIcons.ChevronUpIcon, { title: 'arrow up', fontSize: '1.5em' })) : (jsxRuntime.jsx(akselIcons.ChevronDownIcon, { title: 'arrow down', fontSize: '1.5em' })) })] }));
|
|
@@ -20,35 +20,59 @@ function isInteractiveComboboxCustom(child) {
|
|
|
20
20
|
function useCombobox({ children, inputValue, multiple, filter = (inputValue, option) => {
|
|
21
21
|
return option.label.toLowerCase().startsWith(inputValue.toLowerCase());
|
|
22
22
|
}, initialValue, }) {
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
23
|
+
const { optionsChildren, customIds, restChildren, interactiveChildren } = React.useMemo(() => {
|
|
24
|
+
const allChildren = React.Children.toArray(children);
|
|
25
|
+
const result = allChildren.reduce((acc, child) => {
|
|
26
26
|
if (isComboboxOption(child)) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
label = childrenLabel;
|
|
27
|
+
acc.optionsChildren.push(child);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
acc.restChildren.push(child);
|
|
31
|
+
if (isInteractiveComboboxCustom(child)) {
|
|
32
|
+
const childElement = child;
|
|
33
|
+
acc.interactiveChildren.push(childElement);
|
|
34
|
+
if (!childElement.props.id) {
|
|
35
|
+
throw new Error('If ComboboxCustom is interactive, it must have an id');
|
|
36
|
+
}
|
|
37
|
+
acc.customIds.push(childElement.props.id);
|
|
41
38
|
}
|
|
42
|
-
allOptions[props.value] = {
|
|
43
|
-
value: props.value,
|
|
44
|
-
label,
|
|
45
|
-
displayValue: props.displayValue,
|
|
46
|
-
description: props.description,
|
|
47
|
-
};
|
|
48
39
|
}
|
|
40
|
+
return acc;
|
|
41
|
+
}, {
|
|
42
|
+
optionsChildren: [],
|
|
43
|
+
customIds: [],
|
|
44
|
+
restChildren: [],
|
|
45
|
+
interactiveChildren: [],
|
|
49
46
|
});
|
|
50
|
-
return
|
|
47
|
+
return result;
|
|
51
48
|
}, [children]);
|
|
49
|
+
const options = React.useMemo(() => {
|
|
50
|
+
const allOptions = {};
|
|
51
|
+
optionsChildren.map((child) => {
|
|
52
|
+
const props = child.props;
|
|
53
|
+
let label = props.displayValue || '';
|
|
54
|
+
if (!props.displayValue) {
|
|
55
|
+
let childrenLabel = '';
|
|
56
|
+
// go over children and find all strings
|
|
57
|
+
React.Children.forEach(props.children, (child) => {
|
|
58
|
+
if (typeof child === 'string') {
|
|
59
|
+
childrenLabel += child;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
throw new Error('If ComboboxOption is not a string, it must have a displayValue prop');
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
label = childrenLabel;
|
|
66
|
+
}
|
|
67
|
+
allOptions[props.value] = {
|
|
68
|
+
value: props.value,
|
|
69
|
+
label,
|
|
70
|
+
displayValue: props.displayValue,
|
|
71
|
+
description: props.description,
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
return allOptions;
|
|
75
|
+
}, [optionsChildren]);
|
|
52
76
|
const preSelectedOptions = React.useMemo(() => (initialValue || []).reduce((acc, value) => {
|
|
53
77
|
const option = options[value];
|
|
54
78
|
if (isOption(option)) {
|
|
@@ -57,22 +81,6 @@ function useCombobox({ children, inputValue, multiple, filter = (inputValue, opt
|
|
|
57
81
|
return acc;
|
|
58
82
|
}, {}), [initialValue, options]);
|
|
59
83
|
const [selectedOptions, setSelectedOptions] = React.useState(preSelectedOptions);
|
|
60
|
-
const [prevSelectedHash, setPrevSelectedHash] = React.useState(JSON.stringify(selectedOptions));
|
|
61
|
-
const { optionsChildren, customIds } = React.useMemo(() => {
|
|
62
|
-
const allChildren = React.Children.toArray(children);
|
|
63
|
-
const optionsChildren = allChildren.filter((child) => isComboboxOption(child));
|
|
64
|
-
// find all custom components with `interactive=true` and generate random values for them
|
|
65
|
-
const customChildren = allChildren.filter((child) => {
|
|
66
|
-
return isInteractiveComboboxCustom(child);
|
|
67
|
-
});
|
|
68
|
-
// return all ids
|
|
69
|
-
const customIds = customChildren.map((child) => {
|
|
70
|
-
if (!child.props.id)
|
|
71
|
-
throw new Error('If ComboboxCustom is interactive, it must have an id');
|
|
72
|
-
return child.props.id;
|
|
73
|
-
});
|
|
74
|
-
return { optionsChildren, customIds };
|
|
75
|
-
}, [children]);
|
|
76
84
|
const { filteredOptions, filteredOptionsChildren } = React.useMemo(() => {
|
|
77
85
|
const filteredOptions = [];
|
|
78
86
|
const filteredOptionsChildren = Object.keys(options)
|
|
@@ -90,35 +98,15 @@ function useCombobox({ children, inputValue, multiple, filter = (inputValue, opt
|
|
|
90
98
|
return { filteredOptions, filteredOptionsChildren };
|
|
91
99
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
92
100
|
}, [inputValue, multiple, options, optionsChildren, selectedOptions]);
|
|
93
|
-
const optionValues = React.useMemo(() => {
|
|
94
|
-
// create an index map of values from optionsChildren
|
|
95
|
-
const options = optionsChildren.map((child) => {
|
|
96
|
-
const { value } = child.props;
|
|
97
|
-
return value;
|
|
98
|
-
});
|
|
99
|
-
return [...customIds, ...options];
|
|
100
|
-
}, [customIds, optionsChildren]);
|
|
101
|
-
const { restChildren, interactiveChildren } = React.useMemo(() => {
|
|
102
|
-
const restChildren = React.Children.toArray(children).filter((child) => {
|
|
103
|
-
return !isComboboxOption(child);
|
|
104
|
-
});
|
|
105
|
-
const interactiveChildren = restChildren.filter((child) => {
|
|
106
|
-
return isInteractiveComboboxCustom(child);
|
|
107
|
-
});
|
|
108
|
-
return { restChildren, interactiveChildren };
|
|
109
|
-
}, [children]);
|
|
110
101
|
return {
|
|
111
102
|
filteredOptionsChildren,
|
|
112
103
|
filteredOptions,
|
|
113
|
-
optionValues,
|
|
114
104
|
restChildren,
|
|
115
105
|
options,
|
|
116
106
|
customIds,
|
|
117
107
|
selectedOptions,
|
|
118
|
-
prevSelectedHash,
|
|
119
108
|
interactiveChildren,
|
|
120
109
|
setSelectedOptions,
|
|
121
|
-
setPrevSelectedHash,
|
|
122
110
|
};
|
|
123
111
|
}
|
|
124
112
|
|