periplo-ui 4.4.0 → 4.4.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/components/Combobox/Combobox.d.ts +26 -22
- package/dist/components/Combobox/Combobox.js +1 -1
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Combobox/hooks/index.d.ts +0 -2
- package/dist/components/Combobox/hooks/index.js +0 -2
- package/dist/components/Combobox/hooks/index.js.map +1 -1
- package/dist/components/Combobox/hooks/useDisplayValue.d.ts +1 -5
- package/dist/components/Combobox/hooks/useDisplayValue.js +8 -15
- package/dist/components/Combobox/hooks/useDisplayValue.js.map +1 -1
- package/dist/components/Combobox/useCombobox.d.ts +1 -2
- package/dist/components/Combobox/useCombobox.js +18 -25
- package/dist/components/Combobox/useCombobox.js.map +1 -1
- package/package.json +1 -1
- package/dist/components/Combobox/hooks/usePaginatedOptions.d.ts +0 -24
- package/dist/components/Combobox/hooks/usePaginatedOptions.js +0 -54
- package/dist/components/Combobox/hooks/usePaginatedOptions.js.map +0 -1
- package/dist/components/Combobox/hooks/useSelectedCache.d.ts +0 -4
- package/dist/components/Combobox/hooks/useSelectedCache.js +0 -17
- package/dist/components/Combobox/hooks/useSelectedCache.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
type ComboboxBaseProps<T> = {
|
|
2
2
|
/** Unique identifier for the combobox */
|
|
3
3
|
id?: string;
|
|
4
|
-
/** Array of options to display in the combobox */
|
|
5
|
-
options
|
|
4
|
+
/** Array of options to display in the combobox (static mode). */
|
|
5
|
+
options?: Array<T>;
|
|
6
6
|
/** Function to get the unique identifier from an option. */
|
|
7
7
|
getOptionValue: (option: T) => string;
|
|
8
8
|
/** Function to get the display text from an option. */
|
|
@@ -31,7 +31,7 @@ type ComboboxBaseProps<T> = {
|
|
|
31
31
|
loadingPlaceholder?: string;
|
|
32
32
|
/** Whether the combobox has an error */
|
|
33
33
|
error?: boolean | string;
|
|
34
|
-
/** Custom function to filter options based on search term */
|
|
34
|
+
/** Custom function to filter options based on search term (static mode only) */
|
|
35
35
|
filterOptions?: (options: Array<T>, searchTerm: string) => Array<T>;
|
|
36
36
|
/** Callback function executed when the clear button is clicked. When provided, an X button will appear on hover to clear the selection. */
|
|
37
37
|
onClear?: boolean | (() => void);
|
|
@@ -55,38 +55,42 @@ type ComboboxBaseProps<T> = {
|
|
|
55
55
|
onOpenAutoFocus?: boolean;
|
|
56
56
|
};
|
|
57
57
|
export type ComboboxSingleProps<T> = ComboboxBaseProps<T> & {
|
|
58
|
+
virtualized?: false;
|
|
58
59
|
multiple?: false;
|
|
59
60
|
value?: string;
|
|
60
61
|
onChange: (value: string) => void;
|
|
61
62
|
/** Custom render function for the selected value display. */
|
|
62
63
|
renderLabel?: (selectedOption: T) => React.ReactNode;
|
|
63
|
-
/**
|
|
64
|
-
* Async pagination function.
|
|
65
|
-
* Note: Multiple selection is not supported with virtualization.
|
|
66
|
-
*/
|
|
67
|
-
fetchPage?: (params: {
|
|
68
|
-
page: number;
|
|
69
|
-
search?: string;
|
|
70
|
-
}) => Promise<{
|
|
71
|
-
items: Array<T>;
|
|
72
|
-
hasNextPage: boolean;
|
|
73
|
-
nextPage: number;
|
|
74
|
-
}>;
|
|
75
|
-
/** Prefetch the first page on mount (virtualized only), so data is ready before opening. */
|
|
76
|
-
prefetch?: boolean;
|
|
77
64
|
};
|
|
78
65
|
export type ComboboxMultipleProps<T> = ComboboxBaseProps<T> & {
|
|
66
|
+
virtualized?: false;
|
|
79
67
|
multiple: true;
|
|
80
68
|
value?: Array<string>;
|
|
81
69
|
onChange: (value: Array<string>) => void;
|
|
82
70
|
/** Custom render function for the selected value(s) display. */
|
|
83
71
|
renderLabel?: (selectedOptions: Array<T>, onRemove: (value: string) => void) => React.ReactNode;
|
|
84
|
-
/** fetchPage is not allowed with multiple selection */
|
|
85
|
-
fetchPage?: never;
|
|
86
|
-
/** prefetch is not allowed with multiple selection */
|
|
87
|
-
prefetch?: never;
|
|
88
72
|
};
|
|
89
|
-
export type
|
|
73
|
+
export type ComboboxVirtualizedProps<T> = ComboboxBaseProps<T> & {
|
|
74
|
+
virtualized: true;
|
|
75
|
+
multiple?: false;
|
|
76
|
+
value?: string;
|
|
77
|
+
onChange: (value: string) => void;
|
|
78
|
+
/** Custom render function for the selected value display. */
|
|
79
|
+
renderLabel?: (selectedOption: T) => React.ReactNode;
|
|
80
|
+
/** The accumulated, flattened list of loaded items. */
|
|
81
|
+
items: Array<T>;
|
|
82
|
+
/** The resolved selected item, fetched independently of the list. Used for the trigger label. */
|
|
83
|
+
selectedItem?: T;
|
|
84
|
+
/** Whether more pages can be loaded. */
|
|
85
|
+
hasNextPage: boolean;
|
|
86
|
+
/** Whether the next page is currently being fetched. */
|
|
87
|
+
isFetchingNextPage: boolean;
|
|
88
|
+
/** Request the next page (triggered near the end of the list). */
|
|
89
|
+
onLoadMore: () => void;
|
|
90
|
+
/** Emitted (debounced) when the search term changes. The consumer refetches. */
|
|
91
|
+
onSearchChange: (search: string) => void;
|
|
92
|
+
};
|
|
93
|
+
export type ComboboxProps<T> = ComboboxSingleProps<T> | ComboboxMultipleProps<T> | ComboboxVirtualizedProps<T>;
|
|
90
94
|
/**
|
|
91
95
|
* A searchable combobox component with support for custom rendering, keyboard navigation, and search filtering.
|
|
92
96
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Combobox.js","sources":["../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { Command, CommandInput } from '../Command'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\n\nimport { ComboboxTrigger } from './ComboboxTrigger'\nimport { StaticComboboxList } from './StaticComboboxList'\nimport { useCombobox } from './useCombobox'\nimport { VirtualizedComboboxList } from './VirtualizedComboboxList'\n\ntype ComboboxBaseProps<T> = {\n /** Unique identifier for the combobox */\n id?: string\n /** Array of options to display in the combobox */\n options: Array<T>\n /** Function to get the unique identifier from an option. */\n getOptionValue: (option: T) => string\n /** Function to get the display text from an option. */\n getOptionLabel: (option: T) => string\n /** Custom render function for options. If not provided, defaults to showing a checkmark and label */\n renderOption?: (option: T, isSelected: boolean) => React.ReactNode\n /** Placeholder text shown when no option is selected */\n placeholder?: string\n /** Placeholder text for the search input field */\n searchPlaceholder?: string\n /** Message shown when no options match the search query */\n emptyMessage?: string\n /** Additional CSS classes to apply to the combobox trigger */\n className?: string\n /** Additional CSS classes to apply to the popover content */\n contentClassName?: string\n /** Whether the combobox is disabled */\n disabled?: boolean\n /** Maximum height of the options list. Can be any valid CSS height value */\n maxHeight?: string | number\n /** Whether to close the dropdown when an option is selected. Defaults to `true` for single select and `false` for multi-select. */\n closeOnSelect?: boolean\n /** Whether the combobox is in a loading state */\n loading?: boolean\n /** Message to show when in loading state */\n loadingPlaceholder?: string\n /** Whether the combobox has an error */\n error?: boolean | string\n /** Custom function to filter options based on search term */\n filterOptions?: (options: Array<T>, searchTerm: string) => Array<T>\n /** Callback function executed when the clear button is clicked. When provided, an X button will appear on hover to clear the selection. */\n onClear?: boolean | (() => void)\n /** Whether the selection can be cleared */\n clearable?: boolean\n /** Whether the combobox is inside a modal */\n modal?: boolean\n /** Placeholder text for the selected multiple options */\n selectedMultiplePlaceholder?: string\n /** Placeholder text for the multiple options */\n multipleOptionsPlaceholder?: string\n /** Special options that appear at the top with their own title. When selected, the combobox switches to single-select mode. */\n specialOptions?: Array<T>\n /** Title for the special options group */\n specialOptionsTitle?: string\n /** Container element to position the combobox relative to. */\n container?: HTMLElement\n /** Alignment of the dropdown relative to the trigger. Defaults to 'center'. */\n align?: 'start' | 'center' | 'end'\n /** Auto-focus the search input when the dropdown opens. */\n onOpenAutoFocus?: boolean\n}\n\nexport type ComboboxSingleProps<T> = ComboboxBaseProps<T> & {\n multiple?: false\n value?: string\n onChange: (value: string) => void\n /** Custom render function for the selected value display. */\n renderLabel?: (selectedOption: T) => React.ReactNode\n /**\n * Async pagination function.\n * Note: Multiple selection is not supported with virtualization.\n */\n fetchPage?: (params: {\n page: number\n search?: string\n }) => Promise<{ items: Array<T>; hasNextPage: boolean; nextPage: number }>\n /** Prefetch the first page on mount (virtualized only), so data is ready before opening. */\n prefetch?: boolean\n}\n\nexport type ComboboxMultipleProps<T> = ComboboxBaseProps<T> & {\n multiple: true\n value?: Array<string>\n onChange: (value: Array<string>) => void\n /** Custom render function for the selected value(s) display. */\n renderLabel?: (selectedOptions: Array<T>, onRemove: (value: string) => void) => React.ReactNode\n /** fetchPage is not allowed with multiple selection */\n fetchPage?: never\n /** prefetch is not allowed with multiple selection */\n prefetch?: never\n}\n\nexport type ComboboxProps<T> = ComboboxSingleProps<T> | ComboboxMultipleProps<T>\n\n/**\n * A searchable combobox component with support for custom rendering, keyboard navigation, and search filtering.\n *\n * @example Basic usage\n * ```tsx\n * <Combobox<User>\n * options={users}\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * />\n * ```\n */\nexport const Combobox = <T extends object>(props: ComboboxProps<T>) => {\n const {\n id,\n options,\n getOptionValue,\n getOptionLabel,\n searchPlaceholder = 'Search...',\n emptyMessage = 'No results found.',\n className = 'w-60',\n contentClassName,\n disabled = false,\n maxHeight = '300px',\n renderOption,\n loading = false,\n loadingPlaceholder = 'Cargando...',\n error = false,\n multiple,\n onClear,\n modal = false,\n selectedMultiplePlaceholder = 'Selected',\n multipleOptionsPlaceholder = 'Options',\n specialOptions,\n specialOptionsTitle,\n container,\n align,\n onOpenAutoFocus = false,\n } = props\n\n const searchInputRef = useRef<HTMLInputElement>(null)\n\n const normalizedMaxHeight = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight\n const boundedListMaxHeight = `min(${normalizedMaxHeight}, max(120px, calc(var(--radix-popover-content-available-height, 100dvh) - 68px)))`\n\n const {\n open,\n setOpen,\n searchTerm,\n setSearchTerm,\n setIsHovered,\n hasNextPage,\n loadingMore,\n isVirtualized,\n filteredOptions,\n displayValue,\n hasValue,\n showClearButton,\n handleSelect,\n handleClear,\n loadNextPage,\n } = useCombobox(props)\n\n useEffect(() => {\n if (!open || !onOpenAutoFocus) return\n const timeoutId = globalThis.setTimeout(() => searchInputRef.current?.focus(), 0)\n return () => globalThis.clearTimeout(timeoutId)\n }, [open, onOpenAutoFocus])\n\n const hasMultipleRenderLabel = !!(multiple && 'renderLabel' in props && props.renderLabel)\n\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <PopoverRoot open={open} onOpenChange={setOpen} modal={modal}>\n <PopoverTrigger\n asChild\n onPointerDown={(event) => {\n event.stopPropagation()\n if (open) {\n setOpen(false)\n event.preventDefault()\n } else {\n setOpen(true)\n }\n }}\n onClick={(event) => {\n event.preventDefault()\n event.stopPropagation()\n }}\n >\n <ComboboxTrigger\n id={id}\n disabled={disabled}\n open={open}\n error={error}\n hasValue={hasValue}\n showClearButton={showClearButton}\n showClearIcon={!!onClear}\n isMultilineLabel={hasMultipleRenderLabel}\n displayValue={displayValue}\n className={className}\n onHoverChange={setIsHovered}\n onClear={handleClear}\n />\n </PopoverTrigger>\n <PopoverContent\n className={cn('overflow-hidden p-0', contentClassName)}\n container={container}\n side=\"bottom\"\n align={align}\n onOpenAutoFocus={onOpenAutoFocus ? (event) => event.preventDefault() : undefined}\n >\n <Command shouldFilter={false}>\n <CommandInput\n ref={searchInputRef}\n placeholder={searchPlaceholder}\n disabled={loading}\n value={searchTerm}\n onValueChange={setSearchTerm}\n />\n {isVirtualized ? (\n <VirtualizedComboboxList\n localOptions={filteredOptions}\n loading={loading}\n loadingPlaceholder={loadingPlaceholder}\n emptyMessage={emptyMessage}\n value={props.value as string}\n getOptionValue={getOptionValue}\n getOptionLabel={getOptionLabel}\n handleSelect={handleSelect}\n renderOption={renderOption}\n maxHeight={boundedListMaxHeight}\n hasNextPage={hasNextPage}\n loadingMore={loadingMore}\n onLoadMore={loadNextPage}\n />\n ) : (\n <StaticComboboxList\n filteredOptions={filteredOptions}\n loading={loading}\n loadingPlaceholder={loadingPlaceholder}\n emptyMessage={emptyMessage}\n multiple={!!multiple}\n value={props.value}\n getOptionValue={getOptionValue}\n getOptionLabel={getOptionLabel}\n handleSelect={handleSelect}\n renderOption={renderOption}\n maxHeight={boundedListMaxHeight}\n selectedMultiplePlaceholder={selectedMultiplePlaceholder}\n multipleOptionsPlaceholder={multipleOptionsPlaceholder}\n options={options}\n specialOptions={specialOptions}\n specialOptionsTitle={specialOptionsTitle}\n />\n )}\n </Command>\n </PopoverContent>\n </PopoverRoot>\n {typeof error === 'string' && <span className=\"text-error-500 text-sm\">{error}</span>}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Combobox.js","sources":["../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { Command, CommandInput } from '../Command'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\n\nimport { ComboboxTrigger } from './ComboboxTrigger'\nimport { StaticComboboxList } from './StaticComboboxList'\nimport { useCombobox } from './useCombobox'\nimport { VirtualizedComboboxList } from './VirtualizedComboboxList'\n\ntype ComboboxBaseProps<T> = {\n /** Unique identifier for the combobox */\n id?: string\n /** Array of options to display in the combobox (static mode). */\n options?: Array<T>\n /** Function to get the unique identifier from an option. */\n getOptionValue: (option: T) => string\n /** Function to get the display text from an option. */\n getOptionLabel: (option: T) => string\n /** Custom render function for options. If not provided, defaults to showing a checkmark and label */\n renderOption?: (option: T, isSelected: boolean) => React.ReactNode\n /** Placeholder text shown when no option is selected */\n placeholder?: string\n /** Placeholder text for the search input field */\n searchPlaceholder?: string\n /** Message shown when no options match the search query */\n emptyMessage?: string\n /** Additional CSS classes to apply to the combobox trigger */\n className?: string\n /** Additional CSS classes to apply to the popover content */\n contentClassName?: string\n /** Whether the combobox is disabled */\n disabled?: boolean\n /** Maximum height of the options list. Can be any valid CSS height value */\n maxHeight?: string | number\n /** Whether to close the dropdown when an option is selected. Defaults to `true` for single select and `false` for multi-select. */\n closeOnSelect?: boolean\n /** Whether the combobox is in a loading state */\n loading?: boolean\n /** Message to show when in loading state */\n loadingPlaceholder?: string\n /** Whether the combobox has an error */\n error?: boolean | string\n /** Custom function to filter options based on search term (static mode only) */\n filterOptions?: (options: Array<T>, searchTerm: string) => Array<T>\n /** Callback function executed when the clear button is clicked. When provided, an X button will appear on hover to clear the selection. */\n onClear?: boolean | (() => void)\n /** Whether the selection can be cleared */\n clearable?: boolean\n /** Whether the combobox is inside a modal */\n modal?: boolean\n /** Placeholder text for the selected multiple options */\n selectedMultiplePlaceholder?: string\n /** Placeholder text for the multiple options */\n multipleOptionsPlaceholder?: string\n /** Special options that appear at the top with their own title. When selected, the combobox switches to single-select mode. */\n specialOptions?: Array<T>\n /** Title for the special options group */\n specialOptionsTitle?: string\n /** Container element to position the combobox relative to. */\n container?: HTMLElement\n /** Alignment of the dropdown relative to the trigger. Defaults to 'center'. */\n align?: 'start' | 'center' | 'end'\n /** Auto-focus the search input when the dropdown opens. */\n onOpenAutoFocus?: boolean\n}\n\nexport type ComboboxSingleProps<T> = ComboboxBaseProps<T> & {\n virtualized?: false\n multiple?: false\n value?: string\n onChange: (value: string) => void\n /** Custom render function for the selected value display. */\n renderLabel?: (selectedOption: T) => React.ReactNode\n}\n\nexport type ComboboxMultipleProps<T> = ComboboxBaseProps<T> & {\n virtualized?: false\n multiple: true\n value?: Array<string>\n onChange: (value: Array<string>) => void\n /** Custom render function for the selected value(s) display. */\n renderLabel?: (selectedOptions: Array<T>, onRemove: (value: string) => void) => React.ReactNode\n}\n\nexport type ComboboxVirtualizedProps<T> = ComboboxBaseProps<T> & {\n virtualized: true\n multiple?: false\n value?: string\n onChange: (value: string) => void\n /** Custom render function for the selected value display. */\n renderLabel?: (selectedOption: T) => React.ReactNode\n /** The accumulated, flattened list of loaded items. */\n items: Array<T>\n /** The resolved selected item, fetched independently of the list. Used for the trigger label. */\n selectedItem?: T\n /** Whether more pages can be loaded. */\n hasNextPage: boolean\n /** Whether the next page is currently being fetched. */\n isFetchingNextPage: boolean\n /** Request the next page (triggered near the end of the list). */\n onLoadMore: () => void\n /** Emitted (debounced) when the search term changes. The consumer refetches. */\n onSearchChange: (search: string) => void\n}\n\nexport type ComboboxProps<T> = ComboboxSingleProps<T> | ComboboxMultipleProps<T> | ComboboxVirtualizedProps<T>\n\n/**\n * A searchable combobox component with support for custom rendering, keyboard navigation, and search filtering.\n *\n * @example Basic usage\n * ```tsx\n * <Combobox<User>\n * options={users}\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * />\n * ```\n */\nexport const Combobox = <T extends object>(props: ComboboxProps<T>) => {\n const {\n id,\n options = [],\n getOptionValue,\n getOptionLabel,\n searchPlaceholder = 'Search...',\n emptyMessage = 'No results found.',\n className = 'w-60',\n contentClassName,\n disabled = false,\n maxHeight = '300px',\n renderOption,\n loading = false,\n loadingPlaceholder = 'Cargando...',\n error = false,\n multiple,\n onClear,\n modal = false,\n selectedMultiplePlaceholder = 'Selected',\n multipleOptionsPlaceholder = 'Options',\n specialOptions,\n specialOptionsTitle,\n container,\n align,\n onOpenAutoFocus = false,\n } = props\n\n const searchInputRef = useRef<HTMLInputElement>(null)\n\n const normalizedMaxHeight = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight\n const boundedListMaxHeight = `min(${normalizedMaxHeight}, max(120px, calc(var(--radix-popover-content-available-height, 100dvh) - 68px)))`\n\n const {\n open,\n setOpen,\n searchTerm,\n setSearchTerm,\n setIsHovered,\n hasNextPage,\n loadingMore,\n isVirtualized,\n filteredOptions,\n displayValue,\n hasValue,\n showClearButton,\n handleSelect,\n handleClear,\n loadNextPage,\n } = useCombobox(props)\n\n useEffect(() => {\n if (!open || !onOpenAutoFocus) return\n const timeoutId = globalThis.setTimeout(() => searchInputRef.current?.focus(), 0)\n return () => globalThis.clearTimeout(timeoutId)\n }, [open, onOpenAutoFocus])\n\n const hasMultipleRenderLabel = !!(multiple && 'renderLabel' in props && props.renderLabel)\n\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <PopoverRoot open={open} onOpenChange={setOpen} modal={modal}>\n <PopoverTrigger\n asChild\n onPointerDown={(event) => {\n event.stopPropagation()\n if (open) {\n setOpen(false)\n event.preventDefault()\n } else {\n setOpen(true)\n }\n }}\n onClick={(event) => {\n event.preventDefault()\n event.stopPropagation()\n }}\n >\n <ComboboxTrigger\n id={id}\n disabled={disabled}\n open={open}\n error={error}\n hasValue={hasValue}\n showClearButton={showClearButton}\n showClearIcon={!!onClear}\n isMultilineLabel={hasMultipleRenderLabel}\n displayValue={displayValue}\n className={className}\n onHoverChange={setIsHovered}\n onClear={handleClear}\n />\n </PopoverTrigger>\n <PopoverContent\n className={cn('overflow-hidden p-0', contentClassName)}\n container={container}\n side=\"bottom\"\n align={align}\n onOpenAutoFocus={onOpenAutoFocus ? (event) => event.preventDefault() : undefined}\n >\n <Command shouldFilter={false}>\n <CommandInput\n ref={searchInputRef}\n placeholder={searchPlaceholder}\n disabled={loading}\n value={searchTerm}\n onValueChange={setSearchTerm}\n />\n {isVirtualized ? (\n <VirtualizedComboboxList\n localOptions={filteredOptions}\n loading={loading}\n loadingPlaceholder={loadingPlaceholder}\n emptyMessage={emptyMessage}\n value={props.value as string}\n getOptionValue={getOptionValue}\n getOptionLabel={getOptionLabel}\n handleSelect={handleSelect}\n renderOption={renderOption}\n maxHeight={boundedListMaxHeight}\n hasNextPage={hasNextPage}\n loadingMore={loadingMore}\n onLoadMore={loadNextPage}\n />\n ) : (\n <StaticComboboxList\n filteredOptions={filteredOptions}\n loading={loading}\n loadingPlaceholder={loadingPlaceholder}\n emptyMessage={emptyMessage}\n multiple={!!multiple}\n value={props.value}\n getOptionValue={getOptionValue}\n getOptionLabel={getOptionLabel}\n handleSelect={handleSelect}\n renderOption={renderOption}\n maxHeight={boundedListMaxHeight}\n selectedMultiplePlaceholder={selectedMultiplePlaceholder}\n multipleOptionsPlaceholder={multipleOptionsPlaceholder}\n options={options}\n specialOptions={specialOptions}\n specialOptionsTitle={specialOptionsTitle}\n />\n )}\n </Command>\n </PopoverContent>\n </PopoverRoot>\n {typeof error === 'string' && <span className=\"text-error-500 text-sm\">{error}</span>}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -2,5 +2,3 @@ export { useComboboxOpenState } from './useComboboxOpenState';
|
|
|
2
2
|
export { useComboboxSelection } from './useComboboxSelection';
|
|
3
3
|
export { useDebouncedState } from './useDebouncedState';
|
|
4
4
|
export { useDisplayValue } from './useDisplayValue';
|
|
5
|
-
export { usePaginatedOptions } from './usePaginatedOptions';
|
|
6
|
-
export { useSelectedCache } from './useSelectedCache';
|
|
@@ -2,6 +2,4 @@ export { useComboboxOpenState } from './useComboboxOpenState.js';
|
|
|
2
2
|
export { useComboboxSelection } from './useComboboxSelection.js';
|
|
3
3
|
export { useDebouncedState } from './useDebouncedState.js';
|
|
4
4
|
export { useDisplayValue } from './useDisplayValue.js';
|
|
5
|
-
export { usePaginatedOptions } from './usePaginatedOptions.js';
|
|
6
|
-
export { useSelectedCache } from './useSelectedCache.js';
|
|
7
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { ComboboxProps } from '../Combobox';
|
|
2
2
|
type UseDisplayValueParams<T extends object> = {
|
|
3
3
|
props: ComboboxProps<T>;
|
|
4
|
-
localOptions: Array<T>;
|
|
5
|
-
isVirtualized: boolean;
|
|
6
|
-
resolve: (value: string) => T | undefined;
|
|
7
|
-
recordOptions: (items: Iterable<T>) => void;
|
|
8
4
|
handleRemove: (value: string) => void;
|
|
9
5
|
};
|
|
10
|
-
export declare function useDisplayValue<T extends object>({ props,
|
|
6
|
+
export declare function useDisplayValue<T extends object>({ props, handleRemove }: UseDisplayValueParams<T>): import('react').ReactNode;
|
|
11
7
|
export {};
|
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
|
|
3
|
-
function useDisplayValue({
|
|
4
|
-
props
|
|
5
|
-
localOptions,
|
|
6
|
-
isVirtualized,
|
|
7
|
-
resolve,
|
|
8
|
-
recordOptions,
|
|
9
|
-
handleRemove
|
|
10
|
-
}) {
|
|
11
|
-
const { options, getOptionValue, getOptionLabel, placeholder = "Select...", multiple, specialOptions } = props;
|
|
3
|
+
function useDisplayValue({ props, handleRemove }) {
|
|
4
|
+
const { getOptionValue, getOptionLabel, placeholder = "Select...", multiple, specialOptions } = props;
|
|
12
5
|
return useMemo(() => {
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
const lookup = (val) => all.find((option) => getOptionValue(option) === val)
|
|
6
|
+
const isVirtualized = props.virtualized === true;
|
|
7
|
+
const options = isVirtualized ? props.items : props.options ?? [];
|
|
8
|
+
const all = specialOptions ? [...specialOptions, ...options] : options;
|
|
9
|
+
const lookup = (val) => all.find((option) => getOptionValue(option) === val);
|
|
17
10
|
if (multiple) {
|
|
18
11
|
const { renderLabel: renderLabel2 } = props;
|
|
19
12
|
const value2 = Array.isArray(props.value) ? props.value : [];
|
|
@@ -22,10 +15,10 @@ function useDisplayValue({
|
|
|
22
15
|
return renderLabel2 ? renderLabel2(selected2, handleRemove) : selected2.map(getOptionLabel).join(", ");
|
|
23
16
|
}
|
|
24
17
|
const { value, renderLabel } = props;
|
|
25
|
-
const selected = value ? lookup(value) : void 0;
|
|
18
|
+
const selected = value ? lookup(value) ?? (isVirtualized ? props.selectedItem : void 0) : void 0;
|
|
26
19
|
if (renderLabel && selected) return renderLabel(selected);
|
|
27
20
|
return selected ? getOptionLabel(selected) : placeholder;
|
|
28
|
-
}, [props,
|
|
21
|
+
}, [props, getOptionLabel, getOptionValue, placeholder, multiple, specialOptions]);
|
|
29
22
|
}
|
|
30
23
|
|
|
31
24
|
export { useDisplayValue };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDisplayValue.js","sources":["../../../../src/components/Combobox/hooks/useDisplayValue.ts"],"sourcesContent":["import { useMemo } from 'react'\n\nimport type { ComboboxProps } from '../Combobox'\n\ntype UseDisplayValueParams<T extends object> = {\n props: ComboboxProps<T>\n
|
|
1
|
+
{"version":3,"file":"useDisplayValue.js","sources":["../../../../src/components/Combobox/hooks/useDisplayValue.ts"],"sourcesContent":["import { useMemo } from 'react'\n\nimport type { ComboboxProps } from '../Combobox'\n\ntype UseDisplayValueParams<T extends object> = {\n props: ComboboxProps<T>\n handleRemove: (value: string) => void\n}\n\nexport function useDisplayValue<T extends object>({ props, handleRemove }: UseDisplayValueParams<T>) {\n const { getOptionValue, getOptionLabel, placeholder = 'Select...', multiple, specialOptions } = props\n\n return useMemo(() => {\n const isVirtualized = props.virtualized === true\n const options = isVirtualized ? props.items : (props.options ?? [])\n const all = specialOptions ? [...specialOptions, ...options] : options\n\n const lookup = (val: string) => all.find((option) => getOptionValue(option) === val)\n\n if (multiple) {\n const { renderLabel } = props\n const value = Array.isArray(props.value) ? props.value : []\n if (value.length === 0) return placeholder\n\n const selected = value.map(lookup).filter((option): option is T => option !== undefined)\n\n return renderLabel ? renderLabel(selected, handleRemove) : selected.map(getOptionLabel).join(', ')\n }\n\n const { value, renderLabel } = props\n const selected = value ? (lookup(value) ?? (isVirtualized ? props.selectedItem : undefined)) : undefined\n if (renderLabel && selected) return renderLabel(selected)\n return selected ? getOptionLabel(selected) : placeholder\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [props, getOptionLabel, getOptionValue, placeholder, multiple, specialOptions])\n}\n"],"names":["renderLabel","value","selected"],"mappings":";;AASO,SAAS,eAAA,CAAkC,EAAE,KAAA,EAAO,YAAA,EAAa,EAA6B;AACnG,EAAA,MAAM,EAAE,cAAA,EAAgB,cAAA,EAAgB,cAAc,WAAA,EAAa,QAAA,EAAU,gBAAe,GAAI,KAAA;AAEhG,EAAA,OAAO,QAAQ,MAAM;AACnB,IAAA,MAAM,aAAA,GAAgB,MAAM,WAAA,KAAgB,IAAA;AAC5C,IAAA,MAAM,UAAU,aAAA,GAAgB,KAAA,CAAM,KAAA,GAAS,KAAA,CAAM,WAAW,EAAC;AACjE,IAAA,MAAM,MAAM,cAAA,GAAiB,CAAC,GAAG,cAAA,EAAgB,GAAG,OAAO,CAAA,GAAI,OAAA;AAE/D,IAAA,MAAM,MAAA,GAAS,CAAC,GAAA,KAAgB,GAAA,CAAI,IAAA,CAAK,CAAC,MAAA,KAAW,cAAA,CAAe,MAAM,CAAA,KAAM,GAAG,CAAA;AAEnF,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,EAAE,WAAA,EAAAA,YAAAA,EAAY,GAAI,KAAA;AACxB,MAAA,MAAMC,MAAAA,GAAQ,MAAM,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAA,GAAI,KAAA,CAAM,QAAQ,EAAC;AAC1D,MAAA,IAAIA,MAAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,WAAA;AAE/B,MAAA,MAAMC,SAAAA,GAAWD,OAAM,GAAA,CAAI,MAAM,EAAE,MAAA,CAAO,CAAC,MAAA,KAAwB,MAAA,KAAW,MAAS,CAAA;AAEvF,MAAA,OAAOD,YAAAA,GAAcA,YAAAA,CAAYE,SAAAA,EAAU,YAAY,CAAA,GAAIA,UAAS,GAAA,CAAI,cAAc,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AAAA,IACnG;AAEA,IAAA,MAAM,EAAE,KAAA,EAAO,WAAA,EAAY,GAAI,KAAA;AAC/B,IAAA,MAAM,QAAA,GAAW,QAAS,MAAA,CAAO,KAAK,MAAM,aAAA,GAAgB,KAAA,CAAM,eAAe,MAAA,CAAA,GAAc,MAAA;AAC/F,IAAA,IAAI,WAAA,IAAe,QAAA,EAAU,OAAO,WAAA,CAAY,QAAQ,CAAA;AACxD,IAAA,OAAO,QAAA,GAAW,cAAA,CAAe,QAAQ,CAAA,GAAI,WAAA;AAAA,EAE/C,CAAA,EAAG,CAAC,KAAA,EAAO,cAAA,EAAgB,gBAAgB,WAAA,EAAa,QAAA,EAAU,cAAc,CAAC,CAAA;AACnF;;;;"}
|
|
@@ -6,7 +6,6 @@ export declare const useCombobox: <T extends object>(props: ComboboxProps<T>) =>
|
|
|
6
6
|
setSearchTerm: (next: string) => void;
|
|
7
7
|
isHovered: boolean;
|
|
8
8
|
setIsHovered: import('react').Dispatch<import('react').SetStateAction<boolean>>;
|
|
9
|
-
localOptions: T[];
|
|
10
9
|
hasNextPage: boolean;
|
|
11
10
|
loadingMore: boolean;
|
|
12
11
|
isVirtualized: boolean;
|
|
@@ -17,5 +16,5 @@ export declare const useCombobox: <T extends object>(props: ComboboxProps<T>) =>
|
|
|
17
16
|
handleSelect: (currentValue: string) => void;
|
|
18
17
|
handleRemove: (valueToRemove: string) => void;
|
|
19
18
|
handleClear: (event: React.MouseEvent) => void;
|
|
20
|
-
loadNextPage: () =>
|
|
19
|
+
loadNextPage: () => void;
|
|
21
20
|
};
|
|
@@ -1,40 +1,34 @@
|
|
|
1
|
-
import { useMemo, useState } from 'react';
|
|
1
|
+
import { useRef, useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import { useComboboxOpenState } from './hooks/useComboboxOpenState.js';
|
|
3
3
|
import { useComboboxSelection } from './hooks/useComboboxSelection.js';
|
|
4
4
|
import { useDisplayValue } from './hooks/useDisplayValue.js';
|
|
5
|
-
import { usePaginatedOptions } from './hooks/usePaginatedOptions.js';
|
|
6
|
-
import { useSelectedCache } from './hooks/useSelectedCache.js';
|
|
7
5
|
|
|
8
6
|
const useCombobox = (props) => {
|
|
9
|
-
const {
|
|
7
|
+
const { getOptionLabel, filterOptions, onClear, clearable = true } = props;
|
|
8
|
+
const options = props.options ?? [];
|
|
9
|
+
const isVirtualized = props.virtualized === true;
|
|
10
10
|
const { open, setOpen, searchTerm, debouncedSearchTerm, setSearchTerm } = useComboboxOpenState();
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
debouncedSearchTerm
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
const onSearchChangeRef = useRef(void 0);
|
|
12
|
+
onSearchChangeRef.current = isVirtualized ? props.onSearchChange : void 0;
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!isVirtualized) return;
|
|
15
|
+
onSearchChangeRef.current?.(debouncedSearchTerm);
|
|
16
|
+
}, [debouncedSearchTerm, isVirtualized]);
|
|
17
|
+
const items = isVirtualized ? props.items : [];
|
|
18
|
+
const hasNextPage = isVirtualized ? props.hasNextPage : false;
|
|
19
|
+
const loadingMore = isVirtualized ? props.isFetchingNextPage : false;
|
|
20
|
+
const loadNextPage = isVirtualized ? props.onLoadMore : () => {
|
|
21
|
+
};
|
|
21
22
|
const filteredOptions = useMemo(() => {
|
|
22
|
-
if (isVirtualized) return
|
|
23
|
+
if (isVirtualized) return items;
|
|
23
24
|
if (!filterOptions) {
|
|
24
25
|
return options.filter((option) => getOptionLabel(option).toLowerCase().includes(searchTerm.toLowerCase()));
|
|
25
26
|
}
|
|
26
27
|
return searchTerm ? filterOptions(options, searchTerm) : options;
|
|
27
|
-
}, [isVirtualized,
|
|
28
|
+
}, [isVirtualized, items, filterOptions, options, searchTerm, getOptionLabel]);
|
|
28
29
|
const { handleSelect, handleRemove, handleClear, hasValue } = useComboboxSelection(props, setOpen);
|
|
29
30
|
const [isHovered, setIsHovered] = useState(false);
|
|
30
|
-
const displayValue = useDisplayValue({
|
|
31
|
-
props,
|
|
32
|
-
localOptions,
|
|
33
|
-
isVirtualized,
|
|
34
|
-
resolve: cache.resolve,
|
|
35
|
-
recordOptions: cache.record,
|
|
36
|
-
handleRemove
|
|
37
|
-
});
|
|
31
|
+
const displayValue = useDisplayValue({ props, handleRemove });
|
|
38
32
|
const showClearButton = onClear && hasValue && isHovered && clearable;
|
|
39
33
|
return {
|
|
40
34
|
open,
|
|
@@ -43,7 +37,6 @@ const useCombobox = (props) => {
|
|
|
43
37
|
setSearchTerm,
|
|
44
38
|
isHovered,
|
|
45
39
|
setIsHovered,
|
|
46
|
-
localOptions,
|
|
47
40
|
hasNextPage,
|
|
48
41
|
loadingMore,
|
|
49
42
|
isVirtualized,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCombobox.js","sources":["../../../src/components/Combobox/useCombobox.ts"],"sourcesContent":["import { useMemo, useState } from 'react'\n\nimport type { ComboboxProps } from './Combobox'\nimport {
|
|
1
|
+
{"version":3,"file":"useCombobox.js","sources":["../../../src/components/Combobox/useCombobox.ts"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react'\n\nimport type { ComboboxProps } from './Combobox'\nimport { useComboboxOpenState, useComboboxSelection, useDisplayValue } from './hooks'\n\nexport const useCombobox = <T extends object>(props: ComboboxProps<T>) => {\n const { getOptionLabel, filterOptions, onClear, clearable = true } = props\n const options = props.options ?? []\n const isVirtualized = props.virtualized === true\n\n const { open, setOpen, searchTerm, debouncedSearchTerm, setSearchTerm } = useComboboxOpenState()\n\n const onSearchChangeRef = useRef<((search: string) => void) | undefined>(undefined)\n onSearchChangeRef.current = isVirtualized ? props.onSearchChange : undefined\n useEffect(() => {\n if (!isVirtualized) return\n onSearchChangeRef.current?.(debouncedSearchTerm)\n }, [debouncedSearchTerm, isVirtualized])\n\n const items = isVirtualized ? props.items : []\n const hasNextPage = isVirtualized ? props.hasNextPage : false\n const loadingMore = isVirtualized ? props.isFetchingNextPage : false\n const loadNextPage = isVirtualized ? props.onLoadMore : () => {}\n\n const filteredOptions = useMemo(() => {\n if (isVirtualized) return items\n\n if (!filterOptions) {\n return options.filter((option) => getOptionLabel(option).toLowerCase().includes(searchTerm.toLowerCase()))\n }\n\n return searchTerm ? filterOptions(options, searchTerm) : options\n }, [isVirtualized, items, filterOptions, options, searchTerm, getOptionLabel])\n\n const { handleSelect, handleRemove, handleClear, hasValue } = useComboboxSelection(props, setOpen)\n\n const [isHovered, setIsHovered] = useState(false)\n\n const displayValue = useDisplayValue<T>({ props, handleRemove })\n\n const showClearButton = onClear && hasValue && isHovered && clearable\n\n return {\n open,\n setOpen,\n searchTerm,\n setSearchTerm,\n isHovered,\n setIsHovered,\n hasNextPage,\n loadingMore,\n isVirtualized,\n filteredOptions,\n displayValue,\n hasValue,\n showClearButton,\n handleSelect,\n handleRemove,\n handleClear,\n loadNextPage,\n }\n}\n"],"names":[],"mappings":";;;;;AAKO,MAAM,WAAA,GAAc,CAAmB,KAAA,KAA4B;AACxE,EAAA,MAAM,EAAE,cAAA,EAAgB,aAAA,EAAe,OAAA,EAAS,SAAA,GAAY,MAAK,GAAI,KAAA;AACrE,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,OAAA,IAAW,EAAC;AAClC,EAAA,MAAM,aAAA,GAAgB,MAAM,WAAA,KAAgB,IAAA;AAE5C,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAS,YAAY,mBAAA,EAAqB,aAAA,KAAkB,oBAAA,EAAqB;AAE/F,EAAA,MAAM,iBAAA,GAAoB,OAA+C,MAAS,CAAA;AAClF,EAAA,iBAAA,CAAkB,OAAA,GAAU,aAAA,GAAgB,KAAA,CAAM,cAAA,GAAiB,MAAA;AACnE,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,aAAA,EAAe;AACpB,IAAA,iBAAA,CAAkB,UAAU,mBAAmB,CAAA;AAAA,EACjD,CAAA,EAAG,CAAC,mBAAA,EAAqB,aAAa,CAAC,CAAA;AAEvC,EAAA,MAAM,KAAA,GAAQ,aAAA,GAAgB,KAAA,CAAM,KAAA,GAAQ,EAAC;AAC7C,EAAA,MAAM,WAAA,GAAc,aAAA,GAAgB,KAAA,CAAM,WAAA,GAAc,KAAA;AACxD,EAAA,MAAM,WAAA,GAAc,aAAA,GAAgB,KAAA,CAAM,kBAAA,GAAqB,KAAA;AAC/D,EAAA,MAAM,YAAA,GAAe,aAAA,GAAgB,KAAA,CAAM,UAAA,GAAa,MAAM;AAAA,EAAC,CAAA;AAE/D,EAAA,MAAM,eAAA,GAAkB,QAAQ,MAAM;AACpC,IAAA,IAAI,eAAe,OAAO,KAAA;AAE1B,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,CAAC,MAAA,KAAW,cAAA,CAAe,MAAM,CAAA,CAAE,WAAA,EAAY,CAAE,QAAA,CAAS,UAAA,CAAW,WAAA,EAAa,CAAC,CAAA;AAAA,IAC3G;AAEA,IAAA,OAAO,UAAA,GAAa,aAAA,CAAc,OAAA,EAAS,UAAU,CAAA,GAAI,OAAA;AAAA,EAC3D,CAAA,EAAG,CAAC,aAAA,EAAe,KAAA,EAAO,eAAe,OAAA,EAAS,UAAA,EAAY,cAAc,CAAC,CAAA;AAE7E,EAAA,MAAM,EAAE,cAAc,YAAA,EAAc,WAAA,EAAa,UAAS,GAAI,oBAAA,CAAqB,OAAO,OAAO,CAAA;AAEjG,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,KAAK,CAAA;AAEhD,EAAA,MAAM,YAAA,GAAe,eAAA,CAAmB,EAAE,KAAA,EAAO,cAAc,CAAA;AAE/D,EAAA,MAAM,eAAA,GAAkB,OAAA,IAAW,QAAA,IAAY,SAAA,IAAa,SAAA;AAE5D,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,aAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAA;AAAA,IACA,aAAA;AAAA,IACA,eAAA;AAAA,IACA,YAAA;AAAA,IACA,QAAA;AAAA,IACA,eAAA;AAAA,IACA,YAAA;AAAA,IACA,YAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
|
package/package.json
CHANGED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
type FetchPageResult<T> = {
|
|
2
|
-
items: Array<T>;
|
|
3
|
-
hasNextPage: boolean;
|
|
4
|
-
nextPage: number;
|
|
5
|
-
};
|
|
6
|
-
type FetchPage<T> = (params: {
|
|
7
|
-
page: number;
|
|
8
|
-
search?: string;
|
|
9
|
-
}) => Promise<FetchPageResult<T>>;
|
|
10
|
-
type UsePaginatedOptionsParams<T> = {
|
|
11
|
-
fetchPage?: FetchPage<T>;
|
|
12
|
-
debouncedSearchTerm: string;
|
|
13
|
-
open: boolean;
|
|
14
|
-
prefetch?: boolean;
|
|
15
|
-
loading: boolean;
|
|
16
|
-
onItemsLoaded: (items: Array<T>) => void;
|
|
17
|
-
};
|
|
18
|
-
export declare function usePaginatedOptions<T>({ fetchPage, debouncedSearchTerm, open, prefetch, loading, onItemsLoaded, }: UsePaginatedOptionsParams<T>): {
|
|
19
|
-
localOptions: T[];
|
|
20
|
-
hasNextPage: boolean;
|
|
21
|
-
loadingMore: boolean;
|
|
22
|
-
loadNextPage: () => Promise<void>;
|
|
23
|
-
};
|
|
24
|
-
export {};
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { useState, useRef, useEffect } from 'react';
|
|
2
|
-
|
|
3
|
-
function usePaginatedOptions({
|
|
4
|
-
fetchPage,
|
|
5
|
-
debouncedSearchTerm,
|
|
6
|
-
open,
|
|
7
|
-
prefetch,
|
|
8
|
-
loading,
|
|
9
|
-
onItemsLoaded
|
|
10
|
-
}) {
|
|
11
|
-
const enabled = !!fetchPage;
|
|
12
|
-
const [page, setPage] = useState(1);
|
|
13
|
-
const [localOptions, setLocalOptions] = useState([]);
|
|
14
|
-
const [hasNextPage, setHasNextPage] = useState(true);
|
|
15
|
-
const [loadingMore, setLoadingMore] = useState(false);
|
|
16
|
-
const loadStateRef = useRef({ token: 0, inFlight: false });
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
if (!enabled) return;
|
|
19
|
-
loadStateRef.current.token++;
|
|
20
|
-
loadStateRef.current.inFlight = false;
|
|
21
|
-
setPage(1);
|
|
22
|
-
setLocalOptions([]);
|
|
23
|
-
setHasNextPage(true);
|
|
24
|
-
setLoadingMore(false);
|
|
25
|
-
}, [debouncedSearchTerm, enabled]);
|
|
26
|
-
const loadNextPage = async () => {
|
|
27
|
-
if (!fetchPage || loadStateRef.current.inFlight || !hasNextPage || loading) return;
|
|
28
|
-
loadStateRef.current.inFlight = true;
|
|
29
|
-
const token = loadStateRef.current.token;
|
|
30
|
-
setLoadingMore(true);
|
|
31
|
-
try {
|
|
32
|
-
const result = await fetchPage({ page, search: debouncedSearchTerm || void 0 });
|
|
33
|
-
if (token !== loadStateRef.current.token) return;
|
|
34
|
-
onItemsLoaded(result.items);
|
|
35
|
-
setLocalOptions((prev) => [...prev, ...result.items]);
|
|
36
|
-
setPage(result.nextPage);
|
|
37
|
-
setHasNextPage(result.hasNextPage);
|
|
38
|
-
} finally {
|
|
39
|
-
if (token === loadStateRef.current.token) {
|
|
40
|
-
loadStateRef.current.inFlight = false;
|
|
41
|
-
setLoadingMore(false);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
if (enabled && (open || prefetch) && localOptions.length === 0 && !loading && !loadingMore) {
|
|
47
|
-
loadNextPage();
|
|
48
|
-
}
|
|
49
|
-
}, [enabled, open, prefetch, localOptions.length, loading, loadingMore, debouncedSearchTerm]);
|
|
50
|
-
return { localOptions, hasNextPage, loadingMore, loadNextPage };
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export { usePaginatedOptions };
|
|
54
|
-
//# sourceMappingURL=usePaginatedOptions.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usePaginatedOptions.js","sources":["../../../../src/components/Combobox/hooks/usePaginatedOptions.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\n\ntype FetchPageResult<T> = { items: Array<T>; hasNextPage: boolean; nextPage: number }\n\ntype FetchPage<T> = (params: { page: number; search?: string }) => Promise<FetchPageResult<T>>\n\ntype UsePaginatedOptionsParams<T> = {\n fetchPage?: FetchPage<T>\n debouncedSearchTerm: string\n open: boolean\n prefetch?: boolean\n loading: boolean\n onItemsLoaded: (items: Array<T>) => void\n}\n\nexport function usePaginatedOptions<T>({\n fetchPage,\n debouncedSearchTerm,\n open,\n prefetch,\n loading,\n onItemsLoaded,\n}: UsePaginatedOptionsParams<T>) {\n const enabled = !!fetchPage\n const [page, setPage] = useState(1)\n const [localOptions, setLocalOptions] = useState<Array<T>>([])\n const [hasNextPage, setHasNextPage] = useState(true)\n const [loadingMore, setLoadingMore] = useState(false)\n const loadStateRef = useRef({ token: 0, inFlight: false })\n\n useEffect(() => {\n if (!enabled) return\n loadStateRef.current.token++\n loadStateRef.current.inFlight = false\n setPage(1)\n setLocalOptions([])\n setHasNextPage(true)\n setLoadingMore(false)\n }, [debouncedSearchTerm, enabled])\n\n const loadNextPage = async () => {\n if (!fetchPage || loadStateRef.current.inFlight || !hasNextPage || loading) return\n\n loadStateRef.current.inFlight = true\n const token = loadStateRef.current.token\n setLoadingMore(true)\n try {\n const result = await fetchPage({ page, search: debouncedSearchTerm || undefined })\n if (token !== loadStateRef.current.token) return\n onItemsLoaded(result.items)\n setLocalOptions((prev) => [...prev, ...result.items])\n setPage(result.nextPage)\n setHasNextPage(result.hasNextPage)\n } finally {\n if (token === loadStateRef.current.token) {\n loadStateRef.current.inFlight = false\n setLoadingMore(false)\n }\n }\n }\n\n useEffect(() => {\n if (enabled && (open || prefetch) && localOptions.length === 0 && !loading && !loadingMore) {\n loadNextPage()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, open, prefetch, localOptions.length, loading, loadingMore, debouncedSearchTerm])\n\n return { localOptions, hasNextPage, loadingMore, loadNextPage }\n}\n"],"names":[],"mappings":";;AAeO,SAAS,mBAAA,CAAuB;AAAA,EACrC,SAAA;AAAA,EACA,mBAAA;AAAA,EACA,IAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,EAAiC;AAC/B,EAAA,MAAM,OAAA,GAAU,CAAC,CAAC,SAAA;AAClB,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,CAAC,CAAA;AAClC,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,QAAA,CAAmB,EAAE,CAAA;AAC7D,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,IAAI,CAAA;AACnD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,KAAK,CAAA;AACpD,EAAA,MAAM,eAAe,MAAA,CAAO,EAAE,OAAO,CAAA,EAAG,QAAA,EAAU,OAAO,CAAA;AAEzD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,YAAA,CAAa,OAAA,CAAQ,KAAA,EAAA;AACrB,IAAA,YAAA,CAAa,QAAQ,QAAA,GAAW,KAAA;AAChC,IAAA,OAAA,CAAQ,CAAC,CAAA;AACT,IAAA,eAAA,CAAgB,EAAE,CAAA;AAClB,IAAA,cAAA,CAAe,IAAI,CAAA;AACnB,IAAA,cAAA,CAAe,KAAK,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,mBAAA,EAAqB,OAAO,CAAC,CAAA;AAEjC,EAAA,MAAM,eAAe,YAAY;AAC/B,IAAA,IAAI,CAAC,SAAA,IAAa,YAAA,CAAa,QAAQ,QAAA,IAAY,CAAC,eAAe,OAAA,EAAS;AAE5E,IAAA,YAAA,CAAa,QAAQ,QAAA,GAAW,IAAA;AAChC,IAAA,MAAM,KAAA,GAAQ,aAAa,OAAA,CAAQ,KAAA;AACnC,IAAA,cAAA,CAAe,IAAI,CAAA;AACnB,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,EAAE,MAAM,MAAA,EAAQ,mBAAA,IAAuB,QAAW,CAAA;AACjF,MAAA,IAAI,KAAA,KAAU,YAAA,CAAa,OAAA,CAAQ,KAAA,EAAO;AAC1C,MAAA,aAAA,CAAc,OAAO,KAAK,CAAA;AAC1B,MAAA,eAAA,CAAgB,CAAC,SAAS,CAAC,GAAG,MAAM,GAAG,MAAA,CAAO,KAAK,CAAC,CAAA;AACpD,MAAA,OAAA,CAAQ,OAAO,QAAQ,CAAA;AACvB,MAAA,cAAA,CAAe,OAAO,WAAW,CAAA;AAAA,IACnC,CAAA,SAAE;AACA,MAAA,IAAI,KAAA,KAAU,YAAA,CAAa,OAAA,CAAQ,KAAA,EAAO;AACxC,QAAA,YAAA,CAAa,QAAQ,QAAA,GAAW,KAAA;AAChC,QAAA,cAAA,CAAe,KAAK,CAAA;AAAA,MACtB;AAAA,IACF;AAAA,EACF,CAAA;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,OAAA,KAAY,QAAQ,QAAA,CAAA,IAAa,YAAA,CAAa,WAAW,CAAA,IAAK,CAAC,OAAA,IAAW,CAAC,WAAA,EAAa;AAC1F,MAAA,YAAA,EAAa;AAAA,IACf;AAAA,EAEF,CAAA,EAAG,CAAC,OAAA,EAAS,IAAA,EAAM,QAAA,EAAU,aAAa,MAAA,EAAQ,OAAA,EAAS,WAAA,EAAa,mBAAmB,CAAC,CAAA;AAE5F,EAAA,OAAO,EAAE,YAAA,EAAc,WAAA,EAAa,WAAA,EAAa,YAAA,EAAa;AAChE;;;;"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { useRef, useCallback } from 'react';
|
|
2
|
-
|
|
3
|
-
function useSelectedCache(getOptionValue) {
|
|
4
|
-
const cacheRef = useRef(/* @__PURE__ */ new Map());
|
|
5
|
-
const getValueRef = useRef(getOptionValue);
|
|
6
|
-
getValueRef.current = getOptionValue;
|
|
7
|
-
const record = useCallback((items) => {
|
|
8
|
-
for (const item of items) {
|
|
9
|
-
cacheRef.current.set(getValueRef.current(item), item);
|
|
10
|
-
}
|
|
11
|
-
}, []);
|
|
12
|
-
const resolve = useCallback((value) => cacheRef.current.get(value), []);
|
|
13
|
-
return { record, resolve };
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export { useSelectedCache };
|
|
17
|
-
//# sourceMappingURL=useSelectedCache.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useSelectedCache.js","sources":["../../../../src/components/Combobox/hooks/useSelectedCache.ts"],"sourcesContent":["import { useCallback, useRef } from 'react'\n\nexport function useSelectedCache<T>(getOptionValue: (option: T) => string) {\n const cacheRef = useRef<Map<string, T>>(new Map())\n const getValueRef = useRef(getOptionValue)\n getValueRef.current = getOptionValue\n\n const record = useCallback((items: Iterable<T>) => {\n for (const item of items) {\n cacheRef.current.set(getValueRef.current(item), item)\n }\n }, [])\n\n const resolve = useCallback((value: string) => cacheRef.current.get(value), [])\n\n return { record, resolve }\n}\n"],"names":[],"mappings":";;AAEO,SAAS,iBAAoB,cAAA,EAAuC;AACzE,EAAA,MAAM,QAAA,GAAW,MAAA,iBAAuB,IAAI,GAAA,EAAK,CAAA;AACjD,EAAA,MAAM,WAAA,GAAc,OAAO,cAAc,CAAA;AACzC,EAAA,WAAA,CAAY,OAAA,GAAU,cAAA;AAEtB,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,CAAC,KAAA,KAAuB;AACjD,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,QAAA,CAAS,QAAQ,GAAA,CAAI,WAAA,CAAY,OAAA,CAAQ,IAAI,GAAG,IAAI,CAAA;AAAA,IACtD;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,OAAA,GAAU,WAAA,CAAY,CAAC,KAAA,KAAkB,QAAA,CAAS,QAAQ,GAAA,CAAI,KAAK,CAAA,EAAG,EAAE,CAAA;AAE9E,EAAA,OAAO,EAAE,QAAQ,OAAA,EAAQ;AAC3B;;;;"}
|