@simplybusiness/mobius 5.6.0 → 5.7.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.
@@ -6,7 +6,7 @@ import { Listbox } from "./Listbox"; // Import Listbox component
6
6
  import { useComboboxHighlight } from "./useComboboxHighlight";
7
7
  import { filterOptions, getOptionValue, isOptionGroup } from "./utils";
8
8
  export const Combobox = /*#__PURE__*/ forwardRef((props, ref)=>{
9
- const { defaultValue, options, onSelected, className, placeholder, icon } = props;
9
+ const { defaultValue, options, asyncOptions, onSelected, className, placeholder, icon } = props;
10
10
  const fallbackRef = useRef(null);
11
11
  const [inputValue, setInputValue] = useState(defaultValue || "");
12
12
  const [isOpen, setIsOpen] = useState(false);
@@ -17,8 +17,8 @@ export const Combobox = /*#__PURE__*/ forwardRef((props, ref)=>{
17
17
  const blurTimeoutRef = useRef(null);
18
18
  useEffect(()=>{
19
19
  const fetchOptions = async ()=>{
20
- if (typeof options === "function") {
21
- const result = await options(inputValue);
20
+ if (asyncOptions) {
21
+ const result = await asyncOptions(inputValue);
22
22
  setFilteredOptions(result);
23
23
  } else {
24
24
  setFilteredOptions(filterOptions(options, inputValue));
@@ -27,7 +27,8 @@ export const Combobox = /*#__PURE__*/ forwardRef((props, ref)=>{
27
27
  fetchOptions();
28
28
  }, [
29
29
  inputValue,
30
- options
30
+ options,
31
+ asyncOptions
31
32
  ]);
32
33
  const handleFocus = ()=>{
33
34
  if (blurTimeoutRef.current) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import classNames from \"classnames/dedupe\";\nimport { forwardRef, useEffect, useId, useRef, useState } from \"react\";\nimport type { ForwardedRefComponent } from \"../../types\";\nimport { TextField } from \"../TextField\";\nimport { Listbox } from \"./Listbox\"; // Import Listbox component\nimport type {\n ComboboxElementType,\n ComboboxOption,\n ComboboxOptions,\n ComboboxProps,\n ComboboxRef,\n} from \"./types\";\nimport { useComboboxHighlight } from \"./useComboboxHighlight\";\nimport { filterOptions, getOptionValue, isOptionGroup } from \"./utils\";\n\nexport const Combobox: ForwardedRefComponent<\n ComboboxProps,\n ComboboxElementType\n> = forwardRef((props: ComboboxProps, ref: ComboboxRef) => {\n const { defaultValue, options, onSelected, className, placeholder, icon } =\n props;\n\n const fallbackRef = useRef<HTMLInputElement>(null);\n const [inputValue, setInputValue] = useState(defaultValue || \"\");\n const [isOpen, setIsOpen] = useState(false);\n const [filteredOptions, setFilteredOptions] = useState<ComboboxOptions>([]);\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 blurTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n useEffect(() => {\n const fetchOptions = async () => {\n if (typeof options === \"function\") {\n const result = await options(inputValue);\n setFilteredOptions(result);\n } else {\n setFilteredOptions(filterOptions(options, inputValue));\n }\n };\n\n fetchOptions();\n }, [inputValue, options]);\n\n const handleFocus = () => {\n if (blurTimeoutRef.current) {\n clearTimeout(blurTimeoutRef.current);\n blurTimeoutRef.current = null;\n }\n setIsOpen(true);\n };\n\n const handleBlur = () => {\n blurTimeoutRef.current = setTimeout(() => {\n setIsOpen(false);\n }, 150);\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n setInputValue(newValue);\n setIsOpen(true);\n clearHighlight();\n };\n\n const handleOptionSelect = (option: ComboboxOption) => {\n const value = getOptionValue(option);\n if (!value) return;\n setIsOpen(false);\n setInputValue(value);\n onSelected?.(value);\n };\n\n function 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 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 handleOptionSelect(getHighlightedOption()!);\n }\n break;\n case \"Escape\":\n e.preventDefault();\n setIsOpen(false);\n clearHighlight();\n break;\n default:\n // Do nothing\n }\n };\n\n const classes = classNames(\n \"mobius mobius-combobox\",\n { expanded: isOpen },\n className,\n );\n\n return (\n <div className={classes}>\n <TextField\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-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls={listboxId}\n aria-expanded={isOpen}\n aria-activedescendant={\n highlightedIndex === -1\n ? undefined\n : `${listboxId}-option-${highlightedGroupIndex}-${highlightedIndex}`\n }\n prefixInside={icon}\n ref={inputRef}\n />\n {isOpen && (\n <Listbox\n id={listboxId}\n options={filteredOptions}\n highlightedIndex={highlightedIndex}\n highlightedGroupIndex={highlightedGroupIndex}\n onOptionSelect={handleOptionSelect}\n expanded={isOpen}\n />\n )}\n </div>\n );\n});\n"],"names":["classNames","forwardRef","useEffect","useId","useRef","useState","TextField","Listbox","useComboboxHighlight","filterOptions","getOptionValue","isOptionGroup","Combobox","props","ref","defaultValue","options","onSelected","className","placeholder","icon","fallbackRef","inputValue","setInputValue","isOpen","setIsOpen","filteredOptions","setFilteredOptions","highlightedIndex","highlightedGroupIndex","highlightNextOption","highlightPreviousOption","highlightFirstOption","highlightLastOption","clearHighlight","inputRef","listboxId","blurTimeoutRef","fetchOptions","result","handleFocus","current","clearTimeout","handleBlur","setTimeout","handleInputChange","e","newValue","target","value","handleOptionSelect","option","getHighlightedOption","undefined","group","handleKeyDown","key","preventDefault","classes","expanded","div","role","onFocus","onBlur","onKeyDown","onChange","autoComplete","aria-autocomplete","aria-haspopup","aria-controls","aria-expanded","aria-activedescendant","prefixInside","id","onOptionSelect"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import classNames from \"classnames/dedupe\";\nimport { forwardRef, useEffect, useId, useRef, useState } from \"react\";\nimport type { ForwardedRefComponent } from \"../../types\";\nimport { TextField } from \"../TextField\";\nimport { Listbox } from \"./Listbox\"; // Import Listbox component\nimport type {\n ComboboxElementType,\n ComboboxOption,\n ComboboxOptions,\n ComboboxProps,\n ComboboxRef,\n} from \"./types\";\nimport { useComboboxHighlight } from \"./useComboboxHighlight\";\nimport { filterOptions, getOptionValue, isOptionGroup } from \"./utils\";\n\nexport const Combobox: ForwardedRefComponent<\n ComboboxProps,\n ComboboxElementType\n> = forwardRef((props: ComboboxProps, ref: ComboboxRef) => {\n const {\n defaultValue,\n options,\n asyncOptions,\n onSelected,\n className,\n placeholder,\n icon,\n } = props;\n\n const fallbackRef = useRef<HTMLInputElement>(null);\n const [inputValue, setInputValue] = useState(defaultValue || \"\");\n const [isOpen, setIsOpen] = useState(false);\n const [filteredOptions, setFilteredOptions] = useState<ComboboxOptions>([]);\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 blurTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n useEffect(() => {\n const fetchOptions = async () => {\n if (asyncOptions) {\n const result = await asyncOptions(inputValue);\n setFilteredOptions(result);\n } else {\n setFilteredOptions(filterOptions(options, inputValue));\n }\n };\n\n fetchOptions();\n }, [inputValue, options, asyncOptions]);\n\n const handleFocus = () => {\n if (blurTimeoutRef.current) {\n clearTimeout(blurTimeoutRef.current);\n blurTimeoutRef.current = null;\n }\n setIsOpen(true);\n };\n\n const handleBlur = () => {\n blurTimeoutRef.current = setTimeout(() => {\n setIsOpen(false);\n }, 150);\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n setInputValue(newValue);\n setIsOpen(true);\n clearHighlight();\n };\n\n const handleOptionSelect = (option: ComboboxOption) => {\n const value = getOptionValue(option);\n if (!value) return;\n setIsOpen(false);\n setInputValue(value);\n onSelected?.(value);\n };\n\n function 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 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 handleOptionSelect(getHighlightedOption()!);\n }\n break;\n case \"Escape\":\n e.preventDefault();\n setIsOpen(false);\n clearHighlight();\n break;\n default:\n // Do nothing\n }\n };\n\n const classes = classNames(\n \"mobius mobius-combobox\",\n { expanded: isOpen },\n className,\n );\n\n return (\n <div className={classes}>\n <TextField\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-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls={listboxId}\n aria-expanded={isOpen}\n aria-activedescendant={\n highlightedIndex === -1\n ? undefined\n : `${listboxId}-option-${highlightedGroupIndex}-${highlightedIndex}`\n }\n prefixInside={icon}\n ref={inputRef}\n />\n {isOpen && (\n <Listbox\n id={listboxId}\n options={filteredOptions}\n highlightedIndex={highlightedIndex}\n highlightedGroupIndex={highlightedGroupIndex}\n onOptionSelect={handleOptionSelect}\n expanded={isOpen}\n />\n )}\n </div>\n );\n});\n"],"names":["classNames","forwardRef","useEffect","useId","useRef","useState","TextField","Listbox","useComboboxHighlight","filterOptions","getOptionValue","isOptionGroup","Combobox","props","ref","defaultValue","options","asyncOptions","onSelected","className","placeholder","icon","fallbackRef","inputValue","setInputValue","isOpen","setIsOpen","filteredOptions","setFilteredOptions","highlightedIndex","highlightedGroupIndex","highlightNextOption","highlightPreviousOption","highlightFirstOption","highlightLastOption","clearHighlight","inputRef","listboxId","blurTimeoutRef","fetchOptions","result","handleFocus","current","clearTimeout","handleBlur","setTimeout","handleInputChange","e","newValue","target","value","handleOptionSelect","option","getHighlightedOption","undefined","group","handleKeyDown","key","preventDefault","classes","expanded","div","role","onFocus","onBlur","onKeyDown","onChange","autoComplete","aria-autocomplete","aria-haspopup","aria-controls","aria-expanded","aria-activedescendant","prefixInside","id","onOptionSelect"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/Combobox/types.tsx"],"sourcesContent":["import type { ReactElement, Ref } from \"react\";\nimport type { TextFieldElementType, TextFieldProps } from \"../TextField\";\n\nexport type ComboboxProps = TextFieldProps & {\n /** The list of options to display in the dropdown */\n options:\n | ComboboxOptions\n | ((filter: string) => ComboboxOptions)\n | ((filter: string) => Promise<ComboboxOptions>);\n /** An icon to display in TextField (left side) */\n icon?: ReactElement;\n /** The default value of the selected option */\n defaultValue?: string | undefined;\n /** Callback when the selected option changes */\n onSelected?: ((value: string) => void) | undefined;\n};\n\nexport type ComboboxOption = string | { label: string; value: string };\n\nexport type ComboboxOptionGroup = {\n heading: string;\n options: ComboboxOption[];\n};\n\nexport type ComboboxOptions = ComboboxOption[] | ComboboxOptionGroup[];\n\nexport type ComboboxElementType = TextFieldElementType;\n\nexport type ComboboxRef = Ref<ComboboxElementType>;\n\nexport type ComboboxOptionProps = {\n option: ComboboxOption;\n index: number;\n groupIndex?: number;\n isHighlighted: boolean;\n onOptionSelect: (option: ComboboxOption) => void;\n id: string;\n};\n"],"names":[],"mappings":"AA8BA,WAOE"}
1
+ {"version":3,"sources":["../../../../src/components/Combobox/types.tsx"],"sourcesContent":["import type { ReactElement, Ref } from \"react\";\nimport type { TextFieldElementType, TextFieldProps } from \"../TextField\";\n\nexport type ComboboxBaseProps = TextFieldProps & {\n /** An icon to display in TextField (left side) */\n icon?: ReactElement;\n /** The default value of the selected option */\n defaultValue?: string | undefined;\n /** Callback when the selected option changes */\n onSelected?: ((value: string) => void) | undefined;\n};\n\nexport type ComboboxSyncProps = ComboboxBaseProps & {\n /** The list of options to display in the dropdown */\n options: ComboboxOptions;\n asyncOptions?: never;\n delay?: never;\n minLength?: never;\n};\n\nexport type ComboboxAsyncProps = ComboboxBaseProps & {\n options?: never;\n delay?: number;\n minLength?: number;\n /** A function that returns a list of options to display in the dropdown */\n asyncOptions:\n | ((inputValue: string) => ComboboxOptions)\n | ((\n inputValue: string,\n options?: { signal?: AbortSignal },\n ) => Promise<ComboboxOptions>);\n};\n\nexport type ComboboxProps = ComboboxAsyncProps | ComboboxSyncProps;\n\nexport type ComboboxOption = string | { label: string; value: string };\n\nexport type ComboboxOptionGroup = {\n heading: string;\n options: ComboboxOption[];\n};\n\nexport type ComboboxOptions = ComboboxOption[] | ComboboxOptionGroup[];\n\nexport type ComboboxElementType = TextFieldElementType;\n\nexport type ComboboxRef = Ref<ComboboxElementType>;\n\nexport type ComboboxOptionProps = {\n option: ComboboxOption;\n index: number;\n groupIndex?: number;\n isHighlighted: boolean;\n onOptionSelect: (option: ComboboxOption) => void;\n id: string;\n};\n"],"names":[],"mappings":"AAgDA,WAOE"}
@@ -1,8 +1,6 @@
1
1
  import type { ReactElement, Ref } from "react";
2
2
  import type { TextFieldElementType, TextFieldProps } from "../TextField";
3
- export type ComboboxProps = TextFieldProps & {
4
- /** The list of options to display in the dropdown */
5
- options: ComboboxOptions | ((filter: string) => ComboboxOptions) | ((filter: string) => Promise<ComboboxOptions>);
3
+ export type ComboboxBaseProps = TextFieldProps & {
6
4
  /** An icon to display in TextField (left side) */
7
5
  icon?: ReactElement;
8
6
  /** The default value of the selected option */
@@ -10,6 +8,23 @@ export type ComboboxProps = TextFieldProps & {
10
8
  /** Callback when the selected option changes */
11
9
  onSelected?: ((value: string) => void) | undefined;
12
10
  };
11
+ export type ComboboxSyncProps = ComboboxBaseProps & {
12
+ /** The list of options to display in the dropdown */
13
+ options: ComboboxOptions;
14
+ asyncOptions?: never;
15
+ delay?: never;
16
+ minLength?: never;
17
+ };
18
+ export type ComboboxAsyncProps = ComboboxBaseProps & {
19
+ options?: never;
20
+ delay?: number;
21
+ minLength?: number;
22
+ /** A function that returns a list of options to display in the dropdown */
23
+ asyncOptions: ((inputValue: string) => ComboboxOptions) | ((inputValue: string, options?: {
24
+ signal?: AbortSignal;
25
+ }) => Promise<ComboboxOptions>);
26
+ };
27
+ export type ComboboxProps = ComboboxAsyncProps | ComboboxSyncProps;
13
28
  export type ComboboxOption = string | {
14
29
  label: string;
15
30
  value: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@simplybusiness/mobius",
3
3
  "license": "UNLICENSED",
4
- "version": "5.6.0",
4
+ "version": "5.7.0",
5
5
  "description": "Core library of Mobius react components",
6
6
  "repository": {
7
7
  "type": "git",
@@ -17,8 +17,15 @@ export const Combobox: ForwardedRefComponent<
17
17
  ComboboxProps,
18
18
  ComboboxElementType
19
19
  > = forwardRef((props: ComboboxProps, ref: ComboboxRef) => {
20
- const { defaultValue, options, onSelected, className, placeholder, icon } =
21
- props;
20
+ const {
21
+ defaultValue,
22
+ options,
23
+ asyncOptions,
24
+ onSelected,
25
+ className,
26
+ placeholder,
27
+ icon,
28
+ } = props;
22
29
 
23
30
  const fallbackRef = useRef<HTMLInputElement>(null);
24
31
  const [inputValue, setInputValue] = useState(defaultValue || "");
@@ -40,8 +47,8 @@ export const Combobox: ForwardedRefComponent<
40
47
 
41
48
  useEffect(() => {
42
49
  const fetchOptions = async () => {
43
- if (typeof options === "function") {
44
- const result = await options(inputValue);
50
+ if (asyncOptions) {
51
+ const result = await asyncOptions(inputValue);
45
52
  setFilteredOptions(result);
46
53
  } else {
47
54
  setFilteredOptions(filterOptions(options, inputValue));
@@ -49,7 +56,7 @@ export const Combobox: ForwardedRefComponent<
49
56
  };
50
57
 
51
58
  fetchOptions();
52
- }, [inputValue, options]);
59
+ }, [inputValue, options, asyncOptions]);
53
60
 
54
61
  const handleFocus = () => {
55
62
  if (blurTimeoutRef.current) {
@@ -1,12 +1,7 @@
1
1
  import type { ReactElement, Ref } from "react";
2
2
  import type { TextFieldElementType, TextFieldProps } from "../TextField";
3
3
 
4
- export type ComboboxProps = TextFieldProps & {
5
- /** The list of options to display in the dropdown */
6
- options:
7
- | ComboboxOptions
8
- | ((filter: string) => ComboboxOptions)
9
- | ((filter: string) => Promise<ComboboxOptions>);
4
+ export type ComboboxBaseProps = TextFieldProps & {
10
5
  /** An icon to display in TextField (left side) */
11
6
  icon?: ReactElement;
12
7
  /** The default value of the selected option */
@@ -15,6 +10,29 @@ export type ComboboxProps = TextFieldProps & {
15
10
  onSelected?: ((value: string) => void) | undefined;
16
11
  };
17
12
 
13
+ export type ComboboxSyncProps = ComboboxBaseProps & {
14
+ /** The list of options to display in the dropdown */
15
+ options: ComboboxOptions;
16
+ asyncOptions?: never;
17
+ delay?: never;
18
+ minLength?: never;
19
+ };
20
+
21
+ export type ComboboxAsyncProps = ComboboxBaseProps & {
22
+ options?: never;
23
+ delay?: number;
24
+ minLength?: number;
25
+ /** A function that returns a list of options to display in the dropdown */
26
+ asyncOptions:
27
+ | ((inputValue: string) => ComboboxOptions)
28
+ | ((
29
+ inputValue: string,
30
+ options?: { signal?: AbortSignal },
31
+ ) => Promise<ComboboxOptions>);
32
+ };
33
+
34
+ export type ComboboxProps = ComboboxAsyncProps | ComboboxSyncProps;
35
+
18
36
  export type ComboboxOption = string | { label: string; value: string };
19
37
 
20
38
  export type ComboboxOptionGroup = {
@@ -32,4 +32,4 @@ test("Doesn't add new publicly published packages without appsec approval", asyn
32
32
  expect(PUBLIC_PACKAGE_WHITELIST).toContain(packageJson.name);
33
33
  }
34
34
  }
35
- });
35
+ }, 30_000); // Set timeout to 30 seconds