@stackline/react-multiselect-dropdown 18.0.0 → 18.0.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/index.d.cts CHANGED
@@ -1,7 +1,20 @@
1
- import { CSSProperties, ReactNode, ForwardedRef, ReactElement } from 'react';
1
+ import { CSSProperties, ReactNode, HTMLAttributes, Ref, AriaAttributes, ButtonHTMLAttributes, InputHTMLAttributes, ForwardedRef, ReactElement } from 'react';
2
2
 
3
3
  type PrimitiveItem = string | number | boolean;
4
4
  type DropdownItem = PrimitiveItem | Record<string, any>;
5
+ type DropdownItemKey<T = DropdownItem> = T extends PrimitiveItem ? string : Extract<keyof T, string>;
6
+ type DropdownSpaceOptionAction = 'toggle' | 'toggle-and-next';
7
+ interface DropdownKeyboardSettings {
8
+ space?: boolean;
9
+ spaceOptionAction?: DropdownSpaceOptionAction;
10
+ tab?: boolean;
11
+ arrows?: boolean;
12
+ escape?: boolean;
13
+ backspaceRemovesLastWhenSearchEmpty?: boolean;
14
+ deleteRemovesFocusedBadge?: boolean;
15
+ /** @deprecated Use `backspaceRemovesLastWhenSearchEmpty` instead. */
16
+ backspace?: boolean;
17
+ }
5
18
  interface DropdownSettings<T = DropdownItem> {
6
19
  singleSelection?: boolean;
7
20
  text?: string;
@@ -12,20 +25,20 @@ interface DropdownSettings<T = DropdownItem> {
12
25
  filterUnSelectAllText?: string;
13
26
  enableFilterSelectAll?: boolean;
14
27
  enableSearchFilter?: boolean;
15
- searchBy?: string[];
28
+ searchBy?: DropdownItemKey<T>[];
16
29
  maxHeight?: number;
17
30
  badgeShowLimit?: number;
18
31
  classes?: string;
19
32
  limitSelection?: number;
20
33
  disabled?: boolean;
21
34
  searchPlaceholderText?: string;
22
- groupBy?: string | ((item: T) => string);
35
+ groupBy?: DropdownItemKey<T> | ((item: T) => string);
23
36
  showCheckbox?: boolean;
24
37
  noDataLabel?: string;
25
38
  searchAutofocus?: boolean;
26
39
  lazyLoading?: boolean;
27
- labelKey?: string;
28
- primaryKey?: string;
40
+ labelKey?: DropdownItemKey<T>;
41
+ primaryKey?: DropdownItemKey<T>;
29
42
  position?: 'top' | 'bottom';
30
43
  autoPosition?: boolean;
31
44
  loading?: boolean;
@@ -49,7 +62,11 @@ interface DropdownSettings<T = DropdownItem> {
49
62
  openDropdownAriaLabel?: string;
50
63
  closeDropdownAriaLabel?: string;
51
64
  loadingText?: string;
65
+ keyboard?: DropdownKeyboardSettings;
52
66
  }
67
+ type ResolvedDropdownSettings<T = DropdownItem> = Required<Omit<DropdownSettings<T>, 'keyboard'>> & {
68
+ keyboard: Required<DropdownKeyboardSettings>;
69
+ };
53
70
  interface DropdownRenderContext<T = DropdownItem> {
54
71
  item: T;
55
72
  label: string;
@@ -59,6 +76,208 @@ interface DropdownRenderContext<T = DropdownItem> {
59
76
  toggle: () => void;
60
77
  remove: () => void;
61
78
  }
79
+ interface MultiSelectDropdownSlotActions<T = DropdownItem> {
80
+ openDropdown: () => void;
81
+ closeDropdown: () => void;
82
+ toggleDropdown: () => void;
83
+ clearSelection: () => void;
84
+ selectItem: (item: T) => void;
85
+ removeItem: (item: T) => void;
86
+ selectAll: (items?: T[]) => void;
87
+ deSelectAll: (items?: T[]) => void;
88
+ toggleGroup: (groupName: string, items: T[]) => void;
89
+ addFilterNewItem: () => Promise<void>;
90
+ setFilter: (value: string) => void;
91
+ }
92
+ interface MultiSelectDropdownSlotState<T = DropdownItem> {
93
+ settings: ResolvedDropdownSettings<T>;
94
+ isOpen: boolean;
95
+ filter: string;
96
+ selectedItems: T[];
97
+ visibleBadges: T[];
98
+ hiddenBadgeCount: number;
99
+ filteredItems: T[];
100
+ selectableItems: T[];
101
+ allFilteredSelected: boolean;
102
+ hasFilteredResults: boolean;
103
+ loading: boolean;
104
+ listboxId: string;
105
+ activeDescendantId?: string;
106
+ label: string;
107
+ }
108
+ interface MultiSelectDropdownSlotBase<T = DropdownItem> {
109
+ state: MultiSelectDropdownSlotState<T>;
110
+ actions: MultiSelectDropdownSlotActions<T>;
111
+ }
112
+ interface MultiSelectDropdownOptionSlot<T = DropdownItem> {
113
+ item: T;
114
+ id: string;
115
+ key: string;
116
+ label: string;
117
+ selected: boolean;
118
+ disabled: boolean;
119
+ index: number;
120
+ groupName?: string;
121
+ }
122
+ interface MultiSelectDropdownGroupSlot<T = DropdownItem> {
123
+ name: string;
124
+ items: T[];
125
+ enabledItems: T[];
126
+ selected: boolean;
127
+ disabled: boolean;
128
+ index: number;
129
+ }
130
+ type MultiSelectDropdownSlotComponent<P> = (props: P) => ReactNode;
131
+ interface MultiSelectDropdownSlots<T = DropdownItem> {
132
+ Root?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
133
+ props: HTMLAttributes<HTMLDivElement> & {
134
+ ref: Ref<HTMLDivElement>;
135
+ };
136
+ children: ReactNode;
137
+ }>;
138
+ Trigger?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
139
+ props: HTMLAttributes<HTMLDivElement> & AriaAttributes & {
140
+ ref: Ref<HTMLDivElement>;
141
+ };
142
+ children: ReactNode;
143
+ }>;
144
+ Value?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
145
+ props: HTMLAttributes<HTMLDivElement>;
146
+ children: ReactNode;
147
+ }>;
148
+ Placeholder?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
149
+ props: HTMLAttributes<HTMLSpanElement>;
150
+ text: string;
151
+ }>;
152
+ SingleValue?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
153
+ props: HTMLAttributes<HTMLSpanElement>;
154
+ item: T;
155
+ label: string;
156
+ }>;
157
+ BadgeList?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
158
+ props: HTMLAttributes<HTMLDivElement>;
159
+ items: T[];
160
+ children: ReactNode;
161
+ }>;
162
+ Badge?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
163
+ props: HTMLAttributes<HTMLSpanElement>;
164
+ item: T;
165
+ label: string;
166
+ children: ReactNode;
167
+ removeButton: ReactNode;
168
+ }>;
169
+ BadgeLabel?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
170
+ props: HTMLAttributes<HTMLSpanElement>;
171
+ item: T;
172
+ label: string;
173
+ children: ReactNode;
174
+ }>;
175
+ BadgeRemove?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
176
+ props: ButtonHTMLAttributes<HTMLButtonElement>;
177
+ item: T;
178
+ label: string;
179
+ icon: ReactNode;
180
+ }>;
181
+ Actions?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
182
+ props: HTMLAttributes<HTMLDivElement>;
183
+ children: ReactNode;
184
+ }>;
185
+ OverflowCounter?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
186
+ props: HTMLAttributes<HTMLSpanElement>;
187
+ count: number;
188
+ }>;
189
+ ClearAll?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
190
+ props: ButtonHTMLAttributes<HTMLButtonElement>;
191
+ icon: ReactNode;
192
+ }>;
193
+ Arrow?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
194
+ props: ButtonHTMLAttributes<HTMLButtonElement> & AriaAttributes;
195
+ icon: ReactNode;
196
+ direction: 'up' | 'down';
197
+ }>;
198
+ Menu?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
199
+ props: HTMLAttributes<HTMLDivElement> & {
200
+ ref: Ref<HTMLDivElement>;
201
+ };
202
+ children: ReactNode;
203
+ position: 'top' | 'bottom';
204
+ appendToBody: boolean;
205
+ }>;
206
+ Toolbar?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
207
+ props: HTMLAttributes<HTMLDivElement>;
208
+ children: ReactNode;
209
+ }>;
210
+ BulkActions?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
211
+ props: HTMLAttributes<HTMLDivElement>;
212
+ children: ReactNode;
213
+ }>;
214
+ SelectAll?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
215
+ props: ButtonHTMLAttributes<HTMLButtonElement>;
216
+ checked: boolean;
217
+ label: string;
218
+ checkbox: ReactNode;
219
+ }>;
220
+ AddNewItem?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
221
+ props: ButtonHTMLAttributes<HTMLButtonElement>;
222
+ query: string;
223
+ label: string;
224
+ }>;
225
+ Search?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
226
+ props: HTMLAttributes<HTMLDivElement>;
227
+ inputProps: InputHTMLAttributes<HTMLInputElement> & {
228
+ ref: Ref<HTMLInputElement>;
229
+ };
230
+ clearButtonProps: ButtonHTMLAttributes<HTMLButtonElement>;
231
+ query: string;
232
+ icon: ReactNode;
233
+ clearIcon: ReactNode;
234
+ }>;
235
+ OptionList?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
236
+ props: HTMLAttributes<HTMLDivElement> & AriaAttributes & {
237
+ ref: Ref<HTMLDivElement>;
238
+ };
239
+ children: ReactNode;
240
+ }>;
241
+ Group?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
242
+ props: HTMLAttributes<HTMLDivElement> & AriaAttributes;
243
+ group: MultiSelectDropdownGroupSlot<T>;
244
+ header: ReactNode;
245
+ children: ReactNode;
246
+ }>;
247
+ GroupHeader?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
248
+ props: HTMLAttributes<HTMLDivElement>;
249
+ group: MultiSelectDropdownGroupSlot<T>;
250
+ action: ReactNode;
251
+ }>;
252
+ GroupAction?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
253
+ props: ButtonHTMLAttributes<HTMLButtonElement>;
254
+ group: MultiSelectDropdownGroupSlot<T>;
255
+ label: string;
256
+ }>;
257
+ Option?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
258
+ props: HTMLAttributes<HTMLDivElement> & AriaAttributes;
259
+ option: MultiSelectDropdownOptionSlot<T>;
260
+ checkbox: ReactNode;
261
+ children: ReactNode;
262
+ }>;
263
+ Checkbox?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
264
+ props: HTMLAttributes<HTMLSpanElement>;
265
+ checked: boolean;
266
+ context: 'option' | 'selectAll';
267
+ }>;
268
+ LoadingState?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
269
+ props: HTMLAttributes<HTMLDivElement>;
270
+ text: string;
271
+ }>;
272
+ EmptyState?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
273
+ props: HTMLAttributes<HTMLDivElement>;
274
+ query: string;
275
+ text: string;
276
+ }>;
277
+ MenuFooter?: MultiSelectDropdownSlotComponent<MultiSelectDropdownSlotBase<T> & {
278
+ props: HTMLAttributes<HTMLDivElement>;
279
+ }>;
280
+ }
62
281
  interface MultiSelectDropdownHandle<T = DropdownItem> {
63
282
  openDropdown: () => void;
64
283
  closeDropdown: () => void;
@@ -102,6 +321,112 @@ interface MultiSelectDropdownProps<T = DropdownItem> {
102
321
  closeDropdown: () => void;
103
322
  }) => ReactNode;
