@simplybusiness/mobius 5.16.0 → 5.17.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 +6 -0
- package/dist/cjs/components/Combobox/Combobox.js +7 -6
- package/dist/cjs/components/Combobox/Combobox.js.map +1 -1
- package/dist/cjs/components/Combobox/Listbox.js +3 -1
- package/dist/cjs/components/Combobox/Listbox.js.map +1 -1
- package/dist/cjs/components/Combobox/Option.js +5 -2
- package/dist/cjs/components/Combobox/Option.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/components/Combobox/Combobox.js +7 -6
- package/dist/esm/components/Combobox/Combobox.js.map +1 -1
- package/dist/esm/components/Combobox/Listbox.js +3 -1
- package/dist/esm/components/Combobox/Listbox.js.map +1 -1
- package/dist/esm/components/Combobox/Option.js +5 -2
- package/dist/esm/components/Combobox/Option.js.map +1 -1
- package/dist/esm/components/Combobox/types.js.map +1 -1
- package/dist/types/src/components/Combobox/Combobox.stories.d.ts +20 -0
- package/dist/types/src/components/Combobox/Listbox.d.ts +3 -2
- package/dist/types/src/components/Combobox/Option.d.ts +1 -1
- package/dist/types/src/components/Combobox/types.d.ts +2 -0
- package/package.json +1 -1
- package/src/components/Combobox/Combobox.css +3 -4
- package/src/components/Combobox/Combobox.mdx +31 -0
- package/src/components/Combobox/Combobox.stories.tsx +27 -0
- package/src/components/Combobox/Combobox.test.tsx +32 -0
- package/src/components/Combobox/Combobox.tsx +6 -4
- package/src/components/Combobox/Listbox.tsx +9 -1
- package/src/components/Combobox/Option.tsx +6 -1
- package/src/components/Combobox/types.tsx +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.17.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- a19a98d: Added `optionComponent` prop to `Combobox` component to allow customisation of how options are rendered. This allows for custom layouts, adding icons, or applying custom styling to individual options.
|
|
8
|
+
|
|
3
9
|
## 5.16.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
|
@@ -24,7 +24,7 @@ function _interop_require_default(obj) {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
const ComboboxInner = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
|
|
27
|
-
const { id, defaultValue, value, options, asyncOptions, delay, minSearchLength, onSelected, className, placeholder, icon, onBlur, onFocus, onChange, ...otherProps } = props;
|
|
27
|
+
const { id, defaultValue, value, options, asyncOptions, delay, minSearchLength, onSelected, className, placeholder, icon, onBlur, onFocus, onChange, optionComponent, ...otherProps } = props;
|
|
28
28
|
// Avoid re-fetching after selecting an option
|
|
29
29
|
const skipNextDebounceRef = (0, _react.useRef)(false);
|
|
30
30
|
const fallbackRef = (0, _react.useRef)(null);
|
|
@@ -142,7 +142,7 @@ const ComboboxInner = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
|
|
|
142
142
|
break;
|
|
143
143
|
case "Enter":
|
|
144
144
|
e.preventDefault();
|
|
145
|
-
if (
|
|
145
|
+
if (showListbox) {
|
|
146
146
|
const selectedOption = getHighlightedOption() || getFirstOption();
|
|
147
147
|
if (selectedOption) {
|
|
148
148
|
handleOptionSelect(selectedOption);
|
|
@@ -166,7 +166,7 @@ const ComboboxInner = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
|
|
|
166
166
|
value
|
|
167
167
|
]);
|
|
168
168
|
const classes = (0, _dedupe.default)("mobius mobius-combobox", {
|
|
169
|
-
"mobius-combobox--is-expanded":
|
|
169
|
+
"mobius-combobox--is-expanded": showListbox,
|
|
170
170
|
"mobius-combobox--is-loading": isLoading
|
|
171
171
|
}, className);
|
|
172
172
|
return /*#__PURE__*/ (0, _jsxruntime.jsxs)("div", {
|
|
@@ -196,8 +196,8 @@ const ComboboxInner = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
|
|
|
196
196
|
"aria-describedby": isLoading ? statusId : undefined,
|
|
197
197
|
"aria-autocomplete": "list",
|
|
198
198
|
"aria-haspopup": "listbox",
|
|
199
|
-
"aria-controls": listboxId,
|
|
200
|
-
"aria-expanded":
|
|
199
|
+
"aria-controls": showListbox ? listboxId : undefined,
|
|
200
|
+
"aria-expanded": showListbox,
|
|
201
201
|
"aria-activedescendant": highlightedIndex === -1 ? undefined : getHighlightedOptionId(),
|
|
202
202
|
prefixInside: icon,
|
|
203
203
|
ref: inputRef
|
|
@@ -207,7 +207,8 @@ const ComboboxInner = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
|
|
|
207
207
|
options: filteredOptions,
|
|
208
208
|
highlightedIndex: highlightedIndex,
|
|
209
209
|
highlightedGroupIndex: highlightedGroupIndex,
|
|
210
|
-
onOptionSelect: handleOptionSelect
|
|
210
|
+
onOptionSelect: handleOptionSelect,
|
|
211
|
+
optionComponent: optionComponent
|
|
211
212
|
})
|
|
212
213
|
]
|
|
213
214
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import classNames from \"classnames/dedupe\";\nimport type { FocusEvent } from \"react\";\nimport { forwardRef, useEffect, useId, useRef, useState } from \"react\";\nimport { useOnUnmount } from \"../../hooks\";\nimport { TextField } from \"../TextField\";\nimport { VisuallyHidden } from \"../VisuallyHidden\";\nimport { Listbox } from \"./Listbox\"; // Import Listbox component\nimport type { ComboboxOption, ComboboxProps, ComboboxRef } from \"./types\";\nimport { useComboboxHighlight } from \"./useComboboxHighlight\";\nimport { useComboboxOptions } from \"./useComboboxOptions\";\nimport { getOptionLabel, getOptionValue, isOptionGroup } from \"./utils\";\n\nconst ComboboxInner = forwardRef(\n <T extends ComboboxOption>(props: ComboboxProps<T>, ref: ComboboxRef) => {\n const {\n id,\n defaultValue,\n value,\n options,\n asyncOptions,\n delay,\n minSearchLength,\n onSelected,\n className,\n placeholder,\n icon,\n onBlur,\n onFocus,\n onChange,\n ...otherProps\n } = props;\n\n // Avoid re-fetching after selecting an option\n const skipNextDebounceRef = useRef(false);\n const fallbackRef = useRef<HTMLInputElement>(null);\n const [inputValue, setInputValue] = useState(defaultValue || \"\");\n const [isOpen, setIsOpen] = useState(false);\n const { filteredOptions, updateFilteredOptions, isLoading } =\n useComboboxOptions({\n options,\n asyncOptions,\n inputValue,\n delay,\n minSearchLength,\n skipNextDebounceRef,\n });\n const {\n highlightedIndex,\n highlightedGroupIndex,\n highlightNextOption,\n highlightPreviousOption,\n highlightFirstOption,\n highlightLastOption,\n clearHighlight,\n } = useComboboxHighlight(filteredOptions);\n\n const inputRef = ref || fallbackRef;\n const listboxId = useId();\n const statusId = useId();\n const blurTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const showListbox = isOpen && filteredOptions.length > 0;\n\n const handleFocus = (e: FocusEvent) => {\n if (filteredOptions.length === 0) return;\n if (blurTimeoutRef.current) {\n clearTimeout(blurTimeoutRef.current);\n blurTimeoutRef.current = null;\n } else {\n onFocus?.(e);\n }\n setIsOpen(true);\n };\n\n useOnUnmount(() => {\n if (blurTimeoutRef.current) {\n clearTimeout(blurTimeoutRef.current);\n }\n });\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n setInputValue(newValue);\n setIsOpen(true);\n clearHighlight();\n onChange?.(e);\n };\n\n const handleOptionSelect = (option: T) => {\n const val = getOptionValue(option);\n if (!val) return;\n\n // TODO: Declare this in the types\n if (\n typeof option === \"object\" &&\n \"callback\" in option &&\n option.callback &&\n typeof option.callback === \"function\"\n ) {\n // @ts-expect-error ref types are hard\n setTimeout(() => inputRef.current.focus(), 0);\n updateFilteredOptions(option.callback());\n return;\n }\n\n // Prevent re-fetching options after selecting an option\n skipNextDebounceRef.current = true;\n\n setIsOpen(false);\n setInputValue(val);\n onSelected?.(option);\n };\n\n const getFirstOption = () => {\n if (isOptionGroup(filteredOptions)) {\n return filteredOptions[0]?.options[0];\n }\n\n return filteredOptions[0];\n };\n\n const getHighlightedOption = () => {\n if (highlightedIndex === -1) return undefined;\n\n if (isOptionGroup(filteredOptions)) {\n const group = filteredOptions[highlightedGroupIndex];\n return group?.options[highlightedIndex];\n }\n\n return filteredOptions[highlightedIndex];\n };\n\n const getHighlightedOptionId = () => {\n const option = getHighlightedOption();\n if (!option) return undefined;\n\n if (isOptionGroup(filteredOptions)) {\n return `${listboxId}-option-${highlightedGroupIndex}-${highlightedIndex}`;\n }\n\n return `${listboxId}-option-${highlightedIndex}`;\n };\n\n const handleBlur = (e: FocusEvent<Element, Element>) => {\n // Force selection if user has matched an entry\n const typedText = inputValue.trim().toLowerCase();\n const highlightedOption = getHighlightedOption();\n const label = getOptionLabel(highlightedOption);\n\n if (typedText === label?.toLowerCase()) {\n handleOptionSelect(highlightedOption as T);\n }\n\n blurTimeoutRef.current = setTimeout(() => {\n onBlur?.(e);\n setIsOpen(false);\n }, 150);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n setIsOpen(true);\n highlightNextOption();\n break;\n case \"ArrowUp\":\n e.preventDefault();\n setIsOpen(true);\n highlightPreviousOption();\n break;\n case \"Home\":\n e.preventDefault();\n setIsOpen(true);\n highlightFirstOption();\n break;\n case \"End\":\n e.preventDefault();\n setIsOpen(true);\n highlightLastOption();\n break;\n case \"Enter\":\n e.preventDefault();\n if (isOpen) {\n const selectedOption = getHighlightedOption() || getFirstOption();\n if (selectedOption) {\n handleOptionSelect(selectedOption);\n }\n }\n break;\n case \"Escape\":\n e.preventDefault();\n setInputValue(\"\");\n setIsOpen(false);\n clearHighlight();\n break;\n default:\n // Do nothing\n }\n };\n\n useEffect(() => {\n if (value) {\n setInputValue(value);\n }\n }, [value]);\n\n const classes = classNames(\n \"mobius mobius-combobox\",\n {\n \"mobius-combobox--is-expanded\": isOpen,\n \"mobius-combobox--is-loading\": isLoading,\n },\n className,\n );\n\n return (\n <div id={id} data-testid=\"mobius-combobox__wrapper\" className={classes}>\n {isLoading && (\n <VisuallyHidden\n role=\"status\"\n aria-live=\"polite\"\n id={statusId}\n elementType=\"div\"\n className=\"mobius-combobox__status\"\n >\n Loading options\n </VisuallyHidden>\n )}\n <TextField\n {...otherProps}\n className=\"mobius-combobox__input\"\n role=\"combobox\"\n value={inputValue}\n placeholder={placeholder}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n onChange={handleInputChange}\n autoComplete=\"off\"\n aria-describedby={isLoading ? statusId : undefined}\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls={listboxId}\n aria-expanded={isOpen}\n aria-activedescendant={\n highlightedIndex === -1 ? undefined : getHighlightedOptionId()\n }\n prefixInside={icon}\n ref={inputRef}\n />\n {showListbox && (\n <Listbox\n id={listboxId}\n options={filteredOptions}\n highlightedIndex={highlightedIndex}\n highlightedGroupIndex={highlightedGroupIndex}\n onOptionSelect={handleOptionSelect}\n />\n )}\n </div>\n );\n },\n);\n\nexport const Combobox = ComboboxInner as <T extends ComboboxOption>(\n props: ComboboxProps<T> & { ref?: ComboboxRef },\n) => JSX.Element;\n"],"names":["Combobox","ComboboxInner","forwardRef","props","ref","id","defaultValue","value","options","asyncOptions","delay","minSearchLength","onSelected","className","placeholder","icon","onBlur","onFocus","onChange","otherProps","skipNextDebounceRef","useRef","fallbackRef","inputValue","setInputValue","useState","isOpen","setIsOpen","filteredOptions","updateFilteredOptions","isLoading","useComboboxOptions","highlightedIndex","highlightedGroupIndex","highlightNextOption","highlightPreviousOption","highlightFirstOption","highlightLastOption","clearHighlight","useComboboxHighlight","inputRef","listboxId","useId","statusId","blurTimeoutRef","showListbox","length","handleFocus","e","current","clearTimeout","useOnUnmount","handleInputChange","newValue","target","handleOptionSelect","option","val","getOptionValue","callback","setTimeout","focus","getFirstOption","isOptionGroup","getHighlightedOption","undefined","group","getHighlightedOptionId","handleBlur","typedText","trim","toLowerCase","highlightedOption","label","getOptionLabel","handleKeyDown","key","preventDefault","selectedOption","useEffect","classes","classNames","div","data-testid","VisuallyHidden","role","aria-live","elementType","TextField","onKeyDown","autoComplete","aria-describedby","aria-autocomplete","aria-haspopup","aria-controls","aria-expanded","aria-activedescendant","prefixInside","Listbox","onOptionSelect"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import classNames from \"classnames/dedupe\";\nimport type { FocusEvent } from \"react\";\nimport { forwardRef, useEffect, useId, useRef, useState } from \"react\";\nimport { useOnUnmount } from \"../../hooks\";\nimport { TextField } from \"../TextField\";\nimport { VisuallyHidden } from \"../VisuallyHidden\";\nimport { Listbox } from \"./Listbox\"; // Import Listbox component\nimport type { ComboboxOption, ComboboxProps, ComboboxRef } from \"./types\";\nimport { useComboboxHighlight } from \"./useComboboxHighlight\";\nimport { useComboboxOptions } from \"./useComboboxOptions\";\nimport { getOptionLabel, getOptionValue, isOptionGroup } from \"./utils\";\n\nconst ComboboxInner = forwardRef(\n <T extends ComboboxOption>(props: ComboboxProps<T>, ref: ComboboxRef) => {\n const {\n id,\n defaultValue,\n value,\n options,\n asyncOptions,\n delay,\n minSearchLength,\n onSelected,\n className,\n placeholder,\n icon,\n onBlur,\n onFocus,\n onChange,\n optionComponent,\n ...otherProps\n } = props;\n\n // Avoid re-fetching after selecting an option\n const skipNextDebounceRef = useRef(false);\n const fallbackRef = useRef<HTMLInputElement>(null);\n const [inputValue, setInputValue] = useState(defaultValue || \"\");\n const [isOpen, setIsOpen] = useState(false);\n const { filteredOptions, updateFilteredOptions, isLoading } =\n useComboboxOptions({\n options,\n asyncOptions,\n inputValue,\n delay,\n minSearchLength,\n skipNextDebounceRef,\n });\n const {\n highlightedIndex,\n highlightedGroupIndex,\n highlightNextOption,\n highlightPreviousOption,\n highlightFirstOption,\n highlightLastOption,\n clearHighlight,\n } = useComboboxHighlight(filteredOptions);\n\n const inputRef = ref || fallbackRef;\n const listboxId = useId();\n const statusId = useId();\n const blurTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const showListbox = isOpen && filteredOptions.length > 0;\n\n const handleFocus = (e: FocusEvent) => {\n if (filteredOptions.length === 0) return;\n if (blurTimeoutRef.current) {\n clearTimeout(blurTimeoutRef.current);\n blurTimeoutRef.current = null;\n } else {\n onFocus?.(e);\n }\n setIsOpen(true);\n };\n\n useOnUnmount(() => {\n if (blurTimeoutRef.current) {\n clearTimeout(blurTimeoutRef.current);\n }\n });\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n setInputValue(newValue);\n setIsOpen(true);\n clearHighlight();\n onChange?.(e);\n };\n\n const handleOptionSelect = (option: T) => {\n const val = getOptionValue(option);\n if (!val) return;\n\n // TODO: Declare this in the types\n if (\n typeof option === \"object\" &&\n \"callback\" in option &&\n option.callback &&\n typeof option.callback === \"function\"\n ) {\n // @ts-expect-error ref types are hard\n setTimeout(() => inputRef.current.focus(), 0);\n updateFilteredOptions(option.callback());\n return;\n }\n\n // Prevent re-fetching options after selecting an option\n skipNextDebounceRef.current = true;\n\n setIsOpen(false);\n setInputValue(val);\n onSelected?.(option);\n };\n\n const getFirstOption = () => {\n if (isOptionGroup(filteredOptions)) {\n return filteredOptions[0]?.options[0];\n }\n\n return filteredOptions[0];\n };\n\n const getHighlightedOption = () => {\n if (highlightedIndex === -1) return undefined;\n\n if (isOptionGroup(filteredOptions)) {\n const group = filteredOptions[highlightedGroupIndex];\n return group?.options[highlightedIndex];\n }\n\n return filteredOptions[highlightedIndex];\n };\n\n const getHighlightedOptionId = () => {\n const option = getHighlightedOption();\n if (!option) return undefined;\n\n if (isOptionGroup(filteredOptions)) {\n return `${listboxId}-option-${highlightedGroupIndex}-${highlightedIndex}`;\n }\n\n return `${listboxId}-option-${highlightedIndex}`;\n };\n\n const handleBlur = (e: FocusEvent<Element, Element>) => {\n // Force selection if user has matched an entry\n const typedText = inputValue.trim().toLowerCase();\n const highlightedOption = getHighlightedOption();\n const label = getOptionLabel(highlightedOption);\n\n if (typedText === label?.toLowerCase()) {\n handleOptionSelect(highlightedOption as T);\n }\n\n blurTimeoutRef.current = setTimeout(() => {\n onBlur?.(e);\n setIsOpen(false);\n }, 150);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n setIsOpen(true);\n highlightNextOption();\n break;\n case \"ArrowUp\":\n e.preventDefault();\n setIsOpen(true);\n highlightPreviousOption();\n break;\n case \"Home\":\n e.preventDefault();\n setIsOpen(true);\n highlightFirstOption();\n break;\n case \"End\":\n e.preventDefault();\n setIsOpen(true);\n highlightLastOption();\n break;\n case \"Enter\":\n e.preventDefault();\n if (showListbox) {\n const selectedOption = getHighlightedOption() || getFirstOption();\n if (selectedOption) {\n handleOptionSelect(selectedOption);\n }\n }\n break;\n case \"Escape\":\n e.preventDefault();\n setInputValue(\"\");\n setIsOpen(false);\n clearHighlight();\n break;\n default:\n // Do nothing\n }\n };\n\n useEffect(() => {\n if (value) {\n setInputValue(value);\n }\n }, [value]);\n\n const classes = classNames(\n \"mobius mobius-combobox\",\n {\n \"mobius-combobox--is-expanded\": showListbox,\n \"mobius-combobox--is-loading\": isLoading,\n },\n className,\n );\n\n return (\n <div id={id} data-testid=\"mobius-combobox__wrapper\" className={classes}>\n {isLoading && (\n <VisuallyHidden\n role=\"status\"\n aria-live=\"polite\"\n id={statusId}\n elementType=\"div\"\n className=\"mobius-combobox__status\"\n >\n Loading options\n </VisuallyHidden>\n )}\n <TextField\n {...otherProps}\n className=\"mobius-combobox__input\"\n role=\"combobox\"\n value={inputValue}\n placeholder={placeholder}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n onChange={handleInputChange}\n autoComplete=\"off\"\n aria-describedby={isLoading ? statusId : undefined}\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls={showListbox ? listboxId : undefined}\n aria-expanded={showListbox}\n aria-activedescendant={\n highlightedIndex === -1 ? undefined : getHighlightedOptionId()\n }\n prefixInside={icon}\n ref={inputRef}\n />\n {showListbox && (\n <Listbox\n id={listboxId}\n options={filteredOptions}\n highlightedIndex={highlightedIndex}\n highlightedGroupIndex={highlightedGroupIndex}\n onOptionSelect={handleOptionSelect}\n optionComponent={optionComponent}\n />\n )}\n </div>\n );\n },\n);\n\nexport const Combobox = ComboboxInner as <T extends ComboboxOption>(\n props: ComboboxProps<T> & { ref?: ComboboxRef },\n) => JSX.Element;\n"],"names":["Combobox","ComboboxInner","forwardRef","props","ref","id","defaultValue","value","options","asyncOptions","delay","minSearchLength","onSelected","className","placeholder","icon","onBlur","onFocus","onChange","optionComponent","otherProps","skipNextDebounceRef","useRef","fallbackRef","inputValue","setInputValue","useState","isOpen","setIsOpen","filteredOptions","updateFilteredOptions","isLoading","useComboboxOptions","highlightedIndex","highlightedGroupIndex","highlightNextOption","highlightPreviousOption","highlightFirstOption","highlightLastOption","clearHighlight","useComboboxHighlight","inputRef","listboxId","useId","statusId","blurTimeoutRef","showListbox","length","handleFocus","e","current","clearTimeout","useOnUnmount","handleInputChange","newValue","target","handleOptionSelect","option","val","getOptionValue","callback","setTimeout","focus","getFirstOption","isOptionGroup","getHighlightedOption","undefined","group","getHighlightedOptionId","handleBlur","typedText","trim","toLowerCase","highlightedOption","label","getOptionLabel","handleKeyDown","key","preventDefault","selectedOption","useEffect","classes","classNames","div","data-testid","VisuallyHidden","role","aria-live","elementType","TextField","onKeyDown","autoComplete","aria-describedby","aria-autocomplete","aria-haspopup","aria-controls","aria-expanded","aria-activedescendant","prefixInside","Listbox","onOptionSelect"],"mappings":"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"}
|
|
@@ -17,7 +17,7 @@ function _interop_require_default(obj) {
|
|
|
17
17
|
default: obj
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
-
const Listbox = ({ id, options, highlightedIndex, highlightedGroupIndex, onOptionSelect })=>{
|
|
20
|
+
const Listbox = ({ id, options, highlightedIndex, highlightedGroupIndex, onOptionSelect, optionComponent })=>{
|
|
21
21
|
const classes = (0, _classnames.default)("mobius-combobox__list");
|
|
22
22
|
function getOptionId(option, groupIndex, index) {
|
|
23
23
|
if (typeof option === "object" && "id" in option && typeof option.id === "string") {
|
|
@@ -44,6 +44,7 @@ const Listbox = ({ id, options, highlightedIndex, highlightedGroupIndex, onOptio
|
|
|
44
44
|
option: groupOption,
|
|
45
45
|
isHighlighted: highlightedIndex === index && highlightedGroupIndex === groupIndex,
|
|
46
46
|
onOptionSelect: onOptionSelect,
|
|
47
|
+
optionComponent: optionComponent,
|
|
47
48
|
id: getOptionId(groupOption, groupIndex, index)
|
|
48
49
|
}, `${id}-option-${groupIndex}-${index}`))
|
|
49
50
|
]
|
|
@@ -51,6 +52,7 @@ const Listbox = ({ id, options, highlightedIndex, highlightedGroupIndex, onOptio
|
|
|
51
52
|
option: option,
|
|
52
53
|
isHighlighted: highlightedIndex === index,
|
|
53
54
|
onOptionSelect: onOptionSelect,
|
|
55
|
+
optionComponent: optionComponent,
|
|
54
56
|
id: getOptionId(option, 0, index)
|
|
55
57
|
}, index))
|
|
56
58
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Combobox/Listbox.tsx"],"sourcesContent":["import classNames from \"classnames\";\nimport { Option } from \"./Option\";\nimport type {
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Combobox/Listbox.tsx"],"sourcesContent":["import classNames from \"classnames\";\nimport { Option } from \"./Option\";\nimport type {\n ComboboxBaseProps,\n ComboboxOption,\n ComboboxOptions,\n} from \"./types\";\nimport { isOptionGroup } from \"./utils\";\n\nexport type ListboxProps<T extends ComboboxOption> = {\n id: string;\n options: ComboboxOptions<T>;\n highlightedIndex: number;\n highlightedGroupIndex: number;\n onOptionSelect: (option: T) => void;\n optionComponent?: ComboboxBaseProps<T>[\"optionComponent\"];\n};\n\nexport const Listbox = <T extends ComboboxOption>({\n id,\n options,\n highlightedIndex,\n highlightedGroupIndex,\n onOptionSelect,\n optionComponent,\n}: ListboxProps<T>) => {\n const classes = classNames(\"mobius-combobox__list\");\n\n function getOptionId(\n option: ComboboxOption,\n groupIndex: number,\n index: number,\n ) {\n if (\n typeof option === \"object\" &&\n \"id\" in option &&\n typeof option.id === \"string\"\n ) {\n return option.id;\n }\n return isOptionGroup(options)\n ? `${id}-option-${groupIndex}-${index}`\n : `${id}-option-${index}`;\n }\n\n return (\n <div role=\"listbox\" id={id} className={classes}>\n {isOptionGroup(options)\n ? options.map((option, groupIndex) => (\n <ul\n role=\"group\"\n key={option.heading}\n aria-labelledby={`${id}-group-${groupIndex}`}\n className=\"mobius-combobox__group\"\n >\n <li\n role=\"presentation\"\n id={`${id}-group-${groupIndex}`}\n className=\"mobius-combobox__group-label\"\n >\n {option.heading}\n </li>\n {option.options.map((groupOption, index) => (\n <Option\n key={`${id}-option-${groupIndex}-${index}`}\n option={groupOption}\n isHighlighted={\n highlightedIndex === index &&\n highlightedGroupIndex === groupIndex\n }\n onOptionSelect={onOptionSelect}\n optionComponent={optionComponent}\n id={getOptionId(groupOption, groupIndex, index)}\n />\n ))}\n </ul>\n ))\n : options.map((option, index) => (\n <Option\n key={index}\n option={option}\n isHighlighted={highlightedIndex === index}\n onOptionSelect={onOptionSelect}\n optionComponent={optionComponent}\n id={getOptionId(option, 0, index)}\n />\n ))}\n </div>\n );\n};\n"],"names":["Listbox","id","options","highlightedIndex","highlightedGroupIndex","onOptionSelect","optionComponent","classes","classNames","getOptionId","option","groupIndex","index","isOptionGroup","div","role","className","map","ul","aria-labelledby","li","heading","groupOption","Option","isHighlighted"],"mappings":";;;;+BAkBaA;;;eAAAA;;;;mEAlBU;wBACA;uBAMO;;;;;;AAWvB,MAAMA,UAAU,CAA2B,EAChDC,EAAE,EACFC,OAAO,EACPC,gBAAgB,EAChBC,qBAAqB,EACrBC,cAAc,EACdC,eAAe,EACC;IAChB,MAAMC,UAAUC,IAAAA,mBAAU,EAAC;IAE3B,SAASC,YACPC,MAAsB,EACtBC,UAAkB,EAClBC,KAAa;QAEb,IACE,OAAOF,WAAW,YAClB,QAAQA,UACR,OAAOA,OAAOT,EAAE,KAAK,UACrB;YACA,OAAOS,OAAOT,EAAE;QAClB;QACA,OAAOY,IAAAA,oBAAa,EAACX,WACjB,GAAGD,GAAG,QAAQ,EAAEU,WAAW,CAAC,EAAEC,OAAO,GACrC,GAAGX,GAAG,QAAQ,EAAEW,OAAO;IAC7B;IAEA,qBACE,qBAACE;QAAIC,MAAK;QAAUd,IAAIA;QAAIe,WAAWT;kBACpCM,IAAAA,oBAAa,EAACX,WACXA,QAAQe,GAAG,CAAC,CAACP,QAAQC,2BACnB,sBAACO;gBACCH,MAAK;gBAELI,mBAAiB,GAAGlB,GAAG,OAAO,EAAEU,YAAY;gBAC5CK,WAAU;;kCAEV,qBAACI;wBACCL,MAAK;wBACLd,IAAI,GAAGA,GAAG,OAAO,EAAEU,YAAY;wBAC/BK,WAAU;kCAETN,OAAOW,OAAO;;oBAEhBX,OAAOR,OAAO,CAACe,GAAG,CAAC,CAACK,aAAaV,sBAChC,qBAACW,cAAM;4BAELb,QAAQY;4BACRE,eACErB,qBAAqBS,SACrBR,0BAA0BO;4BAE5BN,gBAAgBA;4BAChBC,iBAAiBA;4BACjBL,IAAIQ,YAAYa,aAAaX,YAAYC;2BARpC,GAAGX,GAAG,QAAQ,EAAEU,WAAW,CAAC,EAAEC,OAAO;;eAbzCF,OAAOW,OAAO,KA0BvBnB,QAAQe,GAAG,CAAC,CAACP,QAAQE,sBACnB,qBAACW,cAAM;gBAELb,QAAQA;gBACRc,eAAerB,qBAAqBS;gBACpCP,gBAAgBA;gBAChBC,iBAAiBA;gBACjBL,IAAIQ,YAAYC,QAAQ,GAAGE;eALtBA;;AAUnB"}
|
|
@@ -17,7 +17,7 @@ function _interop_require_default(obj) {
|
|
|
17
17
|
default: obj
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
-
const Option = ({ option, isHighlighted, onOptionSelect, id })=>{
|
|
20
|
+
const Option = ({ option, isHighlighted, onOptionSelect, optionComponent: OptionComponent, id })=>{
|
|
21
21
|
const optionRef = (0, _react.useRef)(null);
|
|
22
22
|
(0, _react.useEffect)(()=>{
|
|
23
23
|
if (isHighlighted && optionRef.current && optionRef.current.scrollIntoView) {
|
|
@@ -37,7 +37,10 @@ const Option = ({ option, isHighlighted, onOptionSelect, id })=>{
|
|
|
37
37
|
className: (0, _dedupe.default)("mobius-combobox__option", {
|
|
38
38
|
"mobius-combobox__option--is-highlighted": isHighlighted
|
|
39
39
|
}),
|
|
40
|
-
children: (0,
|
|
40
|
+
children: OptionComponent ? /*#__PURE__*/ (0, _jsxruntime.jsx)(OptionComponent, {
|
|
41
|
+
option: option,
|
|
42
|
+
isHighlighted: isHighlighted
|
|
43
|
+
}) : (0, _utils.getOptionLabel)(option)
|
|
41
44
|
}, (0, _utils.getOptionValue)(option));
|
|
42
45
|
};
|
|
43
46
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Combobox/Option.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport classNames from \"classnames/dedupe\";\nimport { getOptionValue, getOptionLabel } from \"./utils\";\nimport type { ComboboxOption, ComboboxOptionProps } from \"./types\";\n\nexport const Option = <T extends ComboboxOption>({\n option,\n isHighlighted,\n onOptionSelect,\n id,\n}: ComboboxOptionProps<T>) => {\n const optionRef = useRef<HTMLLIElement>(null);\n\n useEffect(() => {\n if (\n isHighlighted &&\n optionRef.current &&\n optionRef.current.scrollIntoView\n ) {\n optionRef.current.scrollIntoView({ block: \"nearest\" });\n }\n }, [isHighlighted]);\n\n return (\n <li\n ref={optionRef}\n role=\"option\"\n key={getOptionValue(option)}\n id={id}\n aria-selected={isHighlighted}\n onMouseDown={() => onOptionSelect(option)}\n className={classNames(\"mobius-combobox__option\", {\n \"mobius-combobox__option--is-highlighted\": isHighlighted,\n })}\n >\n {getOptionLabel(option)}\n </li>\n );\n};\n"],"names":["Option","option","isHighlighted","onOptionSelect","id","optionRef","useRef","useEffect","current","scrollIntoView","block","li","ref","role","aria-selected","onMouseDown","className","classNames","getOptionLabel","getOptionValue"],"mappings":";;;;+BAKaA;;;eAAAA;;;;uBALqB;+DACX;uBACwB;;;;;;AAGxC,MAAMA,SAAS,CAA2B,EAC/CC,MAAM,EACNC,aAAa,EACbC,cAAc,EACdC,EAAE,EACqB;IACvB,MAAMC,YAAYC,IAAAA,aAAM,EAAgB;IAExCC,IAAAA,gBAAS,EAAC;QACR,
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Combobox/Option.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport classNames from \"classnames/dedupe\";\nimport { getOptionValue, getOptionLabel } from \"./utils\";\nimport type { ComboboxOption, ComboboxOptionProps } from \"./types\";\n\nexport const Option = <T extends ComboboxOption>({\n option,\n isHighlighted,\n onOptionSelect,\n optionComponent: OptionComponent,\n id,\n}: ComboboxOptionProps<T>) => {\n const optionRef = useRef<HTMLLIElement>(null);\n\n useEffect(() => {\n if (\n isHighlighted &&\n optionRef.current &&\n optionRef.current.scrollIntoView\n ) {\n optionRef.current.scrollIntoView({ block: \"nearest\" });\n }\n }, [isHighlighted]);\n\n return (\n <li\n ref={optionRef}\n role=\"option\"\n key={getOptionValue(option)}\n id={id}\n aria-selected={isHighlighted}\n onMouseDown={() => onOptionSelect(option)}\n className={classNames(\"mobius-combobox__option\", {\n \"mobius-combobox__option--is-highlighted\": isHighlighted,\n })}\n >\n {OptionComponent ? (\n <OptionComponent option={option} isHighlighted={isHighlighted} />\n ) : (\n getOptionLabel(option)\n )}\n </li>\n );\n};\n"],"names":["Option","option","isHighlighted","onOptionSelect","optionComponent","OptionComponent","id","optionRef","useRef","useEffect","current","scrollIntoView","block","li","ref","role","aria-selected","onMouseDown","className","classNames","getOptionLabel","getOptionValue"],"mappings":";;;;+BAKaA;;;eAAAA;;;;uBALqB;+DACX;uBACwB;;;;;;AAGxC,MAAMA,SAAS,CAA2B,EAC/CC,MAAM,EACNC,aAAa,EACbC,cAAc,EACdC,iBAAiBC,eAAe,EAChCC,EAAE,EACqB;IACvB,MAAMC,YAAYC,IAAAA,aAAM,EAAgB;IAExCC,IAAAA,gBAAS,EAAC;QACR,IACEP,iBACAK,UAAUG,OAAO,IACjBH,UAAUG,OAAO,CAACC,cAAc,EAChC;YACAJ,UAAUG,OAAO,CAACC,cAAc,CAAC;gBAAEC,OAAO;YAAU;QACtD;IACF,GAAG;QAACV;KAAc;IAElB,qBACE,qBAACW;QACCC,KAAKP;QACLQ,MAAK;QAELT,IAAIA;QACJU,iBAAed;QACfe,aAAa,IAAMd,eAAeF;QAClCiB,WAAWC,IAAAA,eAAU,EAAC,2BAA2B;YAC/C,2CAA2CjB;QAC7C;kBAECG,gCACC,qBAACA;YAAgBJ,QAAQA;YAAQC,eAAeA;aAEhDkB,IAAAA,qBAAc,EAACnB;OAXZoB,IAAAA,qBAAc,EAACpB;AAe1B"}
|