periplo-ui 3.54.0 → 3.56.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.
@@ -17,6 +17,8 @@ type ComboboxBaseProps<T> = {
17
17
  emptyMessage?: string;
18
18
  /** Additional CSS classes to apply to the combobox trigger */
19
19
  className?: string;
20
+ /** Additional CSS classes to apply to the popover content */
21
+ contentClassName?: string;
20
22
  /** Whether the combobox is disabled */
21
23
  disabled?: boolean;
22
24
  /** Maximum height of the options list. Can be any valid CSS height value */
@@ -18,6 +18,7 @@ const Combobox = (props) => {
18
18
  searchPlaceholder = "Search...",
19
19
  emptyMessage = "No results found.",
20
20
  className = "w-60",
21
+ contentClassName,
21
22
  disabled = false,
22
23
  maxHeight = "300px",
23
24
  renderOption,
@@ -33,6 +34,8 @@ const Combobox = (props) => {
33
34
  specialOptionsTitle,
34
35
  container
35
36
  } = props;
37
+ const normalizedMaxHeight = typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight;
38
+ const boundedListMaxHeight = `min(${normalizedMaxHeight}, max(120px, calc(var(--radix-popover-content-available-height, 100dvh) - 68px)))`;
36
39
  const {
37
40
  open,
38
41
  setOpen,
@@ -126,7 +129,7 @@ const Combobox = (props) => {
126
129
  )
127
130
  }
128
131
  ),
129
- /* @__PURE__ */ jsx(PopoverContent, { className: "p-0", container, side: "bottom", avoidCollisions: false, children: /* @__PURE__ */ jsxs(Command, { shouldFilter: false, children: [
132
+ /* @__PURE__ */ jsx(PopoverContent, { className: cn("overflow-hidden p-0", contentClassName), container, side: "bottom", children: /* @__PURE__ */ jsxs(Command, { shouldFilter: false, children: [
130
133
  /* @__PURE__ */ jsx(
131
134
  CommandInput,
132
135
  {
@@ -148,7 +151,7 @@ const Combobox = (props) => {
148
151
  getOptionLabel,
149
152
  handleSelect,
150
153
  renderOption,
151
- maxHeight,
154
+ maxHeight: boundedListMaxHeight,
152
155
  hasNextPage,
153
156
  loadingMore,
154
157
  onLoadMore: loadNextPage
@@ -166,7 +169,7 @@ const Combobox = (props) => {
166
169
  getOptionLabel,
167
170
  handleSelect,
168
171
  renderOption,
169
- maxHeight,
172
+ maxHeight: boundedListMaxHeight,
170
173
  selectedMultiplePlaceholder,
171
174
  multipleOptionsPlaceholder,
172
175
  options,
@@ -1 +1 @@
1
- {"version":3,"file":"Combobox.js","sources":["../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import { CaretDown } from '@phosphor-icons/react/dist/ssr/CaretDown'\nimport { X } from '@phosphor-icons/react/dist/ssr/X'\n\nimport { cn } from '../../lib/utils'\nimport { Button, buttonVariants } from '../Button'\nimport { Command, CommandInput } from '../Command'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\n\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 /** 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}\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}\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}\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 * interface User {\n * id: string\n * name: string\n * email: string\n * }\n *\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 *\n * @example Custom filtering\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 * filterOptions={(options, searchTerm) =>\n * options.filter(user =>\n * user.name.toLowerCase().includes(searchTerm.toLowerCase()) ||\n * user.email.toLowerCase().includes(searchTerm.toLowerCase())\n * )\n * }\n * />\n * ```\n *\n * @example Virtualized infinite scrolling with pagination\n * ```tsx\n * <Combobox<User>\n * options={[]} // Initial options can be empty\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * fetchPage={async ({ page, search }) => {\n * const response = await api.getUsers({ page, search })\n * return {\n * items: response.users,\n * hasNextPage: response.page < response.totalPages,\n * nextPage: page + 1\n * }\n * }}\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 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 } = props\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 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 <Button\n id={id}\n type=\"button\"\n disabled={disabled}\n variant=\"text\"\n className={cn(\n buttonVariants({ variant: 'input', size: 'lg' }),\n 'relative flex justify-between rounded-lg',\n multiple && 'renderLabel' in props && props.renderLabel ? 'h-auto min-h-12' : 'h-12',\n open && 'border-neutral-950',\n disabled && 'cursor-not-allowed',\n error && 'border-error-400 focus-visible:border-error-700',\n className,\n )}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n <span\n className={cn(\n 'block',\n !hasValue && 'text-neutral-300',\n !(multiple && 'renderLabel' in props && props.renderLabel) && 'truncate',\n )}\n >\n {displayValue}\n </span>\n <CaretDown\n className={cn(\n 'h-4 w-4 shrink-0 opacity-50 transition-opacity duration-150',\n showClearButton ? 'opacity-0' : 'opacity-50',\n )}\n />\n {onClear && hasValue && (\n <X\n data-testid=\"clear-button\"\n className={cn(\n 'absolute right-4 z-10 h-4 w-4 shrink-0 cursor-pointer transition-opacity duration-150',\n showClearButton ? 'opacity-100 hover:opacity-70' : 'opacity-0',\n )}\n onClick={handleClear}\n />\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"p-0\" container={container} side=\"bottom\" avoidCollisions={false}>\n <Command shouldFilter={false}>\n <CommandInput\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={maxHeight}\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={maxHeight}\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 { CaretDown } from '@phosphor-icons/react/dist/ssr/CaretDown'\nimport { X } from '@phosphor-icons/react/dist/ssr/X'\n\nimport { cn } from '../../lib/utils'\nimport { Button, buttonVariants } from '../Button'\nimport { Command, CommandInput } from '../Command'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\n\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}\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}\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}\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 * interface User {\n * id: string\n * name: string\n * email: string\n * }\n *\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 *\n * @example Custom filtering\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 * filterOptions={(options, searchTerm) =>\n * options.filter(user =>\n * user.name.toLowerCase().includes(searchTerm.toLowerCase()) ||\n * user.email.toLowerCase().includes(searchTerm.toLowerCase())\n * )\n * }\n * />\n * ```\n *\n * @example Virtualized infinite scrolling with pagination\n * ```tsx\n * <Combobox<User>\n * options={[]} // Initial options can be empty\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * fetchPage={async ({ page, search }) => {\n * const response = await api.getUsers({ page, search })\n * return {\n * items: response.users,\n * hasNextPage: response.page < response.totalPages,\n * nextPage: page + 1\n * }\n * }}\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 } = props\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 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 <Button\n id={id}\n type=\"button\"\n disabled={disabled}\n variant=\"text\"\n className={cn(\n buttonVariants({ variant: 'input', size: 'lg' }),\n 'relative flex justify-between rounded-lg',\n multiple && 'renderLabel' in props && props.renderLabel ? 'h-auto min-h-12' : 'h-12',\n open && 'border-neutral-950',\n disabled && 'cursor-not-allowed',\n error && 'border-error-400 focus-visible:border-error-700',\n className,\n )}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n <span\n className={cn(\n 'block',\n !hasValue && 'text-neutral-300',\n !(multiple && 'renderLabel' in props && props.renderLabel) && 'truncate',\n )}\n >\n {displayValue}\n </span>\n <CaretDown\n className={cn(\n 'h-4 w-4 shrink-0 opacity-50 transition-opacity duration-150',\n showClearButton ? 'opacity-0' : 'opacity-50',\n )}\n />\n {onClear && hasValue && (\n <X\n data-testid=\"clear-button\"\n className={cn(\n 'absolute right-4 z-10 h-4 w-4 shrink-0 cursor-pointer transition-opacity duration-150',\n showClearButton ? 'opacity-100 hover:opacity-70' : 'opacity-0',\n )}\n onClick={handleClear}\n />\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent className={cn('overflow-hidden p-0', contentClassName)} container={container} side=\"bottom\">\n <Command shouldFilter={false}>\n <CommandInput\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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"}
@@ -51,15 +51,23 @@ const StaticComboboxList = ({
51
51
  /* @__PURE__ */ jsx(ComboboxOptionWithTooltip, { label: getOptionLabel(option) })
52
52
  ] }) });
53
53
  };
54
- return /* @__PURE__ */ jsx(CommandList, { style: { maxHeight }, className: "overflow-auto", onWheel: (event) => event.stopPropagation(), children: loading ? /* @__PURE__ */ jsx("div", { className: "text-muted-foreground flex items-center justify-center py-6 text-sm", children: loadingPlaceholder }) : /* @__PURE__ */ jsxs(Fragment, { children: [
55
- filteredOptions.length === 0 && regularOptions.length === 0 && (!specialOptions || specialOptions.length === 0) && /* @__PURE__ */ jsx(CommandEmpty, { children: emptyMessage }),
56
- specialOptions?.length && specialOptionsTitle ? /* @__PURE__ */ jsxs(Fragment, { children: [
57
- /* @__PURE__ */ jsx(CommandGroup, { heading: specialOptionsTitle, children: specialOptions.map((option) => /* @__PURE__ */ jsx(OptionItem, { option }, getOptionValue(option))) }),
58
- /* @__PURE__ */ jsx(CommandSeparator, { className: "!mx-[10px]" })
59
- ] }) : null,
60
- !specialOptions && multiple && isArrayValue && regularSelectedOptions.length > 0 && /* @__PURE__ */ jsx(CommandGroup, { heading: selectedMultiplePlaceholder, children: regularSelectedOptions.map((option) => /* @__PURE__ */ jsx(OptionItem, { option }, getOptionValue(option))) }),
61
- /* @__PURE__ */ jsx(CommandGroup, { heading: groupHeading, children: optionsToShow.map((option) => /* @__PURE__ */ jsx(OptionItem, { option }, getOptionValue(option))) })
62
- ] }) });
54
+ return /* @__PURE__ */ jsx(
55
+ CommandList,
56
+ {
57
+ style: { maxHeight },
58
+ className: "overflow-auto overscroll-contain",
59
+ onWheel: (event) => event.stopPropagation(),
60
+ children: loading ? /* @__PURE__ */ jsx("div", { className: "text-muted-foreground flex items-center justify-center py-6 text-sm", children: loadingPlaceholder }) : /* @__PURE__ */ jsxs(Fragment, { children: [
61
+ filteredOptions.length === 0 && regularOptions.length === 0 && (!specialOptions || specialOptions.length === 0) && /* @__PURE__ */ jsx(CommandEmpty, { children: emptyMessage }),
62
+ specialOptions?.length && specialOptionsTitle ? /* @__PURE__ */ jsxs(Fragment, { children: [
63
+ /* @__PURE__ */ jsx(CommandGroup, { heading: specialOptionsTitle, children: specialOptions.map((option) => /* @__PURE__ */ jsx(OptionItem, { option }, getOptionValue(option))) }),
64
+ /* @__PURE__ */ jsx(CommandSeparator, { className: "!mx-[10px]" })
65
+ ] }) : null,
66
+ !specialOptions && multiple && isArrayValue && regularSelectedOptions.length > 0 && /* @__PURE__ */ jsx(CommandGroup, { heading: selectedMultiplePlaceholder, children: regularSelectedOptions.map((option) => /* @__PURE__ */ jsx(OptionItem, { option }, getOptionValue(option))) }),
67
+ /* @__PURE__ */ jsx(CommandGroup, { heading: groupHeading, children: optionsToShow.map((option) => /* @__PURE__ */ jsx(OptionItem, { option }, getOptionValue(option))) })
68
+ ] })
69
+ }
70
+ );
63
71
  };
64
72
 
65
73
  export { StaticComboboxList };
@@ -1 +1 @@
1
- {"version":3,"file":"StaticComboboxList.js","sources":["../../../src/components/Combobox/StaticComboboxList.tsx"],"sourcesContent":["import { CheckSquare } from '@phosphor-icons/react/dist/ssr/CheckSquare'\nimport { Square } from '@phosphor-icons/react/dist/ssr/Square'\nimport { useMemo } from 'react'\n\nimport { CommandEmpty, CommandGroup, CommandItem, CommandList, CommandSeparator } from '../Command'\n\nimport { ComboboxOptionWithTooltip } from './ComboboxOptionWithTooltip'\nimport type { StaticComboboxListProps } from './types'\n\nexport const StaticComboboxList = <T extends object>({\n filteredOptions,\n loading,\n loadingPlaceholder,\n emptyMessage,\n multiple,\n value,\n getOptionValue,\n getOptionLabel,\n handleSelect,\n renderOption,\n maxHeight,\n selectedMultiplePlaceholder,\n multipleOptionsPlaceholder,\n options,\n specialOptions,\n specialOptionsTitle,\n}: StaticComboboxListProps<T>) => {\n const isArrayValue = Array.isArray(value)\n const selectedValues = useMemo(() => (multiple && isArrayValue ? value : []), [multiple, isArrayValue, value])\n\n const isOptionSelected = (optionValue: string) =>\n multiple ? selectedValues.includes(optionValue) : value === optionValue\n\n const regularOptions = useMemo(() => {\n return filteredOptions.filter(\n (option) => !specialOptions?.some((special) => getOptionValue(special) === getOptionValue(option)),\n )\n }, [filteredOptions, specialOptions, getOptionValue])\n\n const regularSelectedOptions = useMemo(() => {\n if (!multiple || !isArrayValue) return []\n\n return options.filter(\n (option) =>\n selectedValues.includes(getOptionValue(option)) &&\n !specialOptions?.some((special) => getOptionValue(special) === getOptionValue(option)),\n )\n }, [options, selectedValues, specialOptions, getOptionValue, multiple, isArrayValue])\n\n const optionsToShow = useMemo(() => {\n if (specialOptions) return regularOptions\n\n if (!multiple || !isArrayValue) return regularOptions\n\n return regularOptions.filter((option) => !selectedValues.includes(getOptionValue(option)))\n }, [regularOptions, specialOptions, selectedValues, getOptionValue, multiple, isArrayValue])\n\n const groupHeading = !specialOptions && multiple ? multipleOptionsPlaceholder : undefined\n\n const OptionItem = ({ option }: { option: T }) => {\n const optionValue = getOptionValue(option)\n const selected = isOptionSelected(optionValue)\n\n return (\n <CommandItem value={optionValue} onSelect={handleSelect}>\n {renderOption ? (\n renderOption(option, selected)\n ) : (\n <>\n {selected ? <CheckSquare className=\"mr-2 !h-6 !w-6\" /> : <Square className=\"mr-2 !h-6 !w-6\" />}\n <ComboboxOptionWithTooltip label={getOptionLabel(option)} />\n </>\n )}\n </CommandItem>\n )\n }\n\n return (\n <CommandList style={{ maxHeight }} className=\"overflow-auto\" onWheel={(event) => event.stopPropagation()}>\n {loading ? (\n <div className=\"text-muted-foreground flex items-center justify-center py-6 text-sm\">{loadingPlaceholder}</div>\n ) : (\n <>\n {filteredOptions.length === 0 &&\n regularOptions.length === 0 &&\n (!specialOptions || specialOptions.length === 0) && <CommandEmpty>{emptyMessage}</CommandEmpty>}\n\n {specialOptions?.length && specialOptionsTitle ? (\n <>\n <CommandGroup heading={specialOptionsTitle}>\n {specialOptions.map((option) => (\n <OptionItem key={getOptionValue(option)} option={option} />\n ))}\n </CommandGroup>\n\n <CommandSeparator className=\"!mx-[10px]\" />\n </>\n ) : null}\n\n {!specialOptions && multiple && isArrayValue && regularSelectedOptions.length > 0 && (\n <CommandGroup heading={selectedMultiplePlaceholder}>\n {regularSelectedOptions.map((option) => (\n <OptionItem key={getOptionValue(option)} option={option} />\n ))}\n </CommandGroup>\n )}\n\n <CommandGroup heading={groupHeading}>\n {optionsToShow.map((option) => (\n <OptionItem key={getOptionValue(option)} option={option} />\n ))}\n </CommandGroup>\n </>\n )}\n </CommandList>\n )\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StaticComboboxList.js","sources":["../../../src/components/Combobox/StaticComboboxList.tsx"],"sourcesContent":["import { CheckSquare } from '@phosphor-icons/react/dist/ssr/CheckSquare'\nimport { Square } from '@phosphor-icons/react/dist/ssr/Square'\nimport { useMemo } from 'react'\n\nimport { CommandEmpty, CommandGroup, CommandItem, CommandList, CommandSeparator } from '../Command'\n\nimport { ComboboxOptionWithTooltip } from './ComboboxOptionWithTooltip'\nimport type { StaticComboboxListProps } from './types'\n\nexport const StaticComboboxList = <T extends object>({\n filteredOptions,\n loading,\n loadingPlaceholder,\n emptyMessage,\n multiple,\n value,\n getOptionValue,\n getOptionLabel,\n handleSelect,\n renderOption,\n maxHeight,\n selectedMultiplePlaceholder,\n multipleOptionsPlaceholder,\n options,\n specialOptions,\n specialOptionsTitle,\n}: StaticComboboxListProps<T>) => {\n const isArrayValue = Array.isArray(value)\n const selectedValues = useMemo(() => (multiple && isArrayValue ? value : []), [multiple, isArrayValue, value])\n\n const isOptionSelected = (optionValue: string) =>\n multiple ? selectedValues.includes(optionValue) : value === optionValue\n\n const regularOptions = useMemo(() => {\n return filteredOptions.filter(\n (option) => !specialOptions?.some((special) => getOptionValue(special) === getOptionValue(option)),\n )\n }, [filteredOptions, specialOptions, getOptionValue])\n\n const regularSelectedOptions = useMemo(() => {\n if (!multiple || !isArrayValue) return []\n\n return options.filter(\n (option) =>\n selectedValues.includes(getOptionValue(option)) &&\n !specialOptions?.some((special) => getOptionValue(special) === getOptionValue(option)),\n )\n }, [options, selectedValues, specialOptions, getOptionValue, multiple, isArrayValue])\n\n const optionsToShow = useMemo(() => {\n if (specialOptions) return regularOptions\n\n if (!multiple || !isArrayValue) return regularOptions\n\n return regularOptions.filter((option) => !selectedValues.includes(getOptionValue(option)))\n }, [regularOptions, specialOptions, selectedValues, getOptionValue, multiple, isArrayValue])\n\n const groupHeading = !specialOptions && multiple ? multipleOptionsPlaceholder : undefined\n\n const OptionItem = ({ option }: { option: T }) => {\n const optionValue = getOptionValue(option)\n const selected = isOptionSelected(optionValue)\n\n return (\n <CommandItem value={optionValue} onSelect={handleSelect}>\n {renderOption ? (\n renderOption(option, selected)\n ) : (\n <>\n {selected ? <CheckSquare className=\"mr-2 !h-6 !w-6\" /> : <Square className=\"mr-2 !h-6 !w-6\" />}\n <ComboboxOptionWithTooltip label={getOptionLabel(option)} />\n </>\n )}\n </CommandItem>\n )\n }\n\n return (\n <CommandList\n style={{ maxHeight }}\n className=\"overflow-auto overscroll-contain\"\n onWheel={(event) => event.stopPropagation()}\n >\n {loading ? (\n <div className=\"text-muted-foreground flex items-center justify-center py-6 text-sm\">{loadingPlaceholder}</div>\n ) : (\n <>\n {filteredOptions.length === 0 &&\n regularOptions.length === 0 &&\n (!specialOptions || specialOptions.length === 0) && <CommandEmpty>{emptyMessage}</CommandEmpty>}\n\n {specialOptions?.length && specialOptionsTitle ? (\n <>\n <CommandGroup heading={specialOptionsTitle}>\n {specialOptions.map((option) => (\n <OptionItem key={getOptionValue(option)} option={option} />\n ))}\n </CommandGroup>\n\n <CommandSeparator className=\"!mx-[10px]\" />\n </>\n ) : null}\n\n {!specialOptions && multiple && isArrayValue && regularSelectedOptions.length > 0 && (\n <CommandGroup heading={selectedMultiplePlaceholder}>\n {regularSelectedOptions.map((option) => (\n <OptionItem key={getOptionValue(option)} option={option} />\n ))}\n </CommandGroup>\n )}\n\n <CommandGroup heading={groupHeading}>\n {optionsToShow.map((option) => (\n <OptionItem key={getOptionValue(option)} option={option} />\n ))}\n </CommandGroup>\n </>\n )}\n </CommandList>\n )\n}\n"],"names":[],"mappings":"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"}
@@ -56,34 +56,43 @@ const VirtualizedComboboxList = ({
56
56
  const isSelected = value === getOptionValue(option);
57
57
  return { option, isSelected };
58
58
  };
59
- return /* @__PURE__ */ jsxs("div", { ref: parentRef, className: "overflow-auto", style: { maxHeight }, onWheel: (event) => event.stopPropagation(), children: [
60
- /* @__PURE__ */ jsx("div", { style: { height: `${rowVirtualizer.getTotalSize()}px`, position: "relative" }, children: rowVirtualizer.getVirtualItems().map((virtualRow) => {
61
- const { option, isSelected } = getItemAtIndex(virtualRow.index);
62
- const optionValue = getOptionValue(option);
63
- return /* @__PURE__ */ jsx(
64
- "div",
65
- {
66
- "data-index": virtualRow.index,
67
- ref: (el) => {
68
- if (el) rowVirtualizer.measureElement(el);
69
- },
70
- style: {
71
- position: "absolute",
72
- top: 0,
73
- left: 0,
74
- width: "100%",
75
- transform: `translateY(${virtualRow.start}px)`
76
- },
77
- children: /* @__PURE__ */ jsx(CommandItem, { value: optionValue, onSelect: handleSelect, children: renderOption ? renderOption(option, isSelected) : /* @__PURE__ */ jsxs(Fragment, { children: [
78
- /* @__PURE__ */ jsx(Check, { className: `mr-2 h-4 w-4 ${isSelected ? "opacity-100" : "opacity-0"}` }),
79
- /* @__PURE__ */ jsx(ComboboxOptionWithTooltip, { label: getOptionLabel(option) })
80
- ] }) })
81
- },
82
- optionValue
83
- );
84
- }) }),
85
- loadingMore && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-2 text-sm text-neutral-500", children: loadingPlaceholder })
86
- ] });
59
+ return /* @__PURE__ */ jsxs(
60
+ "div",
61
+ {
62
+ ref: parentRef,
63
+ className: "overflow-auto overscroll-contain",
64
+ style: { maxHeight },
65
+ onWheel: (event) => event.stopPropagation(),
66
+ children: [
67
+ /* @__PURE__ */ jsx("div", { style: { height: `${rowVirtualizer.getTotalSize()}px`, position: "relative" }, children: rowVirtualizer.getVirtualItems().map((virtualRow) => {
68
+ const { option, isSelected } = getItemAtIndex(virtualRow.index);
69
+ const optionValue = getOptionValue(option);
70
+ return /* @__PURE__ */ jsx(
71
+ "div",
72
+ {
73
+ "data-index": virtualRow.index,
74
+ ref: (el) => {
75
+ if (el) rowVirtualizer.measureElement(el);
76
+ },
77
+ style: {
78
+ position: "absolute",
79
+ top: 0,
80
+ left: 0,
81
+ width: "100%",
82
+ transform: `translateY(${virtualRow.start}px)`
83
+ },
84
+ children: /* @__PURE__ */ jsx(CommandItem, { value: optionValue, onSelect: handleSelect, children: renderOption ? renderOption(option, isSelected) : /* @__PURE__ */ jsxs(Fragment, { children: [
85
+ /* @__PURE__ */ jsx(Check, { className: `mr-2 h-4 w-4 ${isSelected ? "opacity-100" : "opacity-0"}` }),
86
+ /* @__PURE__ */ jsx(ComboboxOptionWithTooltip, { label: getOptionLabel(option) })
87
+ ] }) })
88
+ },
89
+ optionValue
90
+ );
91
+ }) }),
92
+ loadingMore && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-2 text-sm text-neutral-500", children: loadingPlaceholder })
93
+ ]
94
+ }
95
+ );
87
96
  };
88
97
 
89
98
  export { VirtualizedComboboxList };
@@ -1 +1 @@
1
- {"version":3,"file":"VirtualizedComboboxList.js","sources":["../../../src/components/Combobox/VirtualizedComboboxList.tsx"],"sourcesContent":["import { Check } from '@phosphor-icons/react/dist/ssr/Check'\nimport { useVirtualizer } from '@tanstack/react-virtual'\nimport { useRef, useEffect } from 'react'\n\nimport { CommandEmpty, CommandItem } from '../Command'\n\nimport { ComboboxOptionWithTooltip } from './ComboboxOptionWithTooltip'\nimport type { VirtualizedComboboxListProps } from './types'\n\nexport const VirtualizedComboboxList = <T extends object>({\n localOptions,\n loading,\n loadingPlaceholder,\n emptyMessage,\n value,\n getOptionValue,\n getOptionLabel,\n handleSelect,\n renderOption,\n maxHeight,\n hasNextPage,\n loadingMore,\n onLoadMore,\n}: VirtualizedComboboxListProps<T>) => {\n const parentRef = useRef<HTMLDivElement>(null)\n const hasTriggeredRef = useRef(false)\n\n const totalCount = localOptions.length\n const PREFETCH_THRESHOLD = 25\n\n const rowVirtualizer = useVirtualizer({\n count: totalCount,\n getScrollElement: () => parentRef.current,\n estimateSize: () => 40,\n overscan: 10,\n })\n\n useEffect(() => {\n hasTriggeredRef.current = false\n }, [totalCount])\n\n const virtualItems = rowVirtualizer.getVirtualItems()\n\n useEffect(() => {\n if (virtualItems.length === 0 || !hasNextPage || loadingMore || loading || hasTriggeredRef.current) {\n return\n }\n\n const lastVisibleItem = virtualItems.at(-1)\n const itemsFromEnd = totalCount - (lastVisibleItem?.index ?? 0)\n\n if (itemsFromEnd <= PREFETCH_THRESHOLD) {\n hasTriggeredRef.current = true\n onLoadMore()\n }\n }, [virtualItems, totalCount, hasNextPage, loadingMore, loading, onLoadMore])\n\n if (loading && localOptions.length === 0) {\n return (\n <div className=\"text-muted-foreground flex items-center justify-center py-6 text-sm\">{loadingPlaceholder}</div>\n )\n }\n\n if (localOptions.length === 0 && !loading && !loadingMore) {\n return <CommandEmpty>{emptyMessage}</CommandEmpty>\n }\n\n const getItemAtIndex = (index: number) => {\n const option = localOptions[index]\n const isSelected = value === getOptionValue(option)\n return { option, isSelected }\n }\n\n return (\n <div ref={parentRef} className=\"overflow-auto\" style={{ maxHeight }} onWheel={(event) => event.stopPropagation()}>\n <div style={{ height: `${rowVirtualizer.getTotalSize()}px`, position: 'relative' }}>\n {rowVirtualizer.getVirtualItems().map((virtualRow) => {\n const { option, isSelected } = getItemAtIndex(virtualRow.index)\n const optionValue = getOptionValue(option)\n\n return (\n <div\n key={optionValue}\n data-index={virtualRow.index}\n ref={(el) => {\n if (el) rowVirtualizer.measureElement(el)\n }}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n <CommandItem value={optionValue} onSelect={handleSelect}>\n {renderOption ? (\n renderOption(option, isSelected)\n ) : (\n <>\n <Check className={`mr-2 h-4 w-4 ${isSelected ? 'opacity-100' : 'opacity-0'}`} />\n <ComboboxOptionWithTooltip label={getOptionLabel(option)} />\n </>\n )}\n </CommandItem>\n </div>\n )\n })}\n </div>\n {loadingMore && (\n <div className=\"flex items-center justify-center py-2 text-sm text-neutral-500\">{loadingPlaceholder}</div>\n )}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"VirtualizedComboboxList.js","sources":["../../../src/components/Combobox/VirtualizedComboboxList.tsx"],"sourcesContent":["import { Check } from '@phosphor-icons/react/dist/ssr/Check'\nimport { useVirtualizer } from '@tanstack/react-virtual'\nimport { useRef, useEffect } from 'react'\n\nimport { CommandEmpty, CommandItem } from '../Command'\n\nimport { ComboboxOptionWithTooltip } from './ComboboxOptionWithTooltip'\nimport type { VirtualizedComboboxListProps } from './types'\n\nexport const VirtualizedComboboxList = <T extends object>({\n localOptions,\n loading,\n loadingPlaceholder,\n emptyMessage,\n value,\n getOptionValue,\n getOptionLabel,\n handleSelect,\n renderOption,\n maxHeight,\n hasNextPage,\n loadingMore,\n onLoadMore,\n}: VirtualizedComboboxListProps<T>) => {\n const parentRef = useRef<HTMLDivElement>(null)\n const hasTriggeredRef = useRef(false)\n\n const totalCount = localOptions.length\n const PREFETCH_THRESHOLD = 25\n\n const rowVirtualizer = useVirtualizer({\n count: totalCount,\n getScrollElement: () => parentRef.current,\n estimateSize: () => 40,\n overscan: 10,\n })\n\n useEffect(() => {\n hasTriggeredRef.current = false\n }, [totalCount])\n\n const virtualItems = rowVirtualizer.getVirtualItems()\n\n useEffect(() => {\n if (virtualItems.length === 0 || !hasNextPage || loadingMore || loading || hasTriggeredRef.current) {\n return\n }\n\n const lastVisibleItem = virtualItems.at(-1)\n const itemsFromEnd = totalCount - (lastVisibleItem?.index ?? 0)\n\n if (itemsFromEnd <= PREFETCH_THRESHOLD) {\n hasTriggeredRef.current = true\n onLoadMore()\n }\n }, [virtualItems, totalCount, hasNextPage, loadingMore, loading, onLoadMore])\n\n if (loading && localOptions.length === 0) {\n return (\n <div className=\"text-muted-foreground flex items-center justify-center py-6 text-sm\">{loadingPlaceholder}</div>\n )\n }\n\n if (localOptions.length === 0 && !loading && !loadingMore) {\n return <CommandEmpty>{emptyMessage}</CommandEmpty>\n }\n\n const getItemAtIndex = (index: number) => {\n const option = localOptions[index]\n const isSelected = value === getOptionValue(option)\n return { option, isSelected }\n }\n\n return (\n <div\n ref={parentRef}\n className=\"overflow-auto overscroll-contain\"\n style={{ maxHeight }}\n onWheel={(event) => event.stopPropagation()}\n >\n <div style={{ height: `${rowVirtualizer.getTotalSize()}px`, position: 'relative' }}>\n {rowVirtualizer.getVirtualItems().map((virtualRow) => {\n const { option, isSelected } = getItemAtIndex(virtualRow.index)\n const optionValue = getOptionValue(option)\n\n return (\n <div\n key={optionValue}\n data-index={virtualRow.index}\n ref={(el) => {\n if (el) rowVirtualizer.measureElement(el)\n }}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n <CommandItem value={optionValue} onSelect={handleSelect}>\n {renderOption ? (\n renderOption(option, isSelected)\n ) : (\n <>\n <Check className={`mr-2 h-4 w-4 ${isSelected ? 'opacity-100' : 'opacity-0'}`} />\n <ComboboxOptionWithTooltip label={getOptionLabel(option)} />\n </>\n )}\n </CommandItem>\n </div>\n )\n })}\n </div>\n {loadingMore && (\n <div className=\"flex items-center justify-center py-2 text-sm text-neutral-500\">{loadingPlaceholder}</div>\n )}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
@@ -12,11 +12,11 @@ declare const SelectContent: React.ForwardRefExoticComponent<Omit<SelectPrimitiv
12
12
  declare const SelectLabel: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectLabelProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
13
13
  declare const SelectItem: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
14
14
  declare const SelectSeparator: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectSeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
15
- export { SelectContent, SelectGroup, SelectItem, SelectLabel, SelectRoot, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, };
16
- type Option = {
15
+ export type Option = {
17
16
  value: string;
18
17
  label: React.ReactElement | string | number;
19
18
  };
19
+ export { SelectContent, SelectGroup, SelectItem, SelectLabel, SelectRoot, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, };
20
20
  type Props = {
21
21
  onValueChange?: (value: string) => void;
22
22
  defaultValue?: string;
@@ -29,5 +29,6 @@ type Props = {
29
29
  id?: string;
30
30
  onKeyDown?: (event: React.KeyboardEvent<HTMLButtonElement>) => void;
31
31
  container?: HTMLElement;
32
+ renderOption?: (option: Option) => React.ReactNode;
32
33
  };
33
- export declare function Select({ onValueChange, defaultValue, value, options, placeholder, className, disabled, error, id, onKeyDown, container, ...props }: Readonly<Props>): import("react/jsx-runtime").JSX.Element;
34
+ export declare function Select({ onValueChange, defaultValue, value, options, placeholder, className, disabled, error, id, onKeyDown, container, renderOption, ...props }: Readonly<Props>): import("react/jsx-runtime").JSX.Element;
@@ -37,9 +37,9 @@ const SelectContent = React.forwardRef(({ className, children, position = "poppe
37
37
  SelectPrimitive.Content,
38
38
  {
39
39
  ref,
40
+ sideOffset: 4,
40
41
  className: cn(
41
- "text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-[#fff] shadow-md",
42
- position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
42
+ "text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-[var(--radix-select-content-available-height,300px)] min-w-[8rem] overflow-hidden rounded-md border bg-[#fff] shadow-md",
43
43
  className
44
44
  ),
45
45
  position,
@@ -51,7 +51,7 @@ const SelectContent = React.forwardRef(({ className, children, position = "poppe
51
51
  {
52
52
  className: cn(
53
53
  "p-1",
54
- position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
54
+ position === "popper" && "w-[var(--radix-select-trigger-width)] md:w-auto md:min-w-[var(--radix-select-trigger-width)]"
55
55
  ),
56
56
  children
57
57
  }
@@ -93,6 +93,7 @@ function Select({
93
93
  id,
94
94
  onKeyDown,
95
95
  container,
96
+ renderOption,
96
97
  ...props
97
98
  }) {
98
99
  const [open, setOpen] = React.useState(false);
@@ -154,7 +155,22 @@ function Select({
154
155
  event.preventDefault();
155
156
  }
156
157
  },
157
- children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, "data-testid": option.value, children: option.label }, option.value))
158
+ children: options.map(
159
+ (option) => renderOption ? /* @__PURE__ */ jsxs(
160
+ SelectPrimitive.Item,
161
+ {
162
+ value: option.value,
163
+ "data-testid": option.value,
164
+ textValue: typeof option.label === "string" ? option.label : void 0,
165
+ className: "focus:text-accent-foreground relative flex w-full cursor-default items-start rounded-sm px-2 py-1.5 text-sm outline-none select-none focus:bg-neutral-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
166
+ children: [
167
+ /* @__PURE__ */ jsx("span", { className: "hidden", children: /* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children: option.label }) }),
168
+ renderOption(option)
169
+ ]
170
+ },
171
+ option.value
172
+ ) : /* @__PURE__ */ jsx(SelectItem, { value: option.value, "data-testid": option.value, children: option.label }, option.value)
173
+ )
158
174
  }
159
175
  )
160
176
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"Select.js","sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["import { CaretDown, CaretUp, Check } from '@phosphor-icons/react/dist/ssr'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport * as React from 'react'\n\nimport { buttonVariants } from '../Button'\n\nimport { cn } from '@/lib/utils'\n\nconst SelectRoot = SelectPrimitive.Root\n\nconst SelectGroup = SelectPrimitive.Group\n\nconst SelectValue = SelectPrimitive.Value\n\nconst SelectTrigger = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger ref={ref} className={className} {...props}>\n {children}\n <SelectPrimitive.Icon asChild>\n <CaretDown className=\"h-4 w-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n))\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\nconst SelectScrollUpButton = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn('flex cursor-default items-center justify-center py-1', className)}\n {...props}\n >\n <CaretUp className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\nconst SelectScrollDownButton = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn('flex cursor-default items-center justify-center py-1', className)}\n {...props}\n >\n <CaretDown className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName\n\nconst SelectContent = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> & {\n container?: HTMLElement\n }\n>(({ className, children, position = 'popper', container, ...props }, ref) => (\n <SelectPrimitive.Portal container={container}>\n <SelectPrimitive.Content\n ref={ref}\n className={cn(\n 'text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-[#fff] shadow-md',\n position === 'popper' &&\n 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n className,\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n 'p-1',\n position === 'popper' &&\n 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]',\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n))\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\nconst SelectLabel = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label ref={ref} className={cn('py-1.5 pr-2 pl-8 text-sm font-semibold', className)} {...props} />\n))\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\nconst SelectItem = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'focus:text-accent-foreground relative flex w-full cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none select-none focus:bg-neutral-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n))\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\nconst SelectSeparator = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator ref={ref} className={cn('bg-muted -mx-1 my-1 h-px', className)} {...props} />\n))\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport {\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectRoot,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n}\ntype Option = {\n value: string\n label: React.ReactElement | string | number\n}\ntype Props = {\n onValueChange?: (value: string) => void\n defaultValue?: string\n value?: string\n placeholder?: string\n options: Array<Option>\n className?: string\n disabled?: boolean\n error?: boolean | string\n id?: string\n onKeyDown?: (event: React.KeyboardEvent<HTMLButtonElement>) => void\n container?: HTMLElement\n}\n\nexport function Select({\n onValueChange,\n defaultValue,\n value,\n options,\n placeholder,\n className,\n disabled = false,\n error,\n id,\n onKeyDown,\n container,\n ...props\n}: Readonly<Props>) {\n const [open, setOpen] = React.useState(false)\n\n const handleOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n if (!disabled) setOpen(nextOpen)\n },\n [disabled],\n )\n\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <SelectRoot\n {...props}\n open={open}\n onOpenChange={handleOpenChange}\n onValueChange={onValueChange}\n value={value}\n defaultValue={defaultValue}\n disabled={disabled}\n >\n <SelectTrigger\n id={id}\n onKeyDown={onKeyDown}\n aria-invalid={error ? 'true' : 'false'}\n className={cn(\n buttonVariants({ variant: 'input', size: 'lg' }),\n 'flex justify-between',\n error && 'ring-error-400 focus-within:ring-error-700 border-none ring-1',\n className,\n )}\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 <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n <SelectContent\n container={container}\n onPointerDownOutside={(event) => {\n if (!container) return\n const original = (event as unknown as Record<string, unknown>).detail as\n | { originalEvent?: PointerEvent }\n | undefined\n if (!original?.originalEvent?.composedPath) return\n if (original.originalEvent.composedPath().includes(container)) {\n event.preventDefault()\n }\n }}\n >\n {options.map((option) => (\n <SelectItem key={option.value} value={option.value} data-testid={option.value}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </SelectRoot>\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":"Select.js","sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["import { CaretDown, CaretUp, Check } from '@phosphor-icons/react/dist/ssr'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport * as React from 'react'\n\nimport { buttonVariants } from '../Button'\n\nimport { cn } from '@/lib/utils'\n\nconst SelectRoot = SelectPrimitive.Root\n\nconst SelectGroup = SelectPrimitive.Group\n\nconst SelectValue = SelectPrimitive.Value\n\nconst SelectTrigger = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger ref={ref} className={className} {...props}>\n {children}\n <SelectPrimitive.Icon asChild>\n <CaretDown className=\"h-4 w-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n))\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\nconst SelectScrollUpButton = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn('flex cursor-default items-center justify-center py-1', className)}\n {...props}\n >\n <CaretUp className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\nconst SelectScrollDownButton = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn('flex cursor-default items-center justify-center py-1', className)}\n {...props}\n >\n <CaretDown className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName\n\nconst SelectContent = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> & {\n container?: HTMLElement\n }\n>(({ className, children, position = 'popper', container, ...props }, ref) => (\n <SelectPrimitive.Portal container={container}>\n <SelectPrimitive.Content\n ref={ref}\n sideOffset={4}\n className={cn(\n 'text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-[var(--radix-select-content-available-height,300px)] min-w-[8rem] overflow-hidden rounded-md border bg-[#fff] shadow-md',\n className,\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n 'p-1',\n position === 'popper' &&\n 'w-[var(--radix-select-trigger-width)] md:w-auto md:min-w-[var(--radix-select-trigger-width)]',\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n))\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\nconst SelectLabel = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label ref={ref} className={cn('py-1.5 pr-2 pl-8 text-sm font-semibold', className)} {...props} />\n))\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\nconst SelectItem = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'focus:text-accent-foreground relative flex w-full cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none select-none focus:bg-neutral-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n))\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\nconst SelectSeparator = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator ref={ref} className={cn('bg-muted -mx-1 my-1 h-px', className)} {...props} />\n))\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport type Option = {\n value: string\n label: React.ReactElement | string | number\n}\n\nexport {\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectRoot,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n}\n\ntype Props = {\n onValueChange?: (value: string) => void\n defaultValue?: string\n value?: string\n placeholder?: string\n options: Array<Option>\n className?: string\n disabled?: boolean\n error?: boolean | string\n id?: string\n onKeyDown?: (event: React.KeyboardEvent<HTMLButtonElement>) => void\n container?: HTMLElement\n renderOption?: (option: Option) => React.ReactNode\n}\n\nexport function Select({\n onValueChange,\n defaultValue,\n value,\n options,\n placeholder,\n className,\n disabled = false,\n error,\n id,\n onKeyDown,\n container,\n renderOption,\n ...props\n}: Readonly<Props>) {\n const [open, setOpen] = React.useState(false)\n\n const handleOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n if (!disabled) setOpen(nextOpen)\n },\n [disabled],\n )\n\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <SelectRoot\n {...props}\n open={open}\n onOpenChange={handleOpenChange}\n onValueChange={onValueChange}\n value={value}\n defaultValue={defaultValue}\n disabled={disabled}\n >\n <SelectTrigger\n id={id}\n onKeyDown={onKeyDown}\n aria-invalid={error ? 'true' : 'false'}\n className={cn(\n buttonVariants({ variant: 'input', size: 'lg' }),\n 'flex justify-between',\n error && 'ring-error-400 focus-within:ring-error-700 border-none ring-1',\n className,\n )}\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 <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n <SelectContent\n container={container}\n onPointerDownOutside={(event) => {\n if (!container) return\n const original = (event as unknown as Record<string, unknown>).detail as\n | { originalEvent?: PointerEvent }\n | undefined\n if (!original?.originalEvent?.composedPath) return\n if (original.originalEvent.composedPath().includes(container)) {\n event.preventDefault()\n }\n }}\n >\n {options.map((option) =>\n renderOption ? (\n <SelectPrimitive.Item\n key={option.value}\n value={option.value}\n data-testid={option.value}\n textValue={typeof option.label === 'string' ? option.label : undefined}\n className=\"focus:text-accent-foreground relative flex w-full cursor-default items-start rounded-sm px-2 py-1.5 text-sm outline-none select-none focus:bg-neutral-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50\"\n >\n <span className=\"hidden\">\n <SelectPrimitive.ItemText>{option.label}</SelectPrimitive.ItemText>\n </span>\n {renderOption(option)}\n </SelectPrimitive.Item>\n ) : (\n <SelectItem key={option.value} value={option.value} data-testid={option.value}>\n {option.label}\n </SelectItem>\n ),\n )}\n </SelectContent>\n </SelectRoot>\n {typeof error === 'string' && <span className=\"text-error-500 text-sm\">{error}</span>}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "periplo-ui",
3
3
  "description": "IATI UI library",
4
4
  "private": false,
5
- "version": "3.54.0",
5
+ "version": "3.56.0",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
8
8
  "types": "dist/index.d.ts",