104
323
  renderEmptyState?: (query: string) => ReactNode;
324
+ slots?: MultiSelectDropdownSlots<T>;
325
+ }
326
+ interface HeadlessDropdownOption<T = DropdownItem> {
327
+ item: T;
328
+ key: string;
329
+ id: string;
330
+ label: string;
331
+ selected: boolean;
332
+ disabled: boolean;
333
+ index: number;
334
+ groupName?: string;
335
+ }
336
+ interface HeadlessDropdownGroup<T = DropdownItem> {
337
+ name: string;
338
+ items: HeadlessDropdownOption<T>[];
339
+ selected: boolean;
340
+ disabled: boolean;
341
+ }
342
+ interface UseMultiSelectDropdownProps<T = DropdownItem> extends Omit<MultiSelectDropdownProps<T>, 'className' | 'style' | 'renderItem' | 'renderBadge' | 'renderSearch' | 'renderEmptyState'> {
343
+ id?: string;
344
+ }
345
+ interface UseMultiSelectStateProps<T = DropdownItem> extends Omit<MultiSelectDropdownProps<T>, 'className' | 'style' | 'loading' | 'renderItem' | 'renderBadge' | 'renderSearch' | 'renderEmptyState'> {
346
+ onSelectionShouldClose?: () => void;
347
+ }
348
+ interface UseMultiSelectStateReturn<T = DropdownItem> {
349
+ settings: ResolvedDropdownSettings<T>;
350
+ filter: string;
351
+ setFilter: (value: string) => void;
352
+ selectedItems: T[];
353
+ allItems: T[];
354
+ filteredItems: T[];
355
+ selectableItems: T[];
356
+ visibleBadges: T[];
357
+ hiddenBadgeCount: number;
358
+ allFilteredSelected: boolean;
359
+ isSelected: (item: T) => boolean;
360
+ isDisabled: (item: T) => boolean;
361
+ getItemLabel: (item: T) => string;
362
+ getItemKey: (item: T) => string;
363
+ selectItem: (item: T) => void;
364
+ removeItem: (item: T) => void;
365
+ removeLastSelectedItem: () => void;
366
+ selectAll: (items?: T[], filteredSelection?: boolean) => void;
367
+ deSelectAll: (items?: T[], filteredSelection?: boolean) => void;
368
+ clearSelection: () => void;
369
+ toggleGroup: (groupName: string, items: T[]) => void;
370
+ addFilterNewItem: () => Promise<void>;
371
+ }
372
+ interface UseMultiSelectDropdownReturn<T = DropdownItem> {
373
+ settings: ResolvedDropdownSettings<T>;
374
+ isOpen: boolean;
375
+ filter: string;
376
+ setFilter: (value: string) => void;
377
+ selectedItems: T[];
378
+ selectedOptions: HeadlessDropdownOption<T>[];
379
+ options: HeadlessDropdownOption<T>[];
380
+ groups: HeadlessDropdownGroup<T>[];
381
+ visibleOptions: HeadlessDropdownOption<T>[];
382
+ visibleBadges: T[];
383
+ hiddenBadgeCount: number;
384
+ allFilteredSelected: boolean;
385
+ hasFilteredResults: boolean;
386
+ activeDescendantId?: string;
387
+ listboxId: string;
388
+ label: string;
389
+ openDropdown: () => void;
390
+ closeDropdown: () => void;
391
+ toggleDropdown: () => void;
392
+ clearSelection: () => void;
393
+ selectItem: (item: T) => void;
394
+ removeItem: (item: T) => void;
395
+ selectAll: (items?: T[]) => void;
396
+ deSelectAll: (items?: T[]) => void;
397
+ toggleGroup: (groupName: string, items: T[]) => void;
398
+ addFilterNewItem: () => Promise<void>;
399
+ isSelected: (item: T) => boolean;
400
+ isDisabled: (item: T) => boolean;
401
+ getItemLabel: (item: T) => string;
402
+ getItemKey: (item: T) => string;
403
+ getRootProps: <E extends HTMLElement = HTMLDivElement>(props?: HTMLAttributes<E> & {
404
+ ref?: Ref<E>;
405
+ }) => HTMLAttributes<E> & {
406
+ ref: (node: E | null) => void;
407
+ };
408
+ getTriggerProps: <E extends HTMLElement = HTMLButtonElement>(props?: ButtonHTMLAttributes<E> & {
409
+ ref?: Ref<E>;
410
+ }) => ButtonHTMLAttributes<E> & AriaAttributes & {
411
+ ref: (node: E | null) => void;
412
+ };
413
+ getListboxProps: <E extends HTMLElement = HTMLDivElement>(props?: HTMLAttributes<E> & {
414
+ ref?: Ref<E>;
415
+ }) => HTMLAttributes<E> & AriaAttributes & {
416
+ ref: (node: E | null) => void;
417
+ };
418
+ getOptionProps: <E extends HTMLElement = HTMLDivElement>(optionOrItem: HeadlessDropdownOption<T> | T, props?: HTMLAttributes<E> & {
419
+ ref?: Ref<E>;
420
+ }) => HTMLAttributes<E> & AriaAttributes & {
421
+ ref: (node: E | null) => void;
422
+ };
423
+ getSearchInputProps: <E extends HTMLInputElement = HTMLInputElement>(props?: InputHTMLAttributes<E> & {
424
+ ref?: Ref<E>;
425
+ }) => InputHTMLAttributes<E> & AriaAttributes & {
426
+ ref: (node: E | null) => void;
427
+ };
428
+ getClearAllButtonProps: <E extends HTMLElement = HTMLButtonElement>(props?: ButtonHTMLAttributes<E>) => ButtonHTMLAttributes<E> & AriaAttributes;
429
+ getRemoveButtonProps: <E extends HTMLElement = HTMLButtonElement>(item: T, props?: ButtonHTMLAttributes<E>) => ButtonHTMLAttributes<E> & AriaAttributes;
105
430
  }
106
431
 
107
432
  type MultiSelectComponent = <T extends DropdownItem = DropdownItem>(props: MultiSelectDropdownProps<T> & {
@@ -110,4 +435,21 @@ type MultiSelectComponent = <T extends DropdownItem = DropdownItem>(props: Multi
110
435
  declare const ReactMultiSelectDropdown: MultiSelectComponent;
111
436
  declare const MultiSelectDropdown: MultiSelectComponent;
112
437
 
113
- export { type DropdownItem, type DropdownRenderContext, type DropdownSettings, MultiSelectDropdown, type MultiSelectDropdownHandle, type MultiSelectDropdownProps, type PrimitiveItem, ReactMultiSelectDropdown };
438
+ declare function useMultiSelectDropdown<T extends DropdownItem = DropdownItem>({ id, data, settings: incomingSettings, selectedItems: controlledSelectedItems, defaultSelectedItems, onChange, onSelect, onDeSelect, onSelectAll, onDeSelectAll, onOpen, onClose, onScrollToEnd, onFilterSelectAll, onFilterDeSelectAll, onAddFilterNewItem, onGroupSelect, onGroupDeSelect }: UseMultiSelectDropdownProps<T>): UseMultiSelectDropdownReturn<T>;
439
+
440
+ declare function useMultiSelectState<T extends DropdownItem = DropdownItem>({ data, settings: incomingSettings, selectedItems: controlledSelectedItems, defaultSelectedItems, onChange, onSelect, onDeSelect, onSelectAll, onDeSelectAll, onFilterSelectAll, onFilterDeSelectAll, onAddFilterNewItem, onGroupSelect, onGroupDeSelect, onSelectionShouldClose }: UseMultiSelectStateProps<T>): UseMultiSelectStateReturn<T>;
441
+
442
+ type TypedMultiSelectDropdownComponent<T extends DropdownItem> = (props: MultiSelectDropdownProps<T> & {
443
+ ref?: ForwardedRef<MultiSelectDropdownHandle<T>>;
444
+ }) => ReactElement | null;
445
+ interface TypedMultiSelectDropdownFamily<T extends DropdownItem> {
446
+ Dropdown: TypedMultiSelectDropdownComponent<T>;
447
+ MultiSelectDropdown: TypedMultiSelectDropdownComponent<T>;
448
+ useDropdown: (props: UseMultiSelectDropdownProps<T>) => UseMultiSelectDropdownReturn<T>;
449
+ useSelectionState: (props: UseMultiSelectStateProps<T>) => UseMultiSelectStateReturn<T>;
450
+ defineSettings: (settings: DropdownSettings<T>) => DropdownSettings<T>;
451
+ defineSlots: (slots: MultiSelectDropdownSlots<T>) => MultiSelectDropdownSlots<T>;
452
+ }
453
+ declare function createMultiSelectDropdown<T extends DropdownItem = never>(): TypedMultiSelectDropdownFamily<T>;
454
+
455
+ export { type DropdownItem, type DropdownItemKey, type DropdownKeyboardSettings, type DropdownRenderContext, type DropdownSettings, type DropdownSpaceOptionAction, type HeadlessDropdownGroup, type HeadlessDropdownOption, MultiSelectDropdown, type MultiSelectDropdownGroupSlot, type MultiSelectDropdownHandle, type MultiSelectDropdownOptionSlot, type MultiSelectDropdownProps, type MultiSelectDropdownSlotActions, type MultiSelectDropdownSlotBase, type MultiSelectDropdownSlotComponent, type MultiSelectDropdownSlotState, type MultiSelectDropdownSlots, type PrimitiveItem, ReactMultiSelectDropdown, type ResolvedDropdownSettings, type TypedMultiSelectDropdownComponent, type TypedMultiSelectDropdownFamily, type UseMultiSelectDropdownProps, type UseMultiSelectDropdownReturn, type UseMultiSelectStateProps, type UseMultiSelectStateReturn, createMultiSelectDropdown, useMultiSelectDropdown, useMultiSelectState };