@simplybusiness/mobius 5.5.0 → 5.6.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/CHANGELOG.md +12 -0
- package/dist/cjs/components/Combobox/Combobox.js +56 -33
- package/dist/cjs/components/Combobox/Combobox.js.map +1 -1
- package/dist/cjs/components/Combobox/Listbox.js +58 -0
- package/dist/cjs/components/Combobox/Listbox.js.map +1 -0
- package/dist/cjs/components/Combobox/Option.js +44 -0
- package/dist/cjs/components/Combobox/Option.js.map +1 -0
- package/dist/cjs/components/Combobox/fixtures.js +115 -0
- package/dist/cjs/components/Combobox/fixtures.js.map +1 -1
- package/dist/cjs/components/Combobox/useComboboxHighlight.js +86 -0
- package/dist/cjs/components/Combobox/useComboboxHighlight.js.map +1 -0
- package/dist/cjs/components/Combobox/utils.js +46 -0
- package/dist/cjs/components/Combobox/utils.js.map +1 -0
- package/dist/cjs/components/TextArea/TextArea.js +4 -4
- package/dist/cjs/components/TextArea/TextArea.js.map +1 -1
- package/dist/cjs/components/TextAreaInput/TextAreaInput.js +6 -3
- package/dist/cjs/components/TextAreaInput/TextAreaInput.js.map +1 -1
- package/dist/cjs/components/TextField/TextField.js +4 -3
- package/dist/cjs/components/TextField/TextField.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/components/Combobox/Combobox.js +55 -32
- package/dist/esm/components/Combobox/Combobox.js.map +1 -1
- package/dist/esm/components/Combobox/Listbox.js +43 -0
- package/dist/esm/components/Combobox/Listbox.js.map +1 -0
- package/dist/esm/components/Combobox/Option.js +29 -0
- package/dist/esm/components/Combobox/Option.js.map +1 -0
- package/dist/esm/components/Combobox/fixtures.js +109 -0
- package/dist/esm/components/Combobox/fixtures.js.map +1 -1
- package/dist/esm/components/Combobox/types.js.map +1 -1
- package/dist/esm/components/Combobox/useComboboxHighlight.js +76 -0
- package/dist/esm/components/Combobox/useComboboxHighlight.js.map +1 -0
- package/dist/esm/components/Combobox/utils.js +20 -0
- package/dist/esm/components/Combobox/utils.js.map +1 -0
- package/dist/esm/components/TextArea/TextArea.js +4 -4
- package/dist/esm/components/TextArea/TextArea.js.map +1 -1
- package/dist/esm/components/TextAreaInput/TextAreaInput.js +6 -3
- package/dist/esm/components/TextAreaInput/TextAreaInput.js.map +1 -1
- package/dist/esm/components/TextField/TextField.js +4 -3
- package/dist/esm/components/TextField/TextField.js.map +1 -1
- package/dist/types/components/Combobox/Combobox.d.ts +1 -1
- package/dist/types/components/Combobox/Combobox.stories.d.ts +4 -1
- package/dist/types/components/Combobox/Listbox.d.ts +10 -0
- package/dist/types/components/Combobox/Option.d.ts +2 -0
- package/dist/types/components/Combobox/fixtures.d.ts +5 -0
- package/dist/types/components/Combobox/types.d.ts +17 -2
- package/dist/types/components/Combobox/useComboboxHighlight.d.ts +10 -0
- package/dist/types/components/Combobox/useComboboxHighlight.test.d.ts +1 -0
- package/dist/types/components/Combobox/utils.d.ts +6 -0
- package/dist/types/components/Combobox/utils.test.d.ts +1 -0
- package/dist/types/components/TextArea/TextArea.d.ts +2 -2
- package/dist/types/components/TextAreaInput/TextAreaInput.d.ts +3 -1
- package/package.json +1 -1
- package/src/components/Combobox/Combobox.css +51 -4
- package/src/components/Combobox/Combobox.mdx +147 -0
- package/src/components/Combobox/Combobox.stories.tsx +47 -2
- package/src/components/Combobox/Combobox.test.tsx +535 -316
- package/src/components/Combobox/Combobox.tsx +78 -58
- package/src/components/Combobox/Listbox.tsx +74 -0
- package/src/components/Combobox/Option.tsx +41 -0
- package/src/components/Combobox/fixtures.tsx +111 -0
- package/src/components/Combobox/types.tsx +22 -4
- package/src/components/Combobox/useComboboxHighlight.test.tsx +242 -0
- package/src/components/Combobox/useComboboxHighlight.tsx +88 -0
- package/src/components/Combobox/utils.test.tsx +120 -0
- package/src/components/Combobox/utils.tsx +50 -0
- package/src/components/TextArea/TextArea.tsx +6 -6
- package/src/components/TextAreaInput/TextAreaInput.tsx +16 -4
- package/src/components/TextField/TextField.test.tsx +8 -0
- package/src/components/TextField/TextField.tsx +3 -1
|
@@ -1,33 +1,42 @@
|
|
|
1
|
-
import { forwardRef, useId, useRef, useState, useEffect } from "react";
|
|
2
1
|
import classNames from "classnames/dedupe";
|
|
2
|
+
import { forwardRef, useEffect, useId, useRef, useState } from "react";
|
|
3
|
+
import type { ForwardedRefComponent } from "../../types";
|
|
3
4
|
import { TextField } from "../TextField";
|
|
5
|
+
import { Listbox } from "./Listbox"; // Import Listbox component
|
|
4
6
|
import type {
|
|
5
|
-
ComboboxProps,
|
|
6
7
|
ComboboxElementType,
|
|
7
|
-
ComboboxRef,
|
|
8
8
|
ComboboxOption,
|
|
9
|
+
ComboboxOptions,
|
|
10
|
+
ComboboxProps,
|
|
11
|
+
ComboboxRef,
|
|
9
12
|
} from "./types";
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
const getOptionValue = (option: ComboboxOption) =>
|
|
13
|
-
typeof option === "string" ? option : option.value;
|
|
14
|
-
|
|
15
|
-
const getOptionLabel = (option: ComboboxOption) =>
|
|
16
|
-
typeof option === "string" ? option : option.label;
|
|
13
|
+
import { useComboboxHighlight } from "./useComboboxHighlight";
|
|
14
|
+
import { filterOptions, getOptionValue, isOptionGroup } from "./utils";
|
|
17
15
|
|
|
18
16
|
export const Combobox: ForwardedRefComponent<
|
|
19
17
|
ComboboxProps,
|
|
20
18
|
ComboboxElementType
|
|
21
19
|
> = forwardRef((props: ComboboxProps, ref: ComboboxRef) => {
|
|
22
|
-
const { defaultValue, options, onSelected } =
|
|
20
|
+
const { defaultValue, options, onSelected, className, placeholder, icon } =
|
|
21
|
+
props;
|
|
23
22
|
|
|
24
|
-
const fallbackRef = useRef();
|
|
23
|
+
const fallbackRef = useRef<HTMLInputElement>(null);
|
|
25
24
|
const [inputValue, setInputValue] = useState(defaultValue || "");
|
|
26
25
|
const [isOpen, setIsOpen] = useState(false);
|
|
27
|
-
const [
|
|
28
|
-
const
|
|
26
|
+
const [filteredOptions, setFilteredOptions] = useState<ComboboxOptions>([]);
|
|
27
|
+
const {
|
|
28
|
+
highlightedIndex,
|
|
29
|
+
highlightedGroupIndex,
|
|
30
|
+
highlightNextOption,
|
|
31
|
+
highlightPreviousOption,
|
|
32
|
+
highlightFirstOption,
|
|
33
|
+
highlightLastOption,
|
|
34
|
+
clearHighlight,
|
|
35
|
+
} = useComboboxHighlight(filteredOptions);
|
|
36
|
+
|
|
29
37
|
const inputRef = ref || fallbackRef;
|
|
30
38
|
const listboxId = useId();
|
|
39
|
+
const blurTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
31
40
|
|
|
32
41
|
useEffect(() => {
|
|
33
42
|
const fetchOptions = async () => {
|
|
@@ -35,13 +44,7 @@ export const Combobox: ForwardedRefComponent<
|
|
|
35
44
|
const result = await options(inputValue);
|
|
36
45
|
setFilteredOptions(result);
|
|
37
46
|
} else {
|
|
38
|
-
setFilteredOptions(
|
|
39
|
-
options.filter(option =>
|
|
40
|
-
getOptionLabel(option)
|
|
41
|
-
.toLowerCase()
|
|
42
|
-
.includes(inputValue.toLowerCase()),
|
|
43
|
-
),
|
|
44
|
-
);
|
|
47
|
+
setFilteredOptions(filterOptions(options, inputValue));
|
|
45
48
|
}
|
|
46
49
|
};
|
|
47
50
|
|
|
@@ -49,75 +52,101 @@ export const Combobox: ForwardedRefComponent<
|
|
|
49
52
|
}, [inputValue, options]);
|
|
50
53
|
|
|
51
54
|
const handleFocus = () => {
|
|
55
|
+
if (blurTimeoutRef.current) {
|
|
56
|
+
clearTimeout(blurTimeoutRef.current);
|
|
57
|
+
blurTimeoutRef.current = null;
|
|
58
|
+
}
|
|
52
59
|
setIsOpen(true);
|
|
53
60
|
};
|
|
54
61
|
|
|
55
62
|
const handleBlur = () => {
|
|
56
|
-
|
|
63
|
+
blurTimeoutRef.current = setTimeout(() => {
|
|
64
|
+
setIsOpen(false);
|
|
65
|
+
}, 150);
|
|
57
66
|
};
|
|
58
67
|
|
|
59
68
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
60
69
|
const newValue = e.target.value;
|
|
61
70
|
setInputValue(newValue);
|
|
62
71
|
setIsOpen(true);
|
|
63
|
-
|
|
72
|
+
clearHighlight();
|
|
64
73
|
};
|
|
65
74
|
|
|
66
75
|
const handleOptionSelect = (option: ComboboxOption) => {
|
|
67
76
|
const value = getOptionValue(option);
|
|
77
|
+
if (!value) return;
|
|
68
78
|
setIsOpen(false);
|
|
69
79
|
setInputValue(value);
|
|
70
80
|
onSelected?.(value);
|
|
71
81
|
};
|
|
72
82
|
|
|
83
|
+
function getHighlightedOption() {
|
|
84
|
+
if (highlightedIndex === -1) return undefined;
|
|
85
|
+
|
|
86
|
+
if (isOptionGroup(filteredOptions)) {
|
|
87
|
+
const group = filteredOptions[highlightedGroupIndex];
|
|
88
|
+
return group?.options[highlightedIndex];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return filteredOptions[highlightedIndex];
|
|
92
|
+
}
|
|
93
|
+
|
|
73
94
|
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
74
95
|
switch (e.key) {
|
|
75
96
|
case "ArrowDown":
|
|
76
97
|
e.preventDefault();
|
|
77
98
|
setIsOpen(true);
|
|
78
|
-
|
|
79
|
-
prev < filteredOptions.length - 1 ? prev + 1 : 0,
|
|
80
|
-
);
|
|
99
|
+
highlightNextOption();
|
|
81
100
|
break;
|
|
82
101
|
case "ArrowUp":
|
|
83
102
|
e.preventDefault();
|
|
84
103
|
setIsOpen(true);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
104
|
+
highlightPreviousOption();
|
|
105
|
+
break;
|
|
106
|
+
case "Home":
|
|
107
|
+
e.preventDefault();
|
|
108
|
+
setIsOpen(true);
|
|
109
|
+
highlightFirstOption();
|
|
110
|
+
break;
|
|
111
|
+
case "End":
|
|
112
|
+
e.preventDefault();
|
|
113
|
+
setIsOpen(true);
|
|
114
|
+
highlightLastOption();
|
|
88
115
|
break;
|
|
89
116
|
case "Enter":
|
|
90
117
|
e.preventDefault();
|
|
91
|
-
if (isOpen
|
|
92
|
-
handleOptionSelect(
|
|
93
|
-
} else if (
|
|
94
|
-
isOpen &&
|
|
95
|
-
highlightedIndex === -1 &&
|
|
96
|
-
filteredOptions.length > 0
|
|
97
|
-
) {
|
|
98
|
-
handleOptionSelect(filteredOptions[0]);
|
|
118
|
+
if (isOpen) {
|
|
119
|
+
handleOptionSelect(getHighlightedOption()!);
|
|
99
120
|
}
|
|
100
121
|
break;
|
|
101
122
|
case "Escape":
|
|
102
123
|
e.preventDefault();
|
|
103
124
|
setIsOpen(false);
|
|
104
|
-
|
|
125
|
+
clearHighlight();
|
|
105
126
|
break;
|
|
106
127
|
default:
|
|
107
128
|
// Do nothing
|
|
108
129
|
}
|
|
109
130
|
};
|
|
110
131
|
|
|
132
|
+
const classes = classNames(
|
|
133
|
+
"mobius mobius-combobox",
|
|
134
|
+
{ expanded: isOpen },
|
|
135
|
+
className,
|
|
136
|
+
);
|
|
137
|
+
|
|
111
138
|
return (
|
|
112
|
-
<div className=
|
|
139
|
+
<div className={classes}>
|
|
113
140
|
<TextField
|
|
114
141
|
className="mobius-combobox__input"
|
|
115
142
|
role="combobox"
|
|
116
143
|
value={inputValue}
|
|
144
|
+
placeholder={placeholder}
|
|
117
145
|
onFocus={handleFocus}
|
|
118
146
|
onBlur={handleBlur}
|
|
119
147
|
onKeyDown={handleKeyDown}
|
|
120
148
|
onChange={handleInputChange}
|
|
149
|
+
autoComplete="off"
|
|
121
150
|
aria-autocomplete="list"
|
|
122
151
|
aria-haspopup="listbox"
|
|
123
152
|
aria-controls={listboxId}
|
|
@@ -125,29 +154,20 @@ export const Combobox: ForwardedRefComponent<
|
|
|
125
154
|
aria-activedescendant={
|
|
126
155
|
highlightedIndex === -1
|
|
127
156
|
? undefined
|
|
128
|
-
: `${listboxId}-option-${highlightedIndex}`
|
|
157
|
+
: `${listboxId}-option-${highlightedGroupIndex}-${highlightedIndex}`
|
|
129
158
|
}
|
|
130
|
-
|
|
159
|
+
prefixInside={icon}
|
|
131
160
|
ref={inputRef}
|
|
132
161
|
/>
|
|
133
162
|
{isOpen && (
|
|
134
|
-
<
|
|
135
|
-
{
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
className={classNames("mobius-combobox__option", {
|
|
143
|
-
"mobius-combobox__option--is-highlighted":
|
|
144
|
-
highlightedIndex === index,
|
|
145
|
-
})}
|
|
146
|
-
>
|
|
147
|
-
{getOptionLabel(option)}
|
|
148
|
-
</li>
|
|
149
|
-
))}
|
|
150
|
-
</ul>
|
|
163
|
+
<Listbox
|
|
164
|
+
id={listboxId}
|
|
165
|
+
options={filteredOptions}
|
|
166
|
+
highlightedIndex={highlightedIndex}
|
|
167
|
+
highlightedGroupIndex={highlightedGroupIndex}
|
|
168
|
+
onOptionSelect={handleOptionSelect}
|
|
169
|
+
expanded={isOpen}
|
|
170
|
+
/>
|
|
151
171
|
)}
|
|
152
172
|
</div>
|
|
153
173
|
);
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import classNames from "classnames";
|
|
2
|
+
import { Option } from "./Option";
|
|
3
|
+
import type { ComboboxOption, ComboboxOptions } from "./types";
|
|
4
|
+
import { isOptionGroup } from "./utils";
|
|
5
|
+
|
|
6
|
+
export type ListboxProps = {
|
|
7
|
+
id: string;
|
|
8
|
+
options: ComboboxOptions;
|
|
9
|
+
highlightedIndex: number;
|
|
10
|
+
highlightedGroupIndex: number;
|
|
11
|
+
onOptionSelect: (option: ComboboxOption) => void;
|
|
12
|
+
expanded?: boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const Listbox = ({
|
|
16
|
+
id,
|
|
17
|
+
options,
|
|
18
|
+
highlightedIndex,
|
|
19
|
+
highlightedGroupIndex,
|
|
20
|
+
onOptionSelect,
|
|
21
|
+
expanded = false,
|
|
22
|
+
}: ListboxProps) => {
|
|
23
|
+
const classes = classNames("mobius-combobox__list", {
|
|
24
|
+
expanded,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div role="listbox" id={id} className={classes}>
|
|
29
|
+
{isOptionGroup(options)
|
|
30
|
+
? options.map((option, groupIndex) => (
|
|
31
|
+
<ul
|
|
32
|
+
role="group"
|
|
33
|
+
key={option.heading}
|
|
34
|
+
aria-labelledby={`${id}-group-${groupIndex}`}
|
|
35
|
+
className="mobius-combobox__group"
|
|
36
|
+
>
|
|
37
|
+
<li
|
|
38
|
+
role="presentation"
|
|
39
|
+
id={`${id}-group-${groupIndex}`}
|
|
40
|
+
className="mobius-combobox__group-label"
|
|
41
|
+
>
|
|
42
|
+
{option.heading}
|
|
43
|
+
</li>
|
|
44
|
+
{option.options.map((groupOption, index) => (
|
|
45
|
+
<Option
|
|
46
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
47
|
+
key={`${id}-option-${groupIndex}-${index}`}
|
|
48
|
+
option={groupOption}
|
|
49
|
+
index={index}
|
|
50
|
+
groupIndex={groupIndex}
|
|
51
|
+
isHighlighted={
|
|
52
|
+
highlightedIndex === index &&
|
|
53
|
+
highlightedGroupIndex === groupIndex
|
|
54
|
+
}
|
|
55
|
+
onOptionSelect={onOptionSelect}
|
|
56
|
+
id={id}
|
|
57
|
+
/>
|
|
58
|
+
))}
|
|
59
|
+
</ul>
|
|
60
|
+
))
|
|
61
|
+
: options.map((option, index) => (
|
|
62
|
+
<Option
|
|
63
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
64
|
+
key={index}
|
|
65
|
+
option={option}
|
|
66
|
+
index={index}
|
|
67
|
+
isHighlighted={highlightedIndex === index}
|
|
68
|
+
onOptionSelect={onOptionSelect}
|
|
69
|
+
id={id}
|
|
70
|
+
/>
|
|
71
|
+
))}
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
import classNames from "classnames/dedupe";
|
|
3
|
+
import { getOptionValue, getOptionLabel } from "./utils";
|
|
4
|
+
import type { ComboboxOptionProps } from "./types";
|
|
5
|
+
|
|
6
|
+
export const Option = ({
|
|
7
|
+
option,
|
|
8
|
+
index,
|
|
9
|
+
groupIndex = 0,
|
|
10
|
+
isHighlighted,
|
|
11
|
+
onOptionSelect,
|
|
12
|
+
id,
|
|
13
|
+
}: ComboboxOptionProps) => {
|
|
14
|
+
const optionRef = useRef<HTMLLIElement>(null);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (
|
|
18
|
+
isHighlighted &&
|
|
19
|
+
optionRef.current &&
|
|
20
|
+
optionRef.current.scrollIntoView
|
|
21
|
+
) {
|
|
22
|
+
optionRef.current.scrollIntoView({ block: "nearest" });
|
|
23
|
+
}
|
|
24
|
+
}, [isHighlighted]);
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<li
|
|
28
|
+
ref={optionRef}
|
|
29
|
+
role="option"
|
|
30
|
+
key={getOptionValue(option)}
|
|
31
|
+
id={`${id}-option-${groupIndex}-${index}`}
|
|
32
|
+
aria-selected={isHighlighted}
|
|
33
|
+
onMouseDown={() => onOptionSelect(option)}
|
|
34
|
+
className={classNames("mobius-combobox__option", {
|
|
35
|
+
"mobius-combobox__option--is-highlighted": isHighlighted,
|
|
36
|
+
})}
|
|
37
|
+
>
|
|
38
|
+
{getOptionLabel(option)}
|
|
39
|
+
</li>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
@@ -91,3 +91,114 @@ export const FRUITS_OBJECTS = [
|
|
|
91
91
|
{ label: "Tangerine", value: "tangerine" },
|
|
92
92
|
{ label: "Watermelon", value: "watermelon" },
|
|
93
93
|
];
|
|
94
|
+
|
|
95
|
+
export const FRUITS_GROUPS = [
|
|
96
|
+
{
|
|
97
|
+
heading: "A-L",
|
|
98
|
+
options: [
|
|
99
|
+
"Apple",
|
|
100
|
+
"Apricot",
|
|
101
|
+
"Avocado",
|
|
102
|
+
"Banana",
|
|
103
|
+
"Blackberry",
|
|
104
|
+
"Blueberry",
|
|
105
|
+
"Cantaloupe",
|
|
106
|
+
"Cherry",
|
|
107
|
+
"Clementine",
|
|
108
|
+
"Coconut",
|
|
109
|
+
"Cranberry",
|
|
110
|
+
"Date",
|
|
111
|
+
"Dragonfruit",
|
|
112
|
+
"Durian",
|
|
113
|
+
"Elderberry",
|
|
114
|
+
"Fig",
|
|
115
|
+
"Grape",
|
|
116
|
+
"Grapefruit",
|
|
117
|
+
"Guava",
|
|
118
|
+
"Honeydew",
|
|
119
|
+
"Jackfruit",
|
|
120
|
+
"Kiwi",
|
|
121
|
+
"Kumquat",
|
|
122
|
+
"Lemon",
|
|
123
|
+
"Lime",
|
|
124
|
+
"Lychee",
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
heading: "M-Z",
|
|
129
|
+
options: [
|
|
130
|
+
"Mango",
|
|
131
|
+
"Mulberry",
|
|
132
|
+
"Nectarine",
|
|
133
|
+
"Orange",
|
|
134
|
+
"Papaya",
|
|
135
|
+
"Passionfruit",
|
|
136
|
+
"Peach",
|
|
137
|
+
"Pear",
|
|
138
|
+
"Persimmon",
|
|
139
|
+
"Pineapple",
|
|
140
|
+
"Plum",
|
|
141
|
+
"Pomegranate",
|
|
142
|
+
"Raspberry",
|
|
143
|
+
"Redcurrant",
|
|
144
|
+
"Starfruit",
|
|
145
|
+
"Strawberry",
|
|
146
|
+
"Tangerine",
|
|
147
|
+
"Watermelon",
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
export const US_STATES = [
|
|
153
|
+
"Alabama",
|
|
154
|
+
"Alaska",
|
|
155
|
+
"Arizona",
|
|
156
|
+
"Arkansas",
|
|
157
|
+
"California",
|
|
158
|
+
"Colorado",
|
|
159
|
+
"Connecticut",
|
|
160
|
+
"Delaware",
|
|
161
|
+
"District Of Columbia",
|
|
162
|
+
"Florida",
|
|
163
|
+
"Georgia",
|
|
164
|
+
"Hawaii",
|
|
165
|
+
"Idaho",
|
|
166
|
+
"Illinois",
|
|
167
|
+
"Indiana",
|
|
168
|
+
"Iowa",
|
|
169
|
+
"Kansas",
|
|
170
|
+
"Kentucky",
|
|
171
|
+
"Louisiana",
|
|
172
|
+
"Maine",
|
|
173
|
+
"Maryland",
|
|
174
|
+
"Massachusetts",
|
|
175
|
+
"Michigan",
|
|
176
|
+
"Minnesota",
|
|
177
|
+
"Mississippi",
|
|
178
|
+
"Missouri",
|
|
179
|
+
"Montana",
|
|
180
|
+
"Nebraska",
|
|
181
|
+
"Nevada",
|
|
182
|
+
"New Hampshire",
|
|
183
|
+
"New Jersey",
|
|
184
|
+
"New Mexico",
|
|
185
|
+
"New York",
|
|
186
|
+
"North Carolina",
|
|
187
|
+
"North Dakota",
|
|
188
|
+
"Ohio",
|
|
189
|
+
"Oklahoma",
|
|
190
|
+
"Oregon",
|
|
191
|
+
"Pennsylvania",
|
|
192
|
+
"Rhode Island",
|
|
193
|
+
"South Carolina",
|
|
194
|
+
"South Dakota",
|
|
195
|
+
"Tennessee",
|
|
196
|
+
"Texas",
|
|
197
|
+
"Utah",
|
|
198
|
+
"Vermont",
|
|
199
|
+
"Virginia",
|
|
200
|
+
"Washington",
|
|
201
|
+
"West Virginia",
|
|
202
|
+
"Wisconsin",
|
|
203
|
+
"Wyoming",
|
|
204
|
+
];
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import type { Ref } from "react";
|
|
1
|
+
import type { ReactElement, Ref } from "react";
|
|
2
2
|
import type { TextFieldElementType, TextFieldProps } from "../TextField";
|
|
3
3
|
|
|
4
4
|
export type ComboboxProps = TextFieldProps & {
|
|
5
5
|
/** The list of options to display in the dropdown */
|
|
6
6
|
options:
|
|
7
|
-
|
|
|
8
|
-
| ((filter: string) =>
|
|
9
|
-
| ((filter: string) => Promise<
|
|
7
|
+
| ComboboxOptions
|
|
8
|
+
| ((filter: string) => ComboboxOptions)
|
|
9
|
+
| ((filter: string) => Promise<ComboboxOptions>);
|
|
10
|
+
/** An icon to display in TextField (left side) */
|
|
11
|
+
icon?: ReactElement;
|
|
10
12
|
/** The default value of the selected option */
|
|
11
13
|
defaultValue?: string | undefined;
|
|
12
14
|
/** Callback when the selected option changes */
|
|
@@ -15,6 +17,22 @@ export type ComboboxProps = TextFieldProps & {
|
|
|
15
17
|
|
|
16
18
|
export type ComboboxOption = string | { label: string; value: string };
|
|
17
19
|
|
|
20
|
+
export type ComboboxOptionGroup = {
|
|
21
|
+
heading: string;
|
|
22
|
+
options: ComboboxOption[];
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type ComboboxOptions = ComboboxOption[] | ComboboxOptionGroup[];
|
|
26
|
+
|
|
18
27
|
export type ComboboxElementType = TextFieldElementType;
|
|
19
28
|
|
|
20
29
|
export type ComboboxRef = Ref<ComboboxElementType>;
|
|
30
|
+
|
|
31
|
+
export type ComboboxOptionProps = {
|
|
32
|
+
option: ComboboxOption;
|
|
33
|
+
index: number;
|
|
34
|
+
groupIndex?: number;
|
|
35
|
+
isHighlighted: boolean;
|
|
36
|
+
onOptionSelect: (option: ComboboxOption) => void;
|
|
37
|
+
id: string;
|
|
38
|
+
};
|