diff --git a/.changeset/tender-rice-dance.md b/.changeset/tender-rice-dance.md new file mode 100644 index 00000000..cd786b98 --- /dev/null +++ b/.changeset/tender-rice-dance.md @@ -0,0 +1,5 @@ +--- +"@omnidev/sigil": patch +--- + +Allow customization of `Combobox` async data fetch preloading via `preloadItems` prop diff --git a/src/components/core/Combobox/Combobox.stories.tsx b/src/components/core/Combobox/Combobox.stories.tsx index ec51a2da..12ffc741 100644 --- a/src/components/core/Combobox/Combobox.stories.tsx +++ b/src/components/core/Combobox/Combobox.stories.tsx @@ -105,6 +105,46 @@ export const AsyncItems: StoryObj = { }, }; +/** + * Asynchronously load items without preloading them. To load items, the input field must be updated. + */ +export const AsyncItemsWithoutPreloading: StoryObj = { + render: () => { + const [items, setItems] = useState([]); + + useEffect(() => { + // simulate async data fetching + const fetchItems = async () => { + const asyncData: CollectionItem[] = await new Promise((resolve) => { + setTimeout(() => { + resolve( + fruitBasket.map(({ name, icon }, idx) => ({ + label: `${name} ${icon}`, + value: name, + disabled: idx === 2, + })), + ); + // simulate 1s delay + }, 1000); + }); + + setItems(asyncData); + }; + + void fetchItems(); + }, []); + + return ( + + ); + }, +}; + /** * The input field and group labels can be hidden by setting the `displayFieldLabel` and `displayGroupLabel` props to `false`, respectively. */ diff --git a/src/components/core/Combobox/Combobox.tsx b/src/components/core/Combobox/Combobox.tsx index 94ac5956..1f614d2f 100644 --- a/src/components/core/Combobox/Combobox.tsx +++ b/src/components/core/Combobox/Combobox.tsx @@ -1,5 +1,5 @@ import { Combobox as ArkCombobox } from "@ark-ui/react/combobox"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { BiCheck, BiExpandVertical, BiX } from "react-icons/bi"; import Button from "components/core/Button/Button"; @@ -116,13 +116,17 @@ export interface ComboboxTriggerProps extends AssignJSXStyleProps {} export interface ComboboxProps extends ComboboxRootProps { + /** Color palette. Defaults to "accent". */ colorPalette?: ColorPalette; - /** Whether to display the input field label. */ + /** Whether to display the input field label. Defaults to true. */ displayFieldLabel?: boolean; - /** Whether to display the group label contained in the dropdown. */ + /** Whether to display the group label contained in the dropdown. Defaults to true. */ displayGroupLabel?: boolean; - /** Whether to display the clear trigger button. */ + /** Whether to display the clear trigger button. Defaults to true. */ displayClearTrigger?: boolean; + /** Whether to preload items (useful for async data fetching). Defaults to true. If false, items will be loaded on input change. */ + preloadItems?: boolean; + /** Label. */ label: { // TODO calculate ID from singular (add dashes, lowercase, etc.) id: string; @@ -164,6 +168,7 @@ const Combobox = ({ displayFieldLabel = true, displayGroupLabel = true, displayClearTrigger = true, + preloadItems = true, label, onInputValueChange, labelProps, @@ -201,6 +206,10 @@ const Combobox = ({ onInputValueChange?.(evt); }; + useEffect(() => { + preloadItems && setFilteredItems(collection.items); + }, [collection.items, preloadItems]); + return (