Bin
2025-12-17 1d710f844b65d9bfdf986a71a3b924cd70598a41
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import type { FC, ReactNode } from "react";
 
export type SelectOptionData<T = any> = {
  value: T;
  label?: string;
  hidden?: boolean;
  disabled?: boolean;
  children?: SelectOptionData<T>[];
};
 
export enum SelectSize {
  SMALL = "small",
  MEDIUM = "medium",
  LARGE = "large",
}
 
export type SelectOption<T> = string | number | SelectOptionData<T>;
 
export type OptionProps = {
  value: any;
  label?: string;
  isOptionSelected?: boolean;
  disabled?: boolean;
  style?: any;
  multiple?: boolean;
  onSelect?: () => void;
  isIndeterminate?: boolean;
  className?: string;
};
 
type ExtractStructOption<T> = T extends SelectOptionData ? T["value"] : never;
type ExtractPrimitiveOption<T> = T extends string | number ? T : never;
export type ExtractOption<T> = T extends SelectOption<any>
  ? T extends SelectOptionData<any>
    ? ExtractStructOption<T>
    : ExtractPrimitiveOption<T>
  : never;
 
export type ExtractValue<T, A extends SelectOption<T>[]> = A[number] extends { value: infer U } ? U : A[number];
 
export type SelectProps<T, A extends SelectOption<T>[]> = {
  label?: string;
  description?: string;
  options: A;
  value?: ExtractOption<A[number]> | null;
  defaultValue?: ExtractOption<A[number]> | null;
  validate?: any;
  required?: boolean;
  skip?: boolean;
  labelProps?: any;
  placeholder?: ReactNode;
  triggerClassName?: string;
  contentClassName?: string;
  ghost?: boolean;
  width?: string;
  icon?: any;
  fieldProps?: any;
  error?: boolean;
  autoSelectFirst?: boolean;
  searchable?: boolean;
  searchPlaceholder?: string;
  ref?: React.Ref<HTMLSelectElement>;
  selectedValueRenderer?: FC<{ option: A[number]; index: number }>;
  optionRenderer?: FC<{ option: A[number]; index: number }>;
  dropdown?: any;
  testId?: string;
  searchFilter?: (option: any, queryString: string) => boolean;
  onChange?: (value: any) => void | false;
  setValue?: (value: ExtractOption<A>) => void;
  header?: string | FC | JSX.Element;
  multiple?: boolean;
  disabled?: boolean;
  triggerProps?: any;
  isInline?: boolean;
  isLoading?: boolean;
  dataTestid?: string;
  size?: SelectSize | undefined;
  onSearch?: (value: string) => void;
  selectFirstIfEmpty?: boolean;
  renderSelected?: (selectedOptions?: A[number][], placeholder?: string) => React.ReactNode | string;
  isVirtualList?: boolean;
  loadMore?: () => void;
  pageSize?: number;
  page?: number;
  itemCount?: number;
  onClose?: () => void;
  onOpen?: () => void;
} & SelectVirtualizedProps &
  Omit<React.SelectHTMLAttributes<HTMLSelectElement>, "value" | "placeholder">;
 
type ToNever<T> = {
  [key in keyof T]?: never;
};
 
type VirtualizedProps = {
  overscan?: number;
  estimateSize?: number;
  virtualizedTotal?: number;
  rootMargin?: string;
  onBottomReached?: () => void;
  onTopReached?: () => void;
};
 
type SelectVirtualizedProps =
  | ({
      virtualized?: false;
    } & ToNever<VirtualizedProps>)
  | ({
      virtualized: true;
    } & VirtualizedProps);