@stack-spot/citric-react 0.42.0 → 0.43.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.
- package/dist/citric.css +239 -1
- package/dist/components/Autocomplete.d.ts +370 -0
- package/dist/components/Autocomplete.d.ts.map +1 -0
- package/dist/components/Autocomplete.js +474 -0
- package/dist/components/Autocomplete.js.map +1 -0
- package/dist/components/CitricComponent.d.ts +1 -1
- package/dist/components/CitricComponent.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Autocomplete.tsx +1038 -0
- package/src/components/CitricComponent.ts +1 -1
- package/src/index.ts +1 -0
package/dist/citric.css
CHANGED
|
@@ -1895,7 +1895,8 @@ nav[data-citric="menu"].rounded-items, [data-citric="menu"].rounded-items nav {
|
|
|
1895
1895
|
[data-citric="select"] select,
|
|
1896
1896
|
[data-citric="rich-select"],
|
|
1897
1897
|
[data-citric="multi-select"],
|
|
1898
|
-
[data-citric="textarea"]
|
|
1898
|
+
[data-citric="textarea"],
|
|
1899
|
+
[data-citric="autocomplete"] {
|
|
1899
1900
|
height: 2.5rem;
|
|
1900
1901
|
padding: var(--spacing-3);
|
|
1901
1902
|
outline: none;
|
|
@@ -2796,6 +2797,243 @@ a[data-citric="badge"] {
|
|
|
2796
2797
|
}
|
|
2797
2798
|
|
|
2798
2799
|
|
|
2800
|
+
[data-citric="autocomplete"] {
|
|
2801
|
+
--default-padding: 4px 8px;
|
|
2802
|
+
--default-max-height: 300px;
|
|
2803
|
+
--animation-duration: 0.3s;
|
|
2804
|
+
position: relative;
|
|
2805
|
+
height: auto;
|
|
2806
|
+
display: flex;
|
|
2807
|
+
flex-direction: row;
|
|
2808
|
+
align-items: center;
|
|
2809
|
+
box-sizing: border-box;
|
|
2810
|
+
|
|
2811
|
+
&:after {
|
|
2812
|
+
content: '';
|
|
2813
|
+
position: absolute;
|
|
2814
|
+
pointer-events: none;
|
|
2815
|
+
top: 0;
|
|
2816
|
+
left: 0;
|
|
2817
|
+
right: 0;
|
|
2818
|
+
bottom: 0;
|
|
2819
|
+
border: 1px solid var(--border-color, var(--light-600));
|
|
2820
|
+
border-radius: var(--radius-xs);
|
|
2821
|
+
transition: border var(--animation-duration);
|
|
2822
|
+
}
|
|
2823
|
+
|
|
2824
|
+
&.focused,
|
|
2825
|
+
&:has(:focus) {
|
|
2826
|
+
&:after {
|
|
2827
|
+
border: 2px solid var(--border-color, var(--scheme-500, var(--primary-500)));
|
|
2828
|
+
}
|
|
2829
|
+
|
|
2830
|
+
.dropdown-panel:after {
|
|
2831
|
+
border: 2px solid var(--border-color, var(--scheme-500, var(--primary-500)));
|
|
2832
|
+
border-top: none;
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
|
|
2836
|
+
&:has(:disabled),
|
|
2837
|
+
&.disabled {
|
|
2838
|
+
background-color: var(--light-500);
|
|
2839
|
+
border-color: var(--light-600);
|
|
2840
|
+
color: var(--light-700);
|
|
2841
|
+
cursor: not-allowed;
|
|
2842
|
+
|
|
2843
|
+
[data-citric="progress-circular"] {
|
|
2844
|
+
border-color: var(--light-400);
|
|
2845
|
+
}
|
|
2846
|
+
}
|
|
2847
|
+
|
|
2848
|
+
header {
|
|
2849
|
+
display: flex;
|
|
2850
|
+
gap: 6px;
|
|
2851
|
+
align-items: center;
|
|
2852
|
+
margin: 0px !important;
|
|
2853
|
+
min-width: 80px;
|
|
2854
|
+
justify-content: space-between;
|
|
2855
|
+
flex: 1;
|
|
2856
|
+
flex-wrap: wrap;
|
|
2857
|
+
outline: none;
|
|
2858
|
+
|
|
2859
|
+
.input-container {
|
|
2860
|
+
display: flex;
|
|
2861
|
+
flex: 1;
|
|
2862
|
+
flex-wrap: wrap;
|
|
2863
|
+
flex-direction: row;
|
|
2864
|
+
|
|
2865
|
+
input {
|
|
2866
|
+
all: unset;
|
|
2867
|
+
width: 0px;
|
|
2868
|
+
min-width: 30px;
|
|
2869
|
+
flex-grow: 1;
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
|
|
2873
|
+
.end-adornment {
|
|
2874
|
+
display: flex;
|
|
2875
|
+
align-items: center;
|
|
2876
|
+
gap: 8px;
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
.loader {
|
|
2881
|
+
display: none;
|
|
2882
|
+
}
|
|
2883
|
+
|
|
2884
|
+
/* Dropdown panel */
|
|
2885
|
+
.dropdown-panel {
|
|
2886
|
+
max-height: 0;
|
|
2887
|
+
overflow: hidden;
|
|
2888
|
+
transition: max-height var(--animation-duration) ease-in;
|
|
2889
|
+
position: absolute;
|
|
2890
|
+
top: calc(100% - 3px);
|
|
2891
|
+
z-index: 9999;
|
|
2892
|
+
left: 0;
|
|
2893
|
+
right: 0;
|
|
2894
|
+
background-color: var(--light-300);
|
|
2895
|
+
display: flex;
|
|
2896
|
+
flex-direction: column;
|
|
2897
|
+
gap: 8px;
|
|
2898
|
+
border-bottom-left-radius: var(--radius-xs);
|
|
2899
|
+
border-bottom-right-radius: var(--radius-xs);
|
|
2900
|
+
|
|
2901
|
+
.message {
|
|
2902
|
+
padding: var(--padding, var(--default-padding));
|
|
2903
|
+
text-align: center;
|
|
2904
|
+
color: var(--light-700);
|
|
2905
|
+
font-style: italic;
|
|
2906
|
+
}
|
|
2907
|
+
|
|
2908
|
+
>.options {
|
|
2909
|
+
margin: 0;
|
|
2910
|
+
padding: 0;
|
|
2911
|
+
list-style: none;
|
|
2912
|
+
display: flex;
|
|
2913
|
+
flex-direction: column;
|
|
2914
|
+
flex: 1;
|
|
2915
|
+
overflow: hidden;
|
|
2916
|
+
|
|
2917
|
+
>.option {
|
|
2918
|
+
padding: var(--padding, var(--default-padding));
|
|
2919
|
+
display: flex;
|
|
2920
|
+
transition: background-color 0.3s;
|
|
2921
|
+
cursor: pointer;
|
|
2922
|
+
align-items: center;
|
|
2923
|
+
gap: 8px;
|
|
2924
|
+
|
|
2925
|
+
&:not(:last-child) {
|
|
2926
|
+
border-bottom: 1px solid var(--light-600);
|
|
2927
|
+
}
|
|
2928
|
+
|
|
2929
|
+
&:hover {
|
|
2930
|
+
background-color: var(--scheme-500, var(--light-500));
|
|
2931
|
+
}
|
|
2932
|
+
|
|
2933
|
+
&.highlighted {
|
|
2934
|
+
background-color: var(--scheme-500, var(--light-500));
|
|
2935
|
+
}
|
|
2936
|
+
|
|
2937
|
+
&.selected {
|
|
2938
|
+
background-color: var(--scheme-400, var(--light-400));
|
|
2939
|
+
|
|
2940
|
+
&:hover {
|
|
2941
|
+
background-color: var(--scheme-500, var(--light-500));
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
|
|
2945
|
+
&.create-option {
|
|
2946
|
+
color: var(--light-contrastText);
|
|
2947
|
+
font-weight: 500;
|
|
2948
|
+
border-bottom: 2px solid var(--light-600);
|
|
2949
|
+
|
|
2950
|
+
&:hover {
|
|
2951
|
+
background-color: var(--scheme-300, var(--primary-300));
|
|
2952
|
+
}
|
|
2953
|
+
}
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2957
|
+
&:after {
|
|
2958
|
+
content: '';
|
|
2959
|
+
position: absolute;
|
|
2960
|
+
top: 0;
|
|
2961
|
+
bottom: 0;
|
|
2962
|
+
left: 0;
|
|
2963
|
+
right: 0;
|
|
2964
|
+
pointer-events: none;
|
|
2965
|
+
border: 1px solid var(--border-color, var(--light-600));
|
|
2966
|
+
border-top: none;
|
|
2967
|
+
transition: border var(--animation-duration);
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2970
|
+
&::-webkit-scrollbar,
|
|
2971
|
+
::-webkit-scrollbar {
|
|
2972
|
+
width: 0.5rem;
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2975
|
+
|
|
2976
|
+
&[aria-busy="true"],
|
|
2977
|
+
&[aria-busy=""] {
|
|
2978
|
+
cursor: progress !important;
|
|
2979
|
+
|
|
2980
|
+
.loader {
|
|
2981
|
+
display: block;
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2984
|
+
|
|
2985
|
+
&:not(.open) {
|
|
2986
|
+
.dropdown-panel {
|
|
2987
|
+
opacity: 0;
|
|
2988
|
+
animation: var(--animation-duration) autocomplete-delayed-opacity;
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
|
|
2992
|
+
&.open {
|
|
2993
|
+
header:after {
|
|
2994
|
+
transform: rotate(180deg);
|
|
2995
|
+
}
|
|
2996
|
+
|
|
2997
|
+
.dropdown-panel {
|
|
2998
|
+
max-height: var(--max-height, var(--default-max-height));
|
|
2999
|
+
opacity: 1;
|
|
3000
|
+
|
|
3001
|
+
.options {
|
|
3002
|
+
overflow: auto;
|
|
3003
|
+
animation: var(--animation-duration) autocomplete-delayed-overflow;
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
|
|
3009
|
+
@keyframes autocomplete-delayed-overflow {
|
|
3010
|
+
0% {
|
|
3011
|
+
overflow: hidden;
|
|
3012
|
+
}
|
|
3013
|
+
|
|
3014
|
+
99% {
|
|
3015
|
+
overflow: hidden;
|
|
3016
|
+
}
|
|
3017
|
+
|
|
3018
|
+
100% {
|
|
3019
|
+
overflow: auto;
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
|
|
3023
|
+
@keyframes autocomplete-delayed-opacity {
|
|
3024
|
+
0% {
|
|
3025
|
+
opacity: 1;
|
|
3026
|
+
}
|
|
3027
|
+
|
|
3028
|
+
99% {
|
|
3029
|
+
opacity: 1;
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
100% {
|
|
3033
|
+
opacity: 0;
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
|
|
2799
3037
|
[data-citric="alert"] {
|
|
2800
3038
|
padding: var(--spacing-4);
|
|
2801
3039
|
font: var(--font-body2);
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import { ColorPaletteName, ColorSchemeName } from '@stack-spot/portal-theme';
|
|
2
|
+
export interface CustomSelectedTagsConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Color scheme for the tags (badges).
|
|
5
|
+
*/
|
|
6
|
+
colorScheme?: ColorSchemeName;
|
|
7
|
+
/**
|
|
8
|
+
* Color palette for the tags (badges).
|
|
9
|
+
*/
|
|
10
|
+
colorPalette?: ColorPaletteName;
|
|
11
|
+
/**
|
|
12
|
+
* Appearance of the tags (badges).
|
|
13
|
+
* @default 'circle'
|
|
14
|
+
*/
|
|
15
|
+
appearance?: 'square' | 'circle';
|
|
16
|
+
/**
|
|
17
|
+
* Maximum number of tags to show before displaying "+N more".
|
|
18
|
+
*/
|
|
19
|
+
maxItems?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface BaseAutocompleteProps<T, Multiple extends boolean = false> {
|
|
22
|
+
/**
|
|
23
|
+
* The list of options available for selection.
|
|
24
|
+
*/
|
|
25
|
+
options: T[];
|
|
26
|
+
/**
|
|
27
|
+
* The current value(s) selected.
|
|
28
|
+
* - Single selection: T | undefined
|
|
29
|
+
* - Multiple selection: T[]
|
|
30
|
+
*/
|
|
31
|
+
value: Multiple extends true ? T[] : (T | undefined);
|
|
32
|
+
/**
|
|
33
|
+
* Callback fired when the value changes (user selects/removes an option).
|
|
34
|
+
* This is the main callback for getting the final selected value(s).
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```tsx
|
|
38
|
+
* // Single selection
|
|
39
|
+
* <Autocomplete
|
|
40
|
+
* value={user}
|
|
41
|
+
* onChange={(selectedUser) => {
|
|
42
|
+
* console.log('Selected:', selectedUser)
|
|
43
|
+
* setUser(selectedUser)
|
|
44
|
+
* }}
|
|
45
|
+
* />
|
|
46
|
+
*
|
|
47
|
+
* // Multiple selection
|
|
48
|
+
* <Autocomplete
|
|
49
|
+
* multiple
|
|
50
|
+
* value={selectedUsers}
|
|
51
|
+
* onChange={(users) => {
|
|
52
|
+
* console.log('Selected users:', users)
|
|
53
|
+
* setSelectedUsers(users)
|
|
54
|
+
* }}
|
|
55
|
+
* />
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
onChange: Multiple extends true ? (value: T[]) => void : (value: T | undefined) => void;
|
|
59
|
+
/**
|
|
60
|
+
* If true, enables multiple selection mode.
|
|
61
|
+
* @default false
|
|
62
|
+
*/
|
|
63
|
+
multiple?: Multiple;
|
|
64
|
+
/**
|
|
65
|
+
* If true, allows the user to enter values that are not in the options list.
|
|
66
|
+
* @default false
|
|
67
|
+
*/
|
|
68
|
+
freeSolo?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* If true, allows creating new options when no match is found.
|
|
71
|
+
* Shows an "Add [value]" option at the top of the list.
|
|
72
|
+
* @default false
|
|
73
|
+
*/
|
|
74
|
+
creatable?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Callback fired when a new option is created.
|
|
77
|
+
* Required when creatable is true and you want manual control.
|
|
78
|
+
*/
|
|
79
|
+
onCreate?: (inputValue: string) => void;
|
|
80
|
+
/**
|
|
81
|
+
* Function to create a new option object from the input value.
|
|
82
|
+
* Used when creatable is true and onCreate is NOT defined.
|
|
83
|
+
* Allows automatic option creation on Enter key.
|
|
84
|
+
*
|
|
85
|
+
* Note: This prop has no effect when onCreate is defined, as onCreate takes precedence.
|
|
86
|
+
*
|
|
87
|
+
* @param inputValue - The text typed by the user
|
|
88
|
+
* @returns A new option object
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```tsx
|
|
92
|
+
* // Auto-create tags on Enter
|
|
93
|
+
* <Autocomplete
|
|
94
|
+
* multiple
|
|
95
|
+
* creatable
|
|
96
|
+
* freeSolo
|
|
97
|
+
* getOptionFromInput={(text) => ({
|
|
98
|
+
* id: Date.now(),
|
|
99
|
+
* name: text,
|
|
100
|
+
* isCustom: true
|
|
101
|
+
* })}
|
|
102
|
+
* />
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
getOptionFromInput?: (inputValue: string) => T;
|
|
106
|
+
/**
|
|
107
|
+
* The input value (controlled mode).
|
|
108
|
+
* Use this when you need full control over the input text.
|
|
109
|
+
* Usually used with onInputChange for controlled components.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```tsx
|
|
113
|
+
* const [inputValue, setInputValue] = useState('')
|
|
114
|
+
*
|
|
115
|
+
* <Autocomplete
|
|
116
|
+
* inputValue={inputValue}
|
|
117
|
+
* onInputChange={setInputValue}
|
|
118
|
+
* options={options}
|
|
119
|
+
* />
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
inputValue?: string;
|
|
123
|
+
/**
|
|
124
|
+
* Callback fired when the input text changes (user types).
|
|
125
|
+
* Use this to control the input value or perform side effects like API calls.
|
|
126
|
+
* Different from onChange which fires when an option is selected.
|
|
127
|
+
*
|
|
128
|
+
* @param value - The current text in the input field
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```tsx
|
|
132
|
+
* // Debounced API search
|
|
133
|
+
* <Autocomplete
|
|
134
|
+
* onInputChange={(text) => {
|
|
135
|
+
* console.log('User typed:', text)
|
|
136
|
+
* debouncedSearch(text)
|
|
137
|
+
* }}
|
|
138
|
+
* />
|
|
139
|
+
*
|
|
140
|
+
* // Controlled input
|
|
141
|
+
* <Autocomplete
|
|
142
|
+
* inputValue={inputValue}
|
|
143
|
+
* onInputChange={(text) => setInputValue(text.toUpperCase())}
|
|
144
|
+
* />
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
onInputChange?: (value: string) => void;
|
|
148
|
+
/**
|
|
149
|
+
* A function to render the item label.
|
|
150
|
+
* @default "the item's toString() result."
|
|
151
|
+
*/
|
|
152
|
+
renderLabel?: (option: T) => string;
|
|
153
|
+
/**
|
|
154
|
+
* A function to generate a unique key for each option.
|
|
155
|
+
*/
|
|
156
|
+
renderKey?: (option: T) => string | number | undefined;
|
|
157
|
+
/**
|
|
158
|
+
* A function to render an option in the dropdown.
|
|
159
|
+
*/
|
|
160
|
+
renderOption?: (option: T) => React.ReactNode;
|
|
161
|
+
/**
|
|
162
|
+
* Custom function to render the selected values display area in multiple mode.
|
|
163
|
+
* When defined, gives you full control over how selected values are displayed.
|
|
164
|
+
* The customSelectedTags prop has no effect when this is defined.
|
|
165
|
+
*
|
|
166
|
+
* @param values - Array of selected options
|
|
167
|
+
* @param onRemove - Function to call when user wants to remove an option
|
|
168
|
+
* @returns React element to display selected values
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```tsx
|
|
172
|
+
* <Autocomplete
|
|
173
|
+
* multiple
|
|
174
|
+
* renderSelected={(values, onRemove) => (
|
|
175
|
+
* <div style={{ display: 'flex', gap: '4px', flexWrap: 'wrap' }}>
|
|
176
|
+
* {values.map(user => (
|
|
177
|
+
* <div key={user.id} style={{ background: '#e3f2fd', padding: '4px 8px', borderRadius: '12px' }}>
|
|
178
|
+
* <Avatar src={user.avatar} size="xs" />
|
|
179
|
+
* {user.name}
|
|
180
|
+
* <button onClick={() => onRemove(user)}>×</button>
|
|
181
|
+
* </div>
|
|
182
|
+
* ))}
|
|
183
|
+
* </div>
|
|
184
|
+
* )}
|
|
185
|
+
* />
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
renderSelected?: (values: T[], onRemove: (option: T) => void) => React.ReactElement;
|
|
189
|
+
/**
|
|
190
|
+
* Configuration for the default selected tags appearance in multiple mode.
|
|
191
|
+
* Has no effect when renderSelected is defined.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```tsx
|
|
195
|
+
* <Autocomplete
|
|
196
|
+
* multiple
|
|
197
|
+
* customSelectedTags={{
|
|
198
|
+
* colorScheme: 'primary',
|
|
199
|
+
* appearance: 'square',
|
|
200
|
+
* maxItems: 3
|
|
201
|
+
* }}
|
|
202
|
+
* />
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
customSelectedTags?: CustomSelectedTagsConfig;
|
|
206
|
+
/**
|
|
207
|
+
* Custom filter function for options.
|
|
208
|
+
* When not set, the filter will use the text returned by renderLabel (case-insensitive includes).
|
|
209
|
+
*
|
|
210
|
+
* @param options - The full list of options
|
|
211
|
+
* @param inputValue - The current input text
|
|
212
|
+
* @returns Filtered array of options
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```tsx
|
|
216
|
+
* // Search by name OR email
|
|
217
|
+
* <Autocomplete
|
|
218
|
+
* filterOptions={(options, input) =>
|
|
219
|
+
* options.filter(user =>
|
|
220
|
+
* user.name.toLowerCase().includes(input.toLowerCase()) ||
|
|
221
|
+
* user.email.toLowerCase().includes(input.toLowerCase())
|
|
222
|
+
* )
|
|
223
|
+
* }
|
|
224
|
+
* />
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
filterOptions?: (options: T[], inputValue: string) => T[];
|
|
228
|
+
/**
|
|
229
|
+
* If true, shows a loading indicator.
|
|
230
|
+
* @default false
|
|
231
|
+
*/
|
|
232
|
+
loading?: boolean;
|
|
233
|
+
/**
|
|
234
|
+
* If true, the component is disabled.
|
|
235
|
+
* @default false
|
|
236
|
+
*/
|
|
237
|
+
disabled?: boolean;
|
|
238
|
+
/**
|
|
239
|
+
* Placeholder text for the input.
|
|
240
|
+
*/
|
|
241
|
+
placeholder?: string;
|
|
242
|
+
/**
|
|
243
|
+
* Maximum height for the dropdown panel in pixels.
|
|
244
|
+
*/
|
|
245
|
+
maxHeight?: number;
|
|
246
|
+
/**
|
|
247
|
+
* If true, automatically highlights the first option.
|
|
248
|
+
* @default false
|
|
249
|
+
*/
|
|
250
|
+
autoHighlight?: boolean;
|
|
251
|
+
/**
|
|
252
|
+
* If true, clears the input value when an option is selected.
|
|
253
|
+
* Only applies when multiple is true.
|
|
254
|
+
* When false, the input keeps the text after selection, useful for adding multiple similar items quickly.
|
|
255
|
+
*
|
|
256
|
+
* Note: Adding multiple tags with similar prefixes when clearOnSelect={false}, you can select "React",
|
|
257
|
+
* then easily select "React Native"
|
|
258
|
+
* without retyping "React" from scratch
|
|
259
|
+
* @default true (for multiple mode)
|
|
260
|
+
*
|
|
261
|
+
* @example
|
|
262
|
+
* ```tsx
|
|
263
|
+
* // Clear input after each selection (default)
|
|
264
|
+
* <Autocomplete multiple clearOnSelect />
|
|
265
|
+
*
|
|
266
|
+
* // Keep input text after selection
|
|
267
|
+
* const [tags, setTags] = useState<Tag[]>([])
|
|
268
|
+
*
|
|
269
|
+
* <Autocomplete
|
|
270
|
+
* multiple
|
|
271
|
+
* clearOnSelect={false}
|
|
272
|
+
* value={tags}
|
|
273
|
+
* onChange={setTags}
|
|
274
|
+
* options={availableTags}
|
|
275
|
+
* renderLabel={tag => tag.name}
|
|
276
|
+
* />
|
|
277
|
+
* ```
|
|
278
|
+
*/
|
|
279
|
+
clearOnSelect?: boolean;
|
|
280
|
+
/**
|
|
281
|
+
* If true, the popup will open on input focus.
|
|
282
|
+
* @default true
|
|
283
|
+
*/
|
|
284
|
+
openOnFocus?: boolean;
|
|
285
|
+
/**
|
|
286
|
+
* Text to display when no options are available.
|
|
287
|
+
*/
|
|
288
|
+
noOptionsText?: string;
|
|
289
|
+
/**
|
|
290
|
+
* Text to display when loading.
|
|
291
|
+
*/
|
|
292
|
+
loadingText?: string;
|
|
293
|
+
/**
|
|
294
|
+
* Callback fired when the user scrolls to the end of the options list.
|
|
295
|
+
* Useful for implementing infinite scroll/pagination.
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* ```tsx
|
|
299
|
+
* <Autocomplete
|
|
300
|
+
* options={options}
|
|
301
|
+
* onScrollEnd={() => fetchMoreOptions()}
|
|
302
|
+
* loading={isFetchingMore}
|
|
303
|
+
* />
|
|
304
|
+
* ```
|
|
305
|
+
*/
|
|
306
|
+
onScrollEnd?: () => void;
|
|
307
|
+
/**
|
|
308
|
+
* Margin in pixels before the end of the list to trigger onScrollEnd.
|
|
309
|
+
* @default 200
|
|
310
|
+
*/
|
|
311
|
+
scrollEndMargin?: number;
|
|
312
|
+
/**
|
|
313
|
+
* Color scheme for the autocomplete component.
|
|
314
|
+
* Applies the theme's color scheme to the component root.
|
|
315
|
+
*/
|
|
316
|
+
colorScheme?: ColorSchemeName;
|
|
317
|
+
/**
|
|
318
|
+
* The id attribute for the input element.
|
|
319
|
+
* Useful for associating with a label element.
|
|
320
|
+
*/
|
|
321
|
+
id?: string;
|
|
322
|
+
}
|
|
323
|
+
export type AutocompleteProps<T, Multiple extends boolean = false> = Omit<React.JSX.IntrinsicElements['div'], 'ref' | 'onChange'> & BaseAutocompleteProps<T, Multiple>;
|
|
324
|
+
/**
|
|
325
|
+
* A combination of a text input and a dropdown that suggests options as the user types.
|
|
326
|
+
* Supports both single and multiple selection modes, similar to Material-UI Autocomplete.
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* Basic usage (single selection):
|
|
330
|
+
* ```tsx
|
|
331
|
+
* const [value, setValue] = useState<Option | null>(null)
|
|
332
|
+
*
|
|
333
|
+
* <Autocomplete
|
|
334
|
+
* options={options}
|
|
335
|
+
* value={value}
|
|
336
|
+
* onChange={setValue}
|
|
337
|
+
* renderLabel={o => o.name}
|
|
338
|
+
* renderKey={o => o.id}
|
|
339
|
+
* />
|
|
340
|
+
* ```
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* Multiple selection with tags:
|
|
344
|
+
* ```tsx
|
|
345
|
+
* const [value, setValue] = useState<Option[]>([])
|
|
346
|
+
*
|
|
347
|
+
* <Autocomplete
|
|
348
|
+
* multiple
|
|
349
|
+
* options={options}
|
|
350
|
+
* value={value}
|
|
351
|
+
* onChange={setValue}
|
|
352
|
+
* renderLabel={o => o.name}
|
|
353
|
+
* renderKey={o => o.id}
|
|
354
|
+
* />
|
|
355
|
+
* ```
|
|
356
|
+
*
|
|
357
|
+
* @example
|
|
358
|
+
* Free solo (allow custom values):
|
|
359
|
+
* ```tsx
|
|
360
|
+
* <Autocomplete
|
|
361
|
+
* freeSolo
|
|
362
|
+
* options={options}
|
|
363
|
+
* value={value}
|
|
364
|
+
* onChange={setValue}
|
|
365
|
+
* renderLabel={o => o.name}
|
|
366
|
+
* />
|
|
367
|
+
* ```
|
|
368
|
+
*/
|
|
369
|
+
export declare const Autocomplete: <T, Multiple extends boolean = false>(props: AutocompleteProps<T, Multiple>) => React.ReactElement;
|
|
370
|
+
//# sourceMappingURL=Autocomplete.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Autocomplete.d.ts","sourceRoot":"","sources":["../../src/components/Autocomplete.tsx"],"names":[],"mappings":"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"}
|