@stackline/react-multiselect-dropdown 17.0.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/index.js ADDED
@@ -0,0 +1,2002 @@
1
+ // src/MultiSelectDropdown.tsx
2
+ import {
3
+ forwardRef,
4
+ useEffect,
5
+ useImperativeHandle,
6
+ useLayoutEffect,
7
+ useMemo,
8
+ useRef,
9
+ useState
10
+ } from "react";
11
+ import { createPortal } from "react-dom";
12
+
13
+ // src/styles.ts
14
+ var STYLE_ID = "stackline-react-multiselect-dropdown-styles";
15
+ var styles = `
16
+ .rmsd-root {
17
+ --rmsd-primary: #3f51b5;
18
+ --rmsd-primary-soft: rgba(63, 81, 181, 0.12);
19
+ --rmsd-bg: #ffffff;
20
+ --rmsd-surface: #f5f7fb;
21
+ --rmsd-surface-muted: #e8eaf6;
22
+ --rmsd-border: #c5cae9;
23
+ --rmsd-border-strong: #7986cb;
24
+ --rmsd-ink: #212121;
25
+ --rmsd-muted: #5f6368;
26
+ --rmsd-chip-bg: #e8eaf6;
27
+ --rmsd-chip-text: #303f9f;
28
+ --rmsd-chip-remove: #303f9f;
29
+ --rmsd-divider: rgba(125, 119, 134, 0.16);
30
+ --rmsd-section-bg: #f5f7fb;
31
+ --rmsd-focus: rgba(63, 81, 181, 0.32);
32
+ --rmsd-shadow: 0 1px 2px rgba(33, 33, 33, 0.16), 0 12px 32px rgba(63, 81, 181, 0.12);
33
+ --rmsd-shadow-soft: 0 1px 2px rgba(33, 33, 33, 0.12), 0 4px 12px rgba(33, 33, 33, 0.08);
34
+ position: relative;
35
+ display: block;
36
+ width: 100%;
37
+ color: var(--rmsd-ink);
38
+ font: inherit;
39
+ }
40
+
41
+ .rmsd-root *,
42
+ .rmsd-root *::before,
43
+ .rmsd-root *::after,
44
+ .rmsd-menu,
45
+ .rmsd-menu *,
46
+ .rmsd-menu *::before,
47
+ .rmsd-menu *::after {
48
+ box-sizing: border-box;
49
+ }
50
+
51
+ .rmsd-trigger {
52
+ position: relative;
53
+ display: flex;
54
+ align-items: center;
55
+ flex-wrap: wrap;
56
+ width: 100%;
57
+ min-height: 56px;
58
+ gap: 8px;
59
+ border: 1px solid var(--rmsd-border);
60
+ border-radius: 18px;
61
+ background-color: var(--rmsd-bg);
62
+ color: var(--rmsd-ink);
63
+ padding: 11px 54px 11px 16px;
64
+ box-shadow: var(--rmsd-shadow-soft);
65
+ text-align: left;
66
+ cursor: pointer;
67
+ line-height: 1.45;
68
+ transition: border-color 160ms ease, box-shadow 160ms ease, background-color 160ms ease, transform 160ms ease;
69
+ }
70
+
71
+ .rmsd-trigger:hover {
72
+ border-color: var(--rmsd-border-strong);
73
+ }
74
+
75
+ .rmsd-root[data-open="true"] .rmsd-trigger,
76
+ .rmsd-trigger:focus-visible {
77
+ outline: none;
78
+ border-color: var(--rmsd-primary);
79
+ box-shadow: 0 0 0 3px var(--rmsd-focus), var(--rmsd-shadow-soft);
80
+ }
81
+
82
+ .rmsd-trigger.rmsd-disabled {
83
+ cursor: not-allowed;
84
+ opacity: 0.68;
85
+ }
86
+
87
+ .rmsd-value {
88
+ display: flex;
89
+ flex: 1 1 auto;
90
+ min-width: 0;
91
+ align-items: center;
92
+ gap: 8px;
93
+ flex-wrap: wrap;
94
+ }
95
+
96
+ .rmsd-placeholder,
97
+ .rmsd-single-value {
98
+ min-width: 0;
99
+ color: var(--rmsd-muted);
100
+ font-size: 0.95rem;
101
+ overflow: hidden;
102
+ text-overflow: ellipsis;
103
+ white-space: nowrap;
104
+ }
105
+
106
+ .rmsd-single-value {
107
+ color: var(--rmsd-ink);
108
+ font-weight: 500;
109
+ }
110
+
111
+ .rmsd-badge-list {
112
+ display: flex;
113
+ flex: 1 1 auto;
114
+ min-width: 0;
115
+ align-items: center;
116
+ gap: 8px;
117
+ flex-wrap: wrap;
118
+ }
119
+
120
+ .rmsd-badge {
121
+ position: relative;
122
+ display: inline-block;
123
+ vertical-align: middle;
124
+ min-height: 32px;
125
+ max-width: 100%;
126
+ border-radius: 999px;
127
+ background-color: var(--rmsd-chip-bg);
128
+ color: var(--rmsd-chip-text);
129
+ padding: 6px 30px 6px 12px;
130
+ box-shadow: inset 0 0 0 1px rgba(103, 80, 164, 0.08);
131
+ line-height: 1.35;
132
+ white-space: normal;
133
+ overflow-wrap: anywhere;
134
+ }
135
+
136
+ .rmsd-badge-label {
137
+ display: inline-flex;
138
+ align-items: center;
139
+ min-width: 0;
140
+ max-width: 100%;
141
+ line-height: 1.3;
142
+ font-weight: 500;
143
+ white-space: normal;
144
+ overflow-wrap: anywhere;
145
+ }
146
+
147
+ .rmsd-badge-remove,
148
+ .rmsd-clear,
149
+ .rmsd-search-clear,
150
+ .rmsd-arrow-button,
151
+ .rmsd-group-action {
152
+ appearance: none;
153
+ border: 0;
154
+ background: transparent;
155
+ color: inherit;
156
+ cursor: pointer;
157
+ font: inherit;
158
+ padding: 0;
159
+ }
160
+
161
+ .rmsd-badge-remove {
162
+ position: absolute;
163
+ top: 50%;
164
+ right: 10px;
165
+ display: inline-grid;
166
+ width: 16px;
167
+ height: 16px;
168
+ place-items: center;
169
+ transform: translateY(-50%);
170
+ color: var(--rmsd-chip-remove);
171
+ font-size: 12px;
172
+ line-height: 1;
173
+ }
174
+
175
+ .rmsd-overflow {
176
+ display: inline-flex;
177
+ align-items: center;
178
+ justify-content: center;
179
+ min-width: 0;
180
+ min-height: 0;
181
+ color: var(--rmsd-muted);
182
+ font-size: 0.8rem;
183
+ font-weight: 600;
184
+ }
185
+
186
+ .rmsd-root.rmsd-has-overflow:not(.skin-classic) .rmsd-trigger {
187
+ padding-right: 104px;
188
+ }
189
+
190
+ .rmsd-root.rmsd-has-overflow:not(.skin-classic):not(.rmsd-has-clear) .rmsd-trigger {
191
+ padding-right: 74px;
192
+ }
193
+
194
+ .rmsd-root.rmsd-has-overflow:not(.skin-classic) .rmsd-overflow {
195
+ position: absolute;
196
+ top: 50%;
197
+ right: 76px;
198
+ transform: translateY(-50%);
199
+ z-index: 1;
200
+ }
201
+
202
+ .rmsd-root.rmsd-has-overflow:not(.skin-classic):not(.rmsd-has-clear) .rmsd-overflow {
203
+ right: 42px;
204
+ }
205
+
206
+ .rmsd-actions {
207
+ position: absolute;
208
+ top: 50%;
209
+ right: 16px;
210
+ display: inline-flex;
211
+ align-items: center;
212
+ gap: 6px;
213
+ transform: translateY(-50%);
214
+ }
215
+
216
+ .rmsd-clear {
217
+ display: inline-grid;
218
+ width: 20px;
219
+ height: 20px;
220
+ place-items: center;
221
+ border-radius: 999px;
222
+ color: var(--rmsd-muted);
223
+ font-size: 14px;
224
+ line-height: 1;
225
+ }
226
+
227
+ .rmsd-icon {
228
+ display: block;
229
+ width: 100%;
230
+ height: 100%;
231
+ fill: currentColor;
232
+ }
233
+
234
+ .rmsd-badge-remove .rmsd-icon {
235
+ width: 10px;
236
+ height: 10px;
237
+ }
238
+
239
+ .rmsd-clear .rmsd-icon {
240
+ width: 12px;
241
+ height: 12px;
242
+ }
243
+
244
+ .rmsd-search-clear .rmsd-icon {
245
+ width: 18px;
246
+ height: 18px;
247
+ }
248
+
249
+ .rmsd-arrow-button {
250
+ display: inline-grid;
251
+ width: 20px;
252
+ height: 20px;
253
+ place-items: center;
254
+ border-radius: 999px;
255
+ color: var(--rmsd-muted);
256
+ }
257
+
258
+ .rmsd-arrow-button:disabled {
259
+ cursor: not-allowed;
260
+ }
261
+
262
+ .rmsd-badge-remove:focus-visible,
263
+ .rmsd-clear:focus-visible,
264
+ .rmsd-search-clear:focus-visible,
265
+ .rmsd-arrow-button:focus-visible,
266
+ .rmsd-group-action:focus-visible,
267
+ .rmsd-inline-button:focus-visible {
268
+ outline: 3px solid var(--rmsd-focus);
269
+ outline-offset: 2px;
270
+ }
271
+
272
+ .rmsd-arrow {
273
+ display: inline-flex;
274
+ width: 100%;
275
+ height: 100%;
276
+ line-height: 0;
277
+ }
278
+
279
+ .rmsd-arrow .rmsd-icon {
280
+ display: block;
281
+ width: 100%;
282
+ height: 100%;
283
+ fill: currentColor;
284
+ }
285
+
286
+ .rmsd-menu {
287
+ position: absolute;
288
+ left: 0;
289
+ z-index: 99999;
290
+ width: 100%;
291
+ border: 1px solid var(--rmsd-border);
292
+ border-radius: 22px;
293
+ background-color: var(--rmsd-bg);
294
+ box-shadow: var(--rmsd-shadow);
295
+ overflow: hidden;
296
+ }
297
+
298
+ .rmsd-menu.rmsd-body-overlay {
299
+ position: fixed;
300
+ right: auto;
301
+ top: auto;
302
+ bottom: auto;
303
+ max-width: calc(100vw - 16px);
304
+ z-index: 100000;
305
+ }
306
+
307
+ .rmsd-menu.rmsd-bottom {
308
+ top: calc(100% + 8px);
309
+ }
310
+
311
+ .rmsd-menu.rmsd-top {
312
+ bottom: calc(100% + 8px);
313
+ }
314
+
315
+ .rmsd-menu.rmsd-body-overlay.rmsd-bottom,
316
+ .rmsd-menu.rmsd-body-overlay.rmsd-top {
317
+ top: auto;
318
+ bottom: auto;
319
+ }
320
+
321
+ .rmsd-toolbar {
322
+ display: grid;
323
+ gap: 0;
324
+ padding: 0;
325
+ background-color: var(--rmsd-bg);
326
+ }
327
+
328
+ .rmsd-search-shell {
329
+ position: relative;
330
+ min-height: 52px;
331
+ border-bottom: 1px solid var(--rmsd-divider);
332
+ background-color: var(--rmsd-bg);
333
+ }
334
+
335
+ .rmsd-search-icon {
336
+ position: absolute;
337
+ top: 50%;
338
+ left: 16px;
339
+ width: 18px;
340
+ height: 18px;
341
+ color: var(--rmsd-muted);
342
+ fill: currentColor;
343
+ pointer-events: none;
344
+ transform: translateY(-50%);
345
+ }
346
+
347
+ .rmsd-search-input {
348
+ width: 100%;
349
+ min-height: 52px;
350
+ border: 0;
351
+ border-radius: 0;
352
+ background-color: var(--rmsd-bg);
353
+ color: var(--rmsd-ink);
354
+ font: inherit;
355
+ padding: 0 44px 0 48px;
356
+ }
357
+
358
+ .rmsd-search-input:focus {
359
+ outline: none;
360
+ box-shadow: inset 0 0 0 2px var(--rmsd-primary);
361
+ }
362
+
363
+ .rmsd-search-clear {
364
+ position: absolute;
365
+ top: 50%;
366
+ right: 16px;
367
+ display: inline-grid;
368
+ width: 18px;
369
+ height: 18px;
370
+ place-items: center;
371
+ transform: translateY(-50%);
372
+ border-radius: 999px;
373
+ color: var(--rmsd-muted);
374
+ }
375
+
376
+ .rmsd-bulk-actions {
377
+ display: block;
378
+ align-items: center;
379
+ padding: 0;
380
+ border-bottom: 1px solid var(--rmsd-divider);
381
+ background: var(--rmsd-section-bg);
382
+ }
383
+
384
+ .rmsd-inline-button {
385
+ display: flex;
386
+ align-items: center;
387
+ gap: 10px;
388
+ width: 100%;
389
+ min-height: 39px;
390
+ border: 0;
391
+ border-radius: 0;
392
+ background: transparent;
393
+ color: var(--rmsd-ink);
394
+ cursor: pointer;
395
+ font: inherit;
396
+ font-weight: 500;
397
+ padding: 10px 14px;
398
+ text-align: left;
399
+ }
400
+
401
+ .rmsd-inline-button:hover {
402
+ background-color: var(--rmsd-surface);
403
+ }
404
+
405
+ .rmsd-inline-button:disabled {
406
+ opacity: 0.58;
407
+ cursor: not-allowed;
408
+ }
409
+
410
+ .rmsd-add-button {
411
+ justify-content: center;
412
+ border-top: 1px solid var(--rmsd-divider);
413
+ color: var(--rmsd-primary);
414
+ font-weight: 700;
415
+ }
416
+
417
+ .rmsd-list {
418
+ max-height: 300px;
419
+ overflow: auto;
420
+ padding: 8px;
421
+ background: var(--rmsd-bg);
422
+ scrollbar-width: thin;
423
+ scrollbar-color: rgba(125, 119, 134, 0.34) transparent;
424
+ }
425
+
426
+ .rmsd-list:focus {
427
+ outline: none;
428
+ }
429
+
430
+ .rmsd-menu ::-webkit-scrollbar {
431
+ width: 10px;
432
+ }
433
+
434
+ .rmsd-menu ::-webkit-scrollbar-thumb {
435
+ background: rgba(125, 119, 134, 0.34);
436
+ border: 2px solid transparent;
437
+ border-radius: 999px;
438
+ background-clip: padding-box;
439
+ }
440
+
441
+ .rmsd-menu ::-webkit-scrollbar-track {
442
+ background: transparent;
443
+ }
444
+
445
+ .rmsd-option {
446
+ display: flex;
447
+ align-items: center;
448
+ gap: 10px;
449
+ min-height: 0;
450
+ margin: 4px;
451
+ padding: 12px 14px;
452
+ border-radius: 14px;
453
+ background: transparent;
454
+ color: inherit;
455
+ text-align: left;
456
+ cursor: pointer;
457
+ line-height: 1.35;
458
+ }
459
+
460
+ .rmsd-option:hover {
461
+ background-color: var(--rmsd-surface);
462
+ }
463
+
464
+ .rmsd-option:focus-visible {
465
+ outline: 3px solid var(--rmsd-focus);
466
+ outline-offset: 1px;
467
+ }
468
+
469
+ .rmsd-option.rmsd-selected {
470
+ background-color: var(--rmsd-primary-soft);
471
+ color: var(--rmsd-primary);
472
+ }
473
+
474
+ .rmsd-option.rmsd-disabled {
475
+ opacity: 0.54;
476
+ cursor: not-allowed;
477
+ }
478
+
479
+ .rmsd-checkbox {
480
+ position: relative;
481
+ box-sizing: content-box;
482
+ flex: 0 0 auto;
483
+ width: 18px;
484
+ height: 18px;
485
+ margin-top: 0;
486
+ border: 2px solid var(--rmsd-border-strong);
487
+ border-radius: 6px;
488
+ background-color: var(--rmsd-bg);
489
+ }
490
+
491
+ .rmsd-checkbox[data-checked="true"] {
492
+ border-color: var(--rmsd-primary);
493
+ background-color: var(--rmsd-primary);
494
+ }
495
+
496
+ .rmsd-checkbox[data-checked="true"]::after {
497
+ box-sizing: content-box;
498
+ content: "";
499
+ position: absolute;
500
+ top: 50%;
501
+ left: 50%;
502
+ width: 8px;
503
+ height: 4px;
504
+ margin-top: 0;
505
+ border-color: #fff;
506
+ border-style: solid;
507
+ border-width: 0 0 2px 2px;
508
+ transform: translate(-50%, -58%) rotate(-45deg);
509
+ transform-origin: 50%;
510
+ }
511
+
512
+ .rmsd-option-body {
513
+ min-width: 0;
514
+ flex: 1;
515
+ }
516
+
517
+ .rmsd-option-label {
518
+ font-weight: 500;
519
+ }
520
+
521
+ .rmsd-option-hint {
522
+ display: block;
523
+ margin-top: 3px;
524
+ color: var(--rmsd-muted);
525
+ font-size: 12px;
526
+ }
527
+
528
+ .rmsd-group {
529
+ margin-bottom: 8px;
530
+ }
531
+
532
+ .rmsd-group:last-child {
533
+ margin-bottom: 0;
534
+ }
535
+
536
+ .rmsd-group-header {
537
+ display: flex;
538
+ align-items: center;
539
+ justify-content: space-between;
540
+ gap: 8px;
541
+ padding: 9px 10px;
542
+ color: var(--rmsd-muted);
543
+ font-size: 12px;
544
+ font-weight: 800;
545
+ letter-spacing: 0.08em;
546
+ text-transform: uppercase;
547
+ }
548
+
549
+ .rmsd-group-action {
550
+ color: var(--rmsd-primary);
551
+ font-size: 12px;
552
+ font-weight: 800;
553
+ }
554
+
555
+ .rmsd-state {
556
+ padding: 18px 12px;
557
+ text-align: center;
558
+ color: var(--rmsd-muted);
559
+ }
560
+
561
+ .theme-material,
562
+ .skin-material {
563
+ --rmsd-primary: #3f51b5;
564
+ --rmsd-primary-soft: rgba(63, 81, 181, 0.12);
565
+ --rmsd-bg: #ffffff;
566
+ --rmsd-surface: #f5f7fb;
567
+ --rmsd-surface-muted: #e8eaf6;
568
+ --rmsd-border: #c5cae9;
569
+ --rmsd-border-strong: #7986cb;
570
+ --rmsd-ink: #212121;
571
+ --rmsd-muted: #5f6368;
572
+ --rmsd-chip-bg: #e8eaf6;
573
+ --rmsd-chip-text: #303f9f;
574
+ --rmsd-chip-remove: #303f9f;
575
+ --rmsd-divider: rgba(125, 119, 134, 0.16);
576
+ --rmsd-section-bg: #f5f7fb;
577
+ --rmsd-focus: rgba(63, 81, 181, 0.32);
578
+ --rmsd-shadow: 0 1px 2px rgba(33, 33, 33, 0.16), 0 12px 32px rgba(63, 81, 181, 0.12);
579
+ --rmsd-shadow-soft: 0 1px 2px rgba(33, 33, 33, 0.12), 0 4px 12px rgba(33, 33, 33, 0.08);
580
+ }
581
+
582
+ .theme-material .rmsd-trigger,
583
+ .skin-material .rmsd-trigger {
584
+ min-height: 56px;
585
+ border-radius: 18px;
586
+ padding: 11px 54px 11px 16px;
587
+ }
588
+
589
+ .theme-material .rmsd-menu,
590
+ .skin-material .rmsd-menu,
591
+ .rmsd-menu.theme-material,
592
+ .rmsd-menu.skin-material {
593
+ border-radius: 22px;
594
+ }
595
+
596
+ .theme-material .rmsd-option,
597
+ .skin-material .rmsd-option {
598
+ border-radius: 14px;
599
+ margin: 4px;
600
+ padding: 12px 14px;
601
+ }
602
+
603
+ .theme-dark,
604
+ .skin-dark {
605
+ --rmsd-primary: #8ab4f8;
606
+ --rmsd-primary-soft: rgba(138, 180, 248, 0.18);
607
+ --rmsd-bg: #151a23;
608
+ --rmsd-surface: #202736;
609
+ --rmsd-surface-muted: #111722;
610
+ --rmsd-border: #384456;
611
+ --rmsd-border-strong: #8ab4f8;
612
+ --rmsd-ink: #edf2f7;
613
+ --rmsd-muted: #aab6c5;
614
+ --rmsd-chip-bg: #263247;
615
+ --rmsd-chip-text: #d7e6ff;
616
+ --rmsd-chip-remove: #d7e6ff;
617
+ --rmsd-divider: rgba(170, 182, 197, 0.18);
618
+ --rmsd-section-bg: #202736;
619
+ --rmsd-focus: rgba(138, 180, 248, 0.34);
620
+ --rmsd-shadow: 0 20px 50px rgba(0, 0, 0, 0.42);
621
+ --rmsd-shadow-soft: 0 1px 2px rgba(0, 0, 0, 0.45), 0 10px 24px rgba(0, 0, 0, 0.28);
622
+ }
623
+
624
+ .theme-custom,
625
+ .skin-custom {
626
+ --rmsd-primary: var(--stackline-ms-primary, #0f766e);
627
+ --rmsd-primary-soft: var(--stackline-ms-primary-soft, rgba(15, 118, 110, 0.14));
628
+ --rmsd-bg: var(--stackline-ms-surface, #ffffff);
629
+ --rmsd-surface: var(--stackline-ms-surface-soft, #ecfdf5);
630
+ --rmsd-surface-muted: var(--stackline-ms-surface-muted, #d1fae5);
631
+ --rmsd-border: var(--stackline-ms-outline, #99f6e4);
632
+ --rmsd-border-strong: var(--stackline-ms-outline-strong, #0f766e);
633
+ --rmsd-ink: var(--stackline-ms-on-surface, #102a2a);
634
+ --rmsd-muted: var(--stackline-ms-on-surface-muted, #47615f);
635
+ --rmsd-chip-bg: var(--stackline-ms-chip-bg, #ccfbf1);
636
+ --rmsd-chip-text: var(--stackline-ms-chip-text, #115e59);
637
+ --rmsd-chip-remove: var(--stackline-ms-chip-remove, #115e59);
638
+ --rmsd-divider: var(--stackline-ms-divider, rgba(15, 118, 110, 0.18));
639
+ --rmsd-section-bg: var(--stackline-ms-section-bg, #ecfdf5);
640
+ --rmsd-focus: var(--stackline-ms-focus, rgba(15, 118, 110, 0.28));
641
+ --rmsd-shadow: var(--stackline-ms-shadow, 0 18px 42px rgba(15, 118, 110, 0.15));
642
+ --rmsd-shadow-soft: var(--stackline-ms-shadow-soft, 0 1px 2px rgba(15, 118, 110, 0.16), 0 8px 18px rgba(15, 118, 110, 0.09));
643
+ }
644
+
645
+ .theme-brand,
646
+ .skin-brand {
647
+ --stackline-ms-primary: #7c3aed;
648
+ --stackline-ms-primary-soft: rgba(124, 58, 237, 0.14);
649
+ --stackline-ms-surface: #ffffff;
650
+ --stackline-ms-surface-soft: #f5f3ff;
651
+ --stackline-ms-surface-muted: #ede9fe;
652
+ --stackline-ms-outline: #c4b5fd;
653
+ --stackline-ms-outline-strong: #7c3aed;
654
+ --stackline-ms-on-surface: #22183f;
655
+ --stackline-ms-on-surface-muted: #6b5d80;
656
+ --stackline-ms-chip-bg: #ede9fe;
657
+ --stackline-ms-chip-text: #5b21b6;
658
+ --stackline-ms-chip-remove: #5b21b6;
659
+ --stackline-ms-divider: rgba(124, 58, 237, 0.16);
660
+ --stackline-ms-section-bg: #f5f3ff;
661
+ }
662
+
663
+ .theme-classic,
664
+ .skin-classic {
665
+ --rmsd-primary: #0079fe;
666
+ --rmsd-primary-soft: #e9f4ff;
667
+ --rmsd-bg: #ffffff;
668
+ --rmsd-surface: #f5f5f5;
669
+ --rmsd-surface-muted: #e9f4ff;
670
+ --rmsd-border: #cccccc;
671
+ --rmsd-border-strong: #0079fe;
672
+ --rmsd-ink: #333333;
673
+ --rmsd-muted: #333333;
674
+ --rmsd-chip-bg: #0079fe;
675
+ --rmsd-chip-text: #ffffff;
676
+ --rmsd-chip-remove: #ffffff;
677
+ --rmsd-focus: rgba(0, 121, 254, 0.26);
678
+ --rmsd-divider: #cccccc;
679
+ --rmsd-section-bg: #ffffff;
680
+ --rmsd-shadow: 0 1px 5px #959595;
681
+ --rmsd-shadow-soft: 0 1px 5px #959595;
682
+ color: #333333;
683
+ }
684
+
685
+ .theme-classic .rmsd-trigger,
686
+ .skin-classic .rmsd-trigger {
687
+ flex-wrap: nowrap;
688
+ gap: 6px;
689
+ min-height: 42px;
690
+ border-radius: 3px;
691
+ padding: 10px 68px 10px 10px;
692
+ border: 1px solid #cccccc;
693
+ background: #ffffff;
694
+ box-shadow: 0 1px 5px #959595;
695
+ color: #333333;
696
+ font-size: 14px;
697
+ line-height: 1.35;
698
+ }
699
+
700
+ .theme-classic .rmsd-trigger:hover,
701
+ .skin-classic .rmsd-trigger:hover,
702
+ .theme-classic[data-open="true"] .rmsd-trigger,
703
+ .skin-classic[data-open="true"] .rmsd-trigger {
704
+ border-color: #cccccc;
705
+ box-shadow: 0 1px 5px #959595;
706
+ }
707
+
708
+ .theme-classic .rmsd-trigger.rmsd-disabled,
709
+ .skin-classic .rmsd-trigger.rmsd-disabled {
710
+ background: #cccccc;
711
+ opacity: 1;
712
+ }
713
+
714
+ .theme-classic .rmsd-placeholder,
715
+ .theme-classic .rmsd-single-value,
716
+ .skin-classic .rmsd-placeholder,
717
+ .skin-classic .rmsd-single-value {
718
+ color: #333333;
719
+ font-size: 14px;
720
+ }
721
+
722
+ .theme-classic .rmsd-value,
723
+ .theme-classic .rmsd-badge-list,
724
+ .skin-classic .rmsd-value,
725
+ .skin-classic .rmsd-badge-list {
726
+ align-items: center;
727
+ gap: 4px;
728
+ flex-wrap: wrap;
729
+ min-width: 0;
730
+ }
731
+
732
+ .theme-classic .rmsd-badge,
733
+ .skin-classic .rmsd-badge {
734
+ display: inline-block;
735
+ min-height: 0;
736
+ margin: 2px 0 0;
737
+ border-radius: 2px;
738
+ padding: 2px 24px 2px 6px;
739
+ box-shadow: none;
740
+ color: #ffffff;
741
+ line-height: 1.4;
742
+ }
743
+
744
+ .theme-classic .rmsd-badge-label,
745
+ .skin-classic .rmsd-badge-label {
746
+ display: inline;
747
+ color: #ffffff;
748
+ font-size: 14px;
749
+ font-weight: 400;
750
+ line-height: 1.4;
751
+ }
752
+
753
+ .theme-classic .rmsd-badge-remove,
754
+ .skin-classic .rmsd-badge-remove {
755
+ right: 5px;
756
+ width: 14px;
757
+ height: 14px;
758
+ color: #ffffff;
759
+ }
760
+
761
+ .theme-classic .rmsd-badge-remove .rmsd-icon,
762
+ .skin-classic .rmsd-badge-remove .rmsd-icon {
763
+ width: 9px;
764
+ height: 9px;
765
+ }
766
+
767
+ .theme-classic .rmsd-overflow,
768
+ .skin-classic .rmsd-overflow {
769
+ color: #333333;
770
+ font-size: 14px;
771
+ font-weight: 400;
772
+ }
773
+
774
+ .theme-classic .rmsd-actions,
775
+ .skin-classic .rmsd-actions {
776
+ right: 10px;
777
+ gap: 12px;
778
+ }
779
+
780
+ .theme-classic .rmsd-clear,
781
+ .skin-classic .rmsd-clear {
782
+ width: 18px;
783
+ height: 18px;
784
+ color: #333333;
785
+ }
786
+
787
+ .theme-classic .rmsd-clear .rmsd-icon,
788
+ .skin-classic .rmsd-clear .rmsd-icon {
789
+ width: 11px;
790
+ height: 11px;
791
+ }
792
+
793
+ .theme-classic .rmsd-arrow-button,
794
+ .skin-classic .rmsd-arrow-button {
795
+ width: 20px;
796
+ height: 20px;
797
+ color: #333333;
798
+ }
799
+
800
+ .theme-classic .rmsd-menu,
801
+ .skin-classic .rmsd-menu,
802
+ .rmsd-menu.theme-classic,
803
+ .rmsd-menu.skin-classic {
804
+ overflow: visible;
805
+ border: 1px solid #cccccc;
806
+ border-radius: 3px;
807
+ background: #ffffff;
808
+ box-shadow: 0 1px 5px #959595;
809
+ }
810
+
811
+ .rmsd-menu.theme-classic.rmsd-bottom,
812
+ .rmsd-menu.skin-classic.rmsd-bottom {
813
+ top: calc(100% + 14px);
814
+ }
815
+
816
+ .rmsd-menu.theme-classic.rmsd-top,
817
+ .rmsd-menu.skin-classic.rmsd-top {
818
+ bottom: calc(100% + 14px);
819
+ }
820
+
821
+ .rmsd-menu.rmsd-body-overlay.rmsd-bottom,
822
+ .rmsd-menu.rmsd-body-overlay.rmsd-top {
823
+ bottom: auto;
824
+ }
825
+
826
+ .rmsd-menu.theme-classic::before,
827
+ .rmsd-menu.theme-classic::after,
828
+ .rmsd-menu.skin-classic::before,
829
+ .rmsd-menu.skin-classic::after {
830
+ content: "";
831
+ position: absolute;
832
+ left: 15px;
833
+ width: 0;
834
+ height: 0;
835
+ border-right: 13px solid transparent;
836
+ border-left: 13px solid transparent;
837
+ }
838
+
839
+ .rmsd-menu.theme-classic.rmsd-bottom::before,
840
+ .rmsd-menu.skin-classic.rmsd-bottom::before {
841
+ top: -15px;
842
+ border-bottom: 15px solid #cccccc;
843
+ }
844
+
845
+ .rmsd-menu.theme-classic.rmsd-bottom::after,
846
+ .rmsd-menu.skin-classic.rmsd-bottom::after {
847
+ top: -14px;
848
+ border-bottom: 15px solid #ffffff;
849
+ }
850
+
851
+ .rmsd-menu.theme-classic.rmsd-top::before,
852
+ .rmsd-menu.skin-classic.rmsd-top::before {
853
+ bottom: -15px;
854
+ border-top: 15px solid #cccccc;
855
+ }
856
+
857
+ .rmsd-menu.theme-classic.rmsd-top::after,
858
+ .rmsd-menu.skin-classic.rmsd-top::after {
859
+ bottom: -14px;
860
+ border-top: 15px solid #ffffff;
861
+ }
862
+
863
+ .theme-classic .rmsd-toolbar,
864
+ .skin-classic .rmsd-toolbar,
865
+ .rmsd-menu.theme-classic .rmsd-toolbar,
866
+ .rmsd-menu.skin-classic .rmsd-toolbar {
867
+ gap: 0;
868
+ padding: 0;
869
+ background: #ffffff;
870
+ }
871
+
872
+ .theme-classic .rmsd-search-shell,
873
+ .skin-classic .rmsd-search-shell,
874
+ .rmsd-menu.theme-classic .rmsd-search-shell,
875
+ .rmsd-menu.skin-classic .rmsd-search-shell {
876
+ min-height: 35px;
877
+ border-bottom: 1px solid #cccccc;
878
+ background: #ffffff;
879
+ }
880
+
881
+ .theme-classic .rmsd-search-icon,
882
+ .skin-classic .rmsd-search-icon,
883
+ .rmsd-menu.theme-classic .rmsd-search-icon,
884
+ .rmsd-menu.skin-classic .rmsd-search-icon {
885
+ left: 13px;
886
+ width: 18px;
887
+ height: 18px;
888
+ }
889
+
890
+ .theme-classic .rmsd-search-input,
891
+ .skin-classic .rmsd-search-input,
892
+ .rmsd-menu.theme-classic .rmsd-search-input,
893
+ .rmsd-menu.skin-classic .rmsd-search-input {
894
+ min-height: 35px;
895
+ height: 35px;
896
+ padding: 0 35px;
897
+ border: 0;
898
+ color: #333333;
899
+ }
900
+
901
+ .theme-classic .rmsd-search-input:focus,
902
+ .skin-classic .rmsd-search-input:focus,
903
+ .rmsd-menu.theme-classic .rmsd-search-input:focus,
904
+ .rmsd-menu.skin-classic .rmsd-search-input:focus {
905
+ box-shadow: none;
906
+ }
907
+
908
+ .theme-classic .rmsd-search-clear,
909
+ .skin-classic .rmsd-search-clear,
910
+ .rmsd-menu.theme-classic .rmsd-search-clear,
911
+ .rmsd-menu.skin-classic .rmsd-search-clear {
912
+ right: 13px;
913
+ }
914
+
915
+ .theme-classic .rmsd-bulk-actions,
916
+ .skin-classic .rmsd-bulk-actions,
917
+ .rmsd-menu.theme-classic .rmsd-bulk-actions,
918
+ .rmsd-menu.skin-classic .rmsd-bulk-actions {
919
+ border-top: 0;
920
+ border-bottom: 1px solid #cccccc;
921
+ background: #ffffff;
922
+ }
923
+
924
+ .theme-classic .rmsd-inline-button,
925
+ .skin-classic .rmsd-inline-button,
926
+ .rmsd-menu.theme-classic .rmsd-inline-button,
927
+ .rmsd-menu.skin-classic .rmsd-inline-button {
928
+ min-height: 35px;
929
+ border-radius: 0;
930
+ color: #333333;
931
+ font-weight: 400;
932
+ padding: 10px;
933
+ }
934
+
935
+ .theme-classic .rmsd-inline-button:hover,
936
+ .skin-classic .rmsd-inline-button:hover,
937
+ .rmsd-menu.theme-classic .rmsd-inline-button:hover,
938
+ .rmsd-menu.skin-classic .rmsd-inline-button:hover {
939
+ background: #f5f5f5;
940
+ }
941
+
942
+ .theme-classic .rmsd-list,
943
+ .skin-classic .rmsd-list,
944
+ .rmsd-menu.theme-classic .rmsd-list,
945
+ .rmsd-menu.skin-classic .rmsd-list {
946
+ margin: 0;
947
+ padding: 0;
948
+ background: #ffffff;
949
+ }
950
+
951
+ .theme-classic .rmsd-option,
952
+ .skin-classic .rmsd-option,
953
+ .rmsd-menu.theme-classic .rmsd-option,
954
+ .rmsd-menu.skin-classic .rmsd-option {
955
+ border-radius: 0;
956
+ margin: 0;
957
+ padding: 10px;
958
+ color: #333333;
959
+ line-height: 1.35;
960
+ }
961
+
962
+ .theme-classic .rmsd-option:hover,
963
+ .skin-classic .rmsd-option:hover,
964
+ .rmsd-menu.theme-classic .rmsd-option:hover,
965
+ .rmsd-menu.skin-classic .rmsd-option:hover {
966
+ background: #f5f5f5;
967
+ }
968
+
969
+ .theme-classic .rmsd-option.rmsd-selected,
970
+ .skin-classic .rmsd-option.rmsd-selected,
971
+ .rmsd-menu.theme-classic .rmsd-option.rmsd-selected,
972
+ .rmsd-menu.skin-classic .rmsd-option.rmsd-selected {
973
+ background: #e9f4ff;
974
+ color: #333333;
975
+ }
976
+
977
+ .theme-classic .rmsd-checkbox,
978
+ .skin-classic .rmsd-checkbox,
979
+ .rmsd-menu.theme-classic .rmsd-checkbox,
980
+ .rmsd-menu.skin-classic .rmsd-checkbox {
981
+ width: 14px;
982
+ height: 14px;
983
+ border: 2px solid #0079fe;
984
+ border-radius: 0;
985
+ background: #ffffff;
986
+ }
987
+
988
+ .theme-classic .rmsd-checkbox[data-checked="true"],
989
+ .skin-classic .rmsd-checkbox[data-checked="true"],
990
+ .rmsd-menu.theme-classic .rmsd-checkbox[data-checked="true"],
991
+ .rmsd-menu.skin-classic .rmsd-checkbox[data-checked="true"] {
992
+ border-color: #0079fe;
993
+ background: #0079fe;
994
+ }
995
+
996
+ .theme-classic .rmsd-checkbox[data-checked="true"]::after,
997
+ .skin-classic .rmsd-checkbox[data-checked="true"]::after,
998
+ .rmsd-menu.theme-classic .rmsd-checkbox[data-checked="true"]::after,
999
+ .rmsd-menu.skin-classic .rmsd-checkbox[data-checked="true"]::after {
1000
+ top: 50%;
1001
+ left: 50%;
1002
+ width: 8px;
1003
+ height: 3px;
1004
+ margin-top: 0;
1005
+ border-width: 0 0 3px 3px;
1006
+ transform: translate(-50%, -58%) rotate(-45deg);
1007
+ }
1008
+
1009
+ .theme-classic .rmsd-option-label,
1010
+ .skin-classic .rmsd-option-label,
1011
+ .rmsd-menu.theme-classic .rmsd-option-label,
1012
+ .rmsd-menu.skin-classic .rmsd-option-label {
1013
+ color: #000000;
1014
+ font-weight: 300;
1015
+ }
1016
+
1017
+ .theme-classic .rmsd-group-header,
1018
+ .skin-classic .rmsd-group-header,
1019
+ .rmsd-menu.theme-classic .rmsd-group-header,
1020
+ .rmsd-menu.skin-classic .rmsd-group-header {
1021
+ color: #000000;
1022
+ font-size: 14px;
1023
+ font-weight: 700;
1024
+ letter-spacing: 0;
1025
+ text-transform: capitalize;
1026
+ }
1027
+
1028
+ .custom-class-example {
1029
+ --rmsd-primary: #0f766e;
1030
+ --rmsd-primary-soft: #ccfbf1;
1031
+ --rmsd-bg: #f8fffd;
1032
+ --rmsd-surface: #ecfdf5;
1033
+ --rmsd-border: #99f6e4;
1034
+ --rmsd-border-strong: #0f766e;
1035
+ }
1036
+
1037
+ @media (max-width: 720px) {
1038
+ .rmsd-trigger {
1039
+ align-items: flex-start;
1040
+ padding-right: 54px;
1041
+ }
1042
+ }
1043
+ `;
1044
+ function ensureDropdownStyles() {
1045
+ if (typeof document === "undefined") {
1046
+ return;
1047
+ }
1048
+ if (document.getElementById(STYLE_ID)) {
1049
+ return;
1050
+ }
1051
+ const tag = document.createElement("style");
1052
+ tag.id = STYLE_ID;
1053
+ tag.textContent = styles;
1054
+ document.head.appendChild(tag);
1055
+ }
1056
+
1057
+ // src/MultiSelectDropdown.tsx
1058
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
1059
+ var DEFAULT_SETTINGS = {
1060
+ singleSelection: false,
1061
+ text: "Select",
1062
+ enableCheckAll: true,
1063
+ selectAllText: "Select All",
1064
+ unSelectAllText: "Unselect All",
1065
+ filterSelectAllText: "Select filtered",
1066
+ filterUnSelectAllText: "Unselect filtered",
1067
+ enableFilterSelectAll: true,
1068
+ enableSearchFilter: false,
1069
+ searchBy: [],
1070
+ maxHeight: 300,
1071
+ badgeShowLimit: Number.MAX_SAFE_INTEGER,
1072
+ classes: "",
1073
+ limitSelection: 0,
1074
+ disabled: false,
1075
+ searchPlaceholderText: "Search",
1076
+ groupBy: "",
1077
+ showCheckbox: true,
1078
+ noDataLabel: "No Data Available",
1079
+ searchAutofocus: true,
1080
+ lazyLoading: false,
1081
+ labelKey: "itemName",
1082
+ primaryKey: "id",
1083
+ position: "bottom",
1084
+ autoPosition: true,
1085
+ loading: false,
1086
+ selectGroup: false,
1087
+ addNewItemOnFilter: false,
1088
+ addNewButtonText: "Add",
1089
+ escapeToClose: true,
1090
+ clearAll: true,
1091
+ closeDropDownOnSelection: false,
1092
+ tagToBody: false,
1093
+ appendToBody: false,
1094
+ theme: "",
1095
+ skin: "classic",
1096
+ ariaLabel: "Multiselect dropdown",
1097
+ listboxAriaLabel: "Dropdown options",
1098
+ searchAriaLabel: "Search options",
1099
+ clearSearchAriaLabel: "Clear search",
1100
+ clearAllAriaLabel: "Clear selected options",
1101
+ removeItemAriaLabel: "Remove selected option",
1102
+ openDropdownAriaLabel: "Open dropdown",
1103
+ closeDropdownAriaLabel: "Close dropdown",
1104
+ loadingText: "Loading options"
1105
+ };
1106
+ var useClientLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
1107
+ function StacklineIcon({ name, className = "rmsd-icon" }) {
1108
+ if (name === "remove") {
1109
+ return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 47.971 47.971", focusable: "false", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M28.228,23.986L47.092,5.122c1.172-1.171,1.172-3.071,0-4.242c-1.172-1.172-3.07-1.172-4.242,0L23.986,19.744L5.121,0.88c-1.172-1.172-3.07-1.172-4.242,0c-1.172,1.171-1.172,3.071,0,4.242l18.865,18.864L0.879,42.85c-1.172,1.171-1.172,3.071,0,4.242C1.465,47.677,2.233,47.97,3,47.97s1.535-0.293,2.121-0.879l18.865-18.864L42.85,47.091c0.586,0.586,1.354,0.879,2.121,0.879s1.535-0.293,2.121-0.879c1.172-1.171,1.172-3.071,0-4.242L28.228,23.986z" }) });
1110
+ }
1111
+ if (name === "clear") {
1112
+ return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 51.976 51.976", focusable: "false", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M44.373,7.603c-10.137-10.137-26.632-10.138-36.77,0c-10.138,10.138-10.137,26.632,0,36.77s26.632,10.138,36.77,0C54.51,34.235,54.51,17.74,44.373,7.603z M36.241,36.241c-0.781,0.781-2.047,0.781-2.828,0l-7.425-7.425l-7.778,7.778c-0.781,0.781-2.047,0.781-2.828,0c-0.781-0.781-0.781-2.047,0-2.828l7.778-7.778l-7.425-7.425c-0.781-0.781-0.781-2.048,0-2.828c0.781-0.781,2.047-0.781,2.828,0l7.425,7.425l7.071-7.071c0.781-0.781,2.047-0.781,2.828,0c0.781,0.781,0.781,2.047,0,2.828l-7.071,7.071l7.425,7.425C37.022,34.194,37.022,35.46,36.241,36.241z" }) });
1113
+ }
1114
+ if (name === "search") {
1115
+ return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 615.52 615.52", focusable: "false", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M602.531,549.736l-184.31-185.368c26.679-37.72,42.528-83.729,42.528-133.548C460.75,103.35,357.997,0,231.258,0C104.518,0,1.765,103.35,1.765,230.82c0,127.47,102.753,230.82,229.493,230.82c49.53,0,95.271-15.944,132.78-42.777l184.31,185.366c7.482,7.521,17.292,11.291,27.102,11.291c9.812,0,19.62-3.77,27.083-11.291C617.496,589.188,617.496,564.777,602.531,549.736z M355.9,319.763l-15.042,21.273L319.7,356.174c-26.083,18.658-56.667,28.526-88.442,28.526c-84.365,0-152.995-69.035-152.995-153.88c0-84.846,68.63-153.88,152.995-153.88s152.996,69.034,152.996,153.88C384.271,262.769,374.462,293.526,355.9,319.763z" }) });
1116
+ }
1117
+ return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 612 612", focusable: "false", "aria-hidden": "true", children: name === "angle-up" ? /* @__PURE__ */ jsx("path", { d: "M604.501,440.509L325.398,134.956c-5.331-5.357-12.423-7.627-19.386-7.27c-6.989-0.357-14.056,1.913-19.387,7.27L7.499,440.509c-9.999,10.024-9.999,26.298,0,36.323s26.223,10.024,36.222,0l262.293-287.164L568.28,476.832c9.999,10.024,26.222,10.024,36.221,0C614.5,466.809,614.5,450.534,604.501,440.509z" }) : /* @__PURE__ */ jsx("path", { d: "M604.501,134.782c-9.999-10.05-26.222-10.05-36.221,0L306.014,422.558L43.721,134.782c-9.999-10.05-26.223-10.05-36.222,0s-9.999,26.35,0,36.399l279.103,306.241c5.331,5.357,12.422,7.652,19.386,7.296c6.988,0.356,14.055-1.939,19.386-7.296l279.128-306.268C614.5,161.106,614.5,144.832,604.501,134.782z" }) });
1118
+ }
1119
+ function isPrimitiveItem(item) {
1120
+ return typeof item === "string" || typeof item === "number" || typeof item === "boolean";
1121
+ }
1122
+ function getLabel(item, settings) {
1123
+ if (isPrimitiveItem(item)) {
1124
+ return String(item);
1125
+ }
1126
+ const keys = [settings.labelKey, "itemName", "name", "label", "title", "value"].filter(Boolean);
1127
+ for (const key of keys) {
1128
+ if (key && item[key] != null) {
1129
+ return String(item[key]);
1130
+ }
1131
+ }
1132
+ return JSON.stringify(item);
1133
+ }
1134
+ function getPrimaryValue(item, settings) {
1135
+ if (isPrimitiveItem(item)) {
1136
+ return String(item);
1137
+ }
1138
+ const keys = [settings.primaryKey, "id", "value", "key"].filter(Boolean);
1139
+ for (const key of keys) {
1140
+ if (key && item[key] != null) {
1141
+ return String(item[key]);
1142
+ }
1143
+ }
1144
+ return getLabel(item, settings);
1145
+ }
1146
+ function itemMatchesQuery(item, query, settings) {
1147
+ if (!query.trim()) {
1148
+ return true;
1149
+ }
1150
+ const needle = query.trim().toLowerCase();
1151
+ const haystack = /* @__PURE__ */ new Set();
1152
+ haystack.add(getLabel(item, settings).toLowerCase());
1153
+ if (!isPrimitiveItem(item)) {
1154
+ const searchKeys = settings.searchBy.length ? settings.searchBy : [settings.labelKey];
1155
+ for (const key of searchKeys) {
1156
+ if (key && item[key] != null) {
1157
+ haystack.add(String(item[key]).toLowerCase());
1158
+ }
1159
+ }
1160
+ }
1161
+ for (const value of haystack) {
1162
+ if (value.includes(needle)) {
1163
+ return true;
1164
+ }
1165
+ }
1166
+ return false;
1167
+ }
1168
+ function getGroupName(item, settings) {
1169
+ if (!settings.groupBy) {
1170
+ return "";
1171
+ }
1172
+ if (typeof settings.groupBy === "function") {
1173
+ return settings.groupBy(item);
1174
+ }
1175
+ if (!isPrimitiveItem(item)) {
1176
+ const groupKey = settings.groupBy;
1177
+ const objectItem = item;
1178
+ if (groupKey in objectItem) {
1179
+ return String(objectItem[groupKey] ?? "");
1180
+ }
1181
+ }
1182
+ return "";
1183
+ }
1184
+ function mergeUniqueItems(base, extra, settings) {
1185
+ const bucket = /* @__PURE__ */ new Map();
1186
+ for (const item of [...base, ...extra]) {
1187
+ bucket.set(getPrimaryValue(item, settings), item);
1188
+ }
1189
+ return Array.from(bucket.values());
1190
+ }
1191
+ function createItemFromQuery(query, settings, sample) {
1192
+ if (sample && !isPrimitiveItem(sample)) {
1193
+ return {
1194
+ [settings.primaryKey]: query.toLowerCase().replace(/\s+/g, "-"),
1195
+ [settings.labelKey]: query
1196
+ };
1197
+ }
1198
+ return query;
1199
+ }
1200
+ function isDisabledItem(item) {
1201
+ return !isPrimitiveItem(item) && Boolean(item.disabled);
1202
+ }
1203
+ function buildGroups(items, settings) {
1204
+ if (!settings.groupBy) {
1205
+ return [];
1206
+ }
1207
+ const map = /* @__PURE__ */ new Map();
1208
+ for (const item of items) {
1209
+ const groupName = getGroupName(item, settings) || "Ungrouped";
1210
+ const current = map.get(groupName) || [];
1211
+ current.push(item);
1212
+ map.set(groupName, current);
1213
+ }
1214
+ return Array.from(map.entries()).map(([name, groupedItems]) => ({
1215
+ name,
1216
+ items: groupedItems
1217
+ }));
1218
+ }
1219
+ function useControllableSelection(controlledValue, defaultValue, onChange) {
1220
+ const [internalValue, setInternalValue] = useState(defaultValue ?? []);
1221
+ const isControlled = controlledValue !== void 0;
1222
+ const value = isControlled ? controlledValue : internalValue;
1223
+ const setValue = (nextValue) => {
1224
+ if (!isControlled) {
1225
+ setInternalValue(nextValue);
1226
+ }
1227
+ onChange?.(nextValue);
1228
+ };
1229
+ return [value, setValue];
1230
+ }
1231
+ function sanitizeId(value) {
1232
+ return value.replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 56) || "option";
1233
+ }
1234
+ function normalizeSkinName(value) {
1235
+ return sanitizeId(value.toLowerCase()) || "classic";
1236
+ }
1237
+ function getVisibleBadgeLimit(selectedCount, rawLimit) {
1238
+ if (!Number.isFinite(rawLimit)) {
1239
+ return selectedCount;
1240
+ }
1241
+ const limit = Math.max(0, Math.floor(rawLimit));
1242
+ return Math.min(selectedCount, limit);
1243
+ }
1244
+ function InnerMultiSelectDropdown({
1245
+ data,
1246
+ settings: incomingSettings,
1247
+ loading,
1248
+ className,
1249
+ style,
1250
+ selectedItems: controlledSelectedItems,
1251
+ defaultSelectedItems,
1252
+ onChange,
1253
+ onSelect,
1254
+ onDeSelect,
1255
+ onSelectAll,
1256
+ onDeSelectAll,
1257
+ onOpen,
1258
+ onClose,
1259
+ onScrollToEnd,
1260
+ onFilterSelectAll,
1261
+ onFilterDeSelectAll,
1262
+ onAddFilterNewItem,
1263
+ onGroupSelect,
1264
+ onGroupDeSelect,
1265
+ renderItem,
1266
+ renderBadge,
1267
+ renderSearch,
1268
+ renderEmptyState
1269
+ }, ref) {
1270
+ ensureDropdownStyles();
1271
+ const settings = { ...DEFAULT_SETTINGS, ...incomingSettings };
1272
+ const [selectedItems, setSelectedItems] = useControllableSelection(
1273
+ controlledSelectedItems,
1274
+ defaultSelectedItems,
1275
+ onChange
1276
+ );
1277
+ const [isOpen, setIsOpen] = useState(false);
1278
+ const [filter, setFilter] = useState("");
1279
+ const [addedItems, setAddedItems] = useState([]);
1280
+ const [activeDescendantId, setActiveDescendantId] = useState(null);
1281
+ const [bodyMenuStyle, setBodyMenuStyle] = useState();
1282
+ const [bodyListMaxHeight, setBodyListMaxHeight] = useState();
1283
+ const [effectivePosition, setEffectivePosition] = useState(
1284
+ settings.position === "top" ? "top" : "bottom"
1285
+ );
1286
+ const rootRef = useRef(null);
1287
+ const triggerRef = useRef(null);
1288
+ const menuRef = useRef(null);
1289
+ const searchRef = useRef(null);
1290
+ const listRef = useRef(null);
1291
+ const lastScrollHeightRef = useRef(0);
1292
+ const pendingFocusRef = useRef(null);
1293
+ const instanceIdRef = useRef(`rmsd-${Math.random().toString(36).slice(2)}`);
1294
+ const allItems = useMemo(
1295
+ () => mergeUniqueItems(data, addedItems, settings),
1296
+ [addedItems, data, settings]
1297
+ );
1298
+ const filteredItems = useMemo(
1299
+ () => allItems.filter((item) => itemMatchesQuery(item, filter, settings)),
1300
+ [allItems, filter, settings]
1301
+ );
1302
+ const groupedItems = useMemo(() => buildGroups(filteredItems, settings), [filteredItems, settings]);
1303
+ const listboxId = `${instanceIdRef.current}-listbox`;
1304
+ const getOptionId = (item, index, prefix) => `${instanceIdRef.current}-${prefix}-${index}-${sanitizeId(getPrimaryValue(item, settings))}`;
1305
+ const isSelected = (item) => selectedItems.some(
1306
+ (selectedItem) => getPrimaryValue(selectedItem, settings) === getPrimaryValue(item, settings)
1307
+ );
1308
+ const selectableItems = filteredItems.filter((item) => !isDisabledItem(item));
1309
+ const limitReached = Boolean(settings.limitSelection) && selectedItems.length >= settings.limitSelection;
1310
+ const shouldAppendToBody = Boolean(settings.appendToBody || settings.tagToBody);
1311
+ const getOptionElements = () => Array.from(
1312
+ listRef.current?.querySelectorAll('[data-rmsd-option="true"]:not([aria-disabled="true"])') ?? []
1313
+ );
1314
+ const focusOptionByIndex = (index) => {
1315
+ const options = getOptionElements();
1316
+ if (!options.length) {
1317
+ return;
1318
+ }
1319
+ const boundedIndex = Math.max(0, Math.min(index, options.length - 1));
1320
+ const option = options[boundedIndex];
1321
+ option.focus();
1322
+ setActiveDescendantId(option.id || null);
1323
+ option.scrollIntoView({ block: "nearest" });
1324
+ };
1325
+ const focusFirstOption = () => focusOptionByIndex(0);
1326
+ const focusLastOption = () => focusOptionByIndex(getOptionElements().length - 1);
1327
+ const updateSelection = (nextItems) => {
1328
+ setSelectedItems(nextItems);
1329
+ };
1330
+ const openDropdown = (focusTarget = "search") => {
1331
+ if (settings.disabled) {
1332
+ return;
1333
+ }
1334
+ pendingFocusRef.current = focusTarget;
1335
+ setIsOpen((current) => {
1336
+ if (!current) {
1337
+ onOpen?.();
1338
+ }
1339
+ return true;
1340
+ });
1341
+ };
1342
+ const closeDropdown = (returnFocus = false) => {
1343
+ setIsOpen((current) => {
1344
+ if (current) {
1345
+ onClose?.();
1346
+ }
1347
+ return false;
1348
+ });
1349
+ setActiveDescendantId(null);
1350
+ setBodyMenuStyle(void 0);
1351
+ setBodyListMaxHeight(void 0);
1352
+ if (returnFocus) {
1353
+ window.setTimeout(() => triggerRef.current?.focus(), 0);
1354
+ }
1355
+ };
1356
+ const clearSelection = () => {
1357
+ const previousItems = selectedItems;
1358
+ updateSelection([]);
1359
+ onDeSelectAll?.(previousItems);
1360
+ };
1361
+ const toggleDropdown = () => {
1362
+ if (isOpen) {
1363
+ closeDropdown();
1364
+ } else {
1365
+ openDropdown("search");
1366
+ }
1367
+ };
1368
+ const removeItem = (item) => {
1369
+ const nextItems = selectedItems.filter(
1370
+ (selectedItem) => getPrimaryValue(selectedItem, settings) !== getPrimaryValue(item, settings)
1371
+ );
1372
+ updateSelection(nextItems);
1373
+ onDeSelect?.(item);
1374
+ };
1375
+ const selectItem = (item) => {
1376
+ if (settings.disabled || isDisabledItem(item)) {
1377
+ return;
1378
+ }
1379
+ if (isSelected(item)) {
1380
+ removeItem(item);
1381
+ return;
1382
+ }
1383
+ if (settings.singleSelection) {
1384
+ updateSelection([item]);
1385
+ onSelect?.(item);
1386
+ closeDropdown(true);
1387
+ return;
1388
+ }
1389
+ if (settings.limitSelection && selectedItems.length >= settings.limitSelection) {
1390
+ return;
1391
+ }
1392
+ const nextItems = [...selectedItems, item];
1393
+ updateSelection(nextItems);
1394
+ onSelect?.(item);
1395
+ if (settings.closeDropDownOnSelection) {
1396
+ closeDropdown(true);
1397
+ }
1398
+ };
1399
+ const selectAllItems = (items, filteredSelection = false) => {
1400
+ if (settings.singleSelection) {
1401
+ return;
1402
+ }
1403
+ const currentIds = new Set(selectedItems.map((item) => getPrimaryValue(item, settings)));
1404
+ const remainingCapacity = settings.limitSelection ? Math.max(settings.limitSelection - selectedItems.length, 0) : Number.MAX_SAFE_INTEGER;
1405
+ const nextItemsToAdd = items.filter((item) => !currentIds.has(getPrimaryValue(item, settings))).filter((item) => !isDisabledItem(item)).slice(0, remainingCapacity);
1406
+ const nextItems = [...selectedItems, ...nextItemsToAdd];
1407
+ updateSelection(nextItems);
1408
+ if (filteredSelection) {
1409
+ onFilterSelectAll?.(nextItemsToAdd);
1410
+ } else {
1411
+ onSelectAll?.(nextItems);
1412
+ }
1413
+ };
1414
+ const deSelectAllItems = (items, filteredSelection = false) => {
1415
+ const ids = new Set(items.map((item) => getPrimaryValue(item, settings)));
1416
+ const nextItems = selectedItems.filter((item) => !ids.has(getPrimaryValue(item, settings)));
1417
+ updateSelection(nextItems);
1418
+ if (filteredSelection) {
1419
+ onFilterDeSelectAll?.(items);
1420
+ } else {
1421
+ onDeSelectAll?.(items);
1422
+ }
1423
+ };
1424
+ const handleAddFilterNewItem = async () => {
1425
+ const query = filter.trim();
1426
+ if (!query) {
1427
+ return;
1428
+ }
1429
+ const result = await onAddFilterNewItem?.(query);
1430
+ const nextItem = result === void 0 ? createItemFromQuery(query, settings, data[0]) : result;
1431
+ setAddedItems((currentItems) => mergeUniqueItems(currentItems, [nextItem], settings));
1432
+ if (settings.singleSelection) {
1433
+ updateSelection([nextItem]);
1434
+ } else {
1435
+ updateSelection(mergeUniqueItems(selectedItems, [nextItem], settings));
1436
+ }
1437
+ setFilter("");
1438
+ };
1439
+ const toggleGroup = (groupName, items) => {
1440
+ const groupItems = items.filter((item) => !isDisabledItem(item));
1441
+ const allSelected = groupItems.length > 0 && groupItems.every((item) => isSelected(item));
1442
+ if (allSelected) {
1443
+ deSelectAllItems(groupItems, false);
1444
+ onGroupDeSelect?.(groupName, groupItems);
1445
+ return;
1446
+ }
1447
+ selectAllItems(groupItems, false);
1448
+ onGroupSelect?.(groupName, groupItems);
1449
+ };
1450
+ const handleListScroll = () => {
1451
+ if (!listRef.current || !onScrollToEnd) {
1452
+ return;
1453
+ }
1454
+ const { scrollHeight, scrollTop, clientHeight } = listRef.current;
1455
+ if (scrollHeight === lastScrollHeightRef.current && scrollTop + clientHeight < scrollHeight - 12) {
1456
+ return;
1457
+ }
1458
+ if (scrollTop + clientHeight >= scrollHeight - 12) {
1459
+ lastScrollHeightRef.current = scrollHeight;
1460
+ onScrollToEnd({ scrollTop, scrollHeight, clientHeight });
1461
+ }
1462
+ };
1463
+ const resolveDropdownPosition = (triggerRect, menuHeight) => {
1464
+ const preferredPosition = settings.position === "top" ? "top" : "bottom";
1465
+ if (!settings.autoPosition || typeof window === "undefined" || typeof document === "undefined") {
1466
+ return preferredPosition;
1467
+ }
1468
+ const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
1469
+ const spaceOnTop = triggerRect.top;
1470
+ const spaceOnBottom = viewportHeight - triggerRect.bottom;
1471
+ const topHasMeaningfullyMoreRoom = spaceOnTop > spaceOnBottom + 48;
1472
+ if (spaceOnBottom < menuHeight && topHasMeaningfullyMoreRoom && menuHeight < spaceOnTop) {
1473
+ return "top";
1474
+ }
1475
+ return "bottom";
1476
+ };
1477
+ useEffect(() => {
1478
+ if (!isOpen) {
1479
+ return;
1480
+ }
1481
+ const handlePointerDown = (event) => {
1482
+ const target = event.target;
1483
+ if (!rootRef.current?.contains(target) && !menuRef.current?.contains(target)) {
1484
+ closeDropdown();
1485
+ }
1486
+ };
1487
+ const handleKeyDown = (event) => {
1488
+ if (event.key === "Escape" && settings.escapeToClose) {
1489
+ closeDropdown(true);
1490
+ }
1491
+ };
1492
+ document.addEventListener("mousedown", handlePointerDown);
1493
+ document.addEventListener("touchstart", handlePointerDown);
1494
+ document.addEventListener("keydown", handleKeyDown);
1495
+ return () => {
1496
+ document.removeEventListener("mousedown", handlePointerDown);
1497
+ document.removeEventListener("touchstart", handlePointerDown);
1498
+ document.removeEventListener("keydown", handleKeyDown);
1499
+ };
1500
+ }, [isOpen, settings.escapeToClose]);
1501
+ const updateBodyMenuPosition = () => {
1502
+ if (!shouldAppendToBody || !triggerRef.current || typeof window === "undefined") {
1503
+ return;
1504
+ }
1505
+ const gap = 8;
1506
+ const viewportPadding = 8;
1507
+ const triggerRect = triggerRef.current.getBoundingClientRect();
1508
+ const menuHeight = menuRef.current?.offsetHeight ?? 0;
1509
+ const listHeight = listRef.current?.offsetHeight ?? Math.min(settings.maxHeight, menuHeight);
1510
+ const nonListHeight = Math.max(0, menuHeight - listHeight);
1511
+ const resolvedPosition = resolveDropdownPosition(triggerRect, menuHeight);
1512
+ const availableHeight = resolvedPosition === "top" ? Math.max(0, triggerRect.top - gap - viewportPadding) : Math.max(0, window.innerHeight - triggerRect.bottom - gap - viewportPadding);
1513
+ const nextListMaxHeight = menuHeight > 0 ? Math.max(0, Math.min(settings.maxHeight, availableHeight - nonListHeight)) : settings.maxHeight;
1514
+ const positionedMenuHeight = nonListHeight + nextListMaxHeight;
1515
+ const preferredTop = resolvedPosition === "top" ? triggerRect.top - positionedMenuHeight - gap : triggerRect.bottom + gap;
1516
+ const top = resolvedPosition === "top" ? Math.max(viewportPadding, preferredTop) : preferredTop;
1517
+ setEffectivePosition((current) => current === resolvedPosition ? current : resolvedPosition);
1518
+ setBodyListMaxHeight((current) => current === nextListMaxHeight ? current : nextListMaxHeight);
1519
+ const maxWidth = Math.max(0, window.innerWidth - viewportPadding * 2);
1520
+ const width = Math.min(triggerRect.width, maxWidth);
1521
+ const left = Math.min(Math.max(viewportPadding, triggerRect.left), window.innerWidth - width - viewportPadding);
1522
+ setBodyMenuStyle({
1523
+ position: "fixed",
1524
+ top,
1525
+ left,
1526
+ width,
1527
+ maxWidth,
1528
+ zIndex: 1e5
1529
+ });
1530
+ };
1531
+ const updateLocalMenuPosition = () => {
1532
+ if (!triggerRef.current || !menuRef.current || shouldAppendToBody) {
1533
+ return;
1534
+ }
1535
+ setBodyListMaxHeight((current) => current === void 0 ? current : void 0);
1536
+ const triggerRect = triggerRef.current.getBoundingClientRect();
1537
+ const menuHeight = menuRef.current.offsetHeight;
1538
+ const resolvedPosition = resolveDropdownPosition(triggerRect, menuHeight);
1539
+ setEffectivePosition((current) => current === resolvedPosition ? current : resolvedPosition);
1540
+ };
1541
+ useClientLayoutEffect(() => {
1542
+ if (!isOpen) {
1543
+ return;
1544
+ }
1545
+ if (shouldAppendToBody) {
1546
+ updateBodyMenuPosition();
1547
+ return;
1548
+ }
1549
+ updateLocalMenuPosition();
1550
+ }, [
1551
+ isOpen,
1552
+ shouldAppendToBody,
1553
+ settings.position,
1554
+ settings.autoPosition,
1555
+ settings.maxHeight,
1556
+ filteredItems.length,
1557
+ selectedItems.length,
1558
+ filter
1559
+ ]);
1560
+ useEffect(() => {
1561
+ if (!isOpen || !shouldAppendToBody || typeof window === "undefined") {
1562
+ return;
1563
+ }
1564
+ const update = () => updateBodyMenuPosition();
1565
+ const rafUpdate = () => window.requestAnimationFrame(update);
1566
+ window.addEventListener("resize", rafUpdate);
1567
+ window.addEventListener("scroll", rafUpdate, true);
1568
+ const observer = typeof ResizeObserver !== "undefined" && menuRef.current ? new ResizeObserver(rafUpdate) : null;
1569
+ if (observer && menuRef.current) {
1570
+ observer.observe(menuRef.current);
1571
+ }
1572
+ return () => {
1573
+ window.removeEventListener("resize", rafUpdate);
1574
+ window.removeEventListener("scroll", rafUpdate, true);
1575
+ observer?.disconnect();
1576
+ };
1577
+ }, [
1578
+ isOpen,
1579
+ shouldAppendToBody,
1580
+ settings.position,
1581
+ settings.autoPosition,
1582
+ settings.maxHeight,
1583
+ filteredItems.length,
1584
+ selectedItems.length
1585
+ ]);
1586
+ useEffect(() => {
1587
+ if (!isOpen) {
1588
+ return;
1589
+ }
1590
+ const pendingFocus = pendingFocusRef.current;
1591
+ pendingFocusRef.current = null;
1592
+ window.setTimeout(() => {
1593
+ if (pendingFocus === "first") {
1594
+ focusFirstOption();
1595
+ return;
1596
+ }
1597
+ if (pendingFocus === "last") {
1598
+ focusLastOption();
1599
+ return;
1600
+ }
1601
+ if (settings.enableSearchFilter && settings.searchAutofocus) {
1602
+ searchRef.current?.focus();
1603
+ }
1604
+ }, 0);
1605
+ }, [isOpen, filteredItems.length, settings.enableSearchFilter, settings.searchAutofocus]);
1606
+ useEffect(() => {
1607
+ lastScrollHeightRef.current = 0;
1608
+ }, [filteredItems.length]);
1609
+ useImperativeHandle(
1610
+ ref,
1611
+ () => ({
1612
+ openDropdown: () => openDropdown("search"),
1613
+ closeDropdown: () => closeDropdown(),
1614
+ clearSelection,
1615
+ focusSearch: () => {
1616
+ openDropdown("search");
1617
+ window.setTimeout(() => searchRef.current?.focus(), 0);
1618
+ },
1619
+ selectAll: () => selectAllItems(selectableItems),
1620
+ deSelectAll: () => deSelectAllItems(selectedItems),
1621
+ getSelectedItems: () => selectedItems
1622
+ }),
1623
+ [selectableItems, selectedItems]
1624
+ );
1625
+ const selectedCount = selectedItems.length;
1626
+ const visibleBadgeLimit = getVisibleBadgeLimit(selectedCount, settings.badgeShowLimit);
1627
+ const visibleBadges = settings.singleSelection ? selectedItems : selectedItems.slice(0, visibleBadgeLimit);
1628
+ const hiddenBadgeCount = settings.singleSelection ? 0 : Math.max(selectedCount - visibleBadges.length, 0);
1629
+ const hasFilteredResults = filteredItems.length > 0;
1630
+ const allFilteredSelected = selectableItems.length > 0 && selectableItems.every((item) => isSelected(item));
1631
+ const hasBulkActions = settings.enableCheckAll && !settings.singleSelection || Boolean(settings.addNewItemOnFilter && filter.trim());
1632
+ const skinName = normalizeSkinName(String(settings.skin || settings.theme || "classic"));
1633
+ const skinFallbackClass = ["classic", "material", "dark", "custom"].includes(skinName) ? "" : "theme-custom";
1634
+ const rootClassName = [
1635
+ "rmsd-root",
1636
+ `skin-${skinName}`,
1637
+ `theme-${skinName}`,
1638
+ skinFallbackClass,
1639
+ isOpen ? "rmsd-open" : "",
1640
+ hiddenBadgeCount > 0 ? "rmsd-has-overflow" : "",
1641
+ settings.clearAll && selectedItems.length > 0 && !settings.disabled ? "rmsd-has-clear" : "",
1642
+ effectivePosition === "top" ? "rmsd-opens-up" : "rmsd-opens-down",
1643
+ settings.classes,
1644
+ className
1645
+ ].filter(Boolean).join(" ");
1646
+ const getRemoveItemAriaLabel = (item) => {
1647
+ if (typeof settings.removeItemAriaLabel === "function") {
1648
+ return settings.removeItemAriaLabel(item);
1649
+ }
1650
+ return `${settings.removeItemAriaLabel}: ${getLabel(item, settings)}`;
1651
+ };
1652
+ const getTriggerAriaLabel = () => {
1653
+ if (!selectedItems.length) {
1654
+ return settings.ariaLabel;
1655
+ }
1656
+ return `${settings.ariaLabel}: ${selectedItems.map((item) => getLabel(item, settings)).join(", ")}`;
1657
+ };
1658
+ const stopInlineKey = (event) => {
1659
+ if (event.key === "Enter" || event.key === " ") {
1660
+ event.stopPropagation();
1661
+ }
1662
+ };
1663
+ const handleTriggerKeyDown = (event) => {
1664
+ if (settings.disabled) {
1665
+ return;
1666
+ }
1667
+ if (event.key === "Enter" || event.key === " ") {
1668
+ event.preventDefault();
1669
+ toggleDropdown();
1670
+ return;
1671
+ }
1672
+ if (event.key === "ArrowDown") {
1673
+ event.preventDefault();
1674
+ if (!isOpen) {
1675
+ openDropdown("first");
1676
+ } else {
1677
+ focusFirstOption();
1678
+ }
1679
+ return;
1680
+ }
1681
+ if (event.key === "ArrowUp") {
1682
+ event.preventDefault();
1683
+ if (!isOpen) {
1684
+ openDropdown("last");
1685
+ } else {
1686
+ focusLastOption();
1687
+ }
1688
+ return;
1689
+ }
1690
+ if (event.key === "Escape" && isOpen) {
1691
+ event.preventDefault();
1692
+ closeDropdown(true);
1693
+ }
1694
+ };
1695
+ const handleArrowButtonKeyDown = (event) => {
1696
+ if (event.key === "Enter" || event.key === " ") {
1697
+ event.preventDefault();
1698
+ event.stopPropagation();
1699
+ toggleDropdown();
1700
+ return;
1701
+ }
1702
+ if (event.key === "ArrowDown") {
1703
+ event.preventDefault();
1704
+ event.stopPropagation();
1705
+ openDropdown("first");
1706
+ return;
1707
+ }
1708
+ if (event.key === "ArrowUp") {
1709
+ event.preventDefault();
1710
+ event.stopPropagation();
1711
+ openDropdown("last");
1712
+ }
1713
+ };
1714
+ const handleSearchKeyDown = (event) => {
1715
+ if (event.key === "ArrowDown") {
1716
+ event.preventDefault();
1717
+ focusFirstOption();
1718
+ return;
1719
+ }
1720
+ if (event.key === "Escape" && settings.escapeToClose) {
1721
+ event.preventDefault();
1722
+ closeDropdown(true);
1723
+ }
1724
+ };
1725
+ const handleOptionKeyDown = (event, item, optionIndex) => {
1726
+ if (event.key === "Enter" || event.key === " ") {
1727
+ event.preventDefault();
1728
+ selectItem(item);
1729
+ return;
1730
+ }
1731
+ if (event.key === "ArrowDown") {
1732
+ event.preventDefault();
1733
+ const nextIndex = optionIndex + 1;
1734
+ const options = getOptionElements();
1735
+ if (nextIndex < options.length) {
1736
+ focusOptionByIndex(nextIndex);
1737
+ } else if (settings.lazyLoading) {
1738
+ handleListScroll();
1739
+ }
1740
+ return;
1741
+ }
1742
+ if (event.key === "ArrowUp") {
1743
+ event.preventDefault();
1744
+ if (optionIndex > 0) {
1745
+ focusOptionByIndex(optionIndex - 1);
1746
+ } else if (settings.enableSearchFilter) {
1747
+ searchRef.current?.focus();
1748
+ } else {
1749
+ triggerRef.current?.focus();
1750
+ }
1751
+ return;
1752
+ }
1753
+ if (event.key === "Home") {
1754
+ event.preventDefault();
1755
+ focusFirstOption();
1756
+ return;
1757
+ }
1758
+ if (event.key === "End") {
1759
+ event.preventDefault();
1760
+ focusLastOption();
1761
+ return;
1762
+ }
1763
+ if (event.key === "Escape" && settings.escapeToClose) {
1764
+ event.preventDefault();
1765
+ closeDropdown(true);
1766
+ }
1767
+ };
1768
+ const renderItemNode = (item) => {
1769
+ const context = {
1770
+ item,
1771
+ label: getLabel(item, settings),
1772
+ selected: isSelected(item),
1773
+ disabled: settings.disabled || isDisabledItem(item) || !isSelected(item) && limitReached,
1774
+ query: filter,
1775
+ toggle: () => selectItem(item),
1776
+ remove: () => removeItem(item)
1777
+ };
1778
+ return renderItem ? renderItem(item, context) : /* @__PURE__ */ jsxs("div", { className: "rmsd-option-body", children: [
1779
+ /* @__PURE__ */ jsx("div", { className: "rmsd-option-label", children: context.label }),
1780
+ !isPrimitiveItem(item) && item.caption ? /* @__PURE__ */ jsx("span", { className: "rmsd-option-hint", children: String(item.caption) }) : null
1781
+ ] });
1782
+ };
1783
+ const renderBadgeNode = (item) => {
1784
+ const context = {
1785
+ item,
1786
+ label: getLabel(item, settings),
1787
+ selected: true,
1788
+ disabled: settings.disabled || isDisabledItem(item),
1789
+ query: filter,
1790
+ toggle: () => selectItem(item),
1791
+ remove: () => removeItem(item)
1792
+ };
1793
+ return renderBadge ? renderBadge(item, context) : context.label;
1794
+ };
1795
+ let optionCursor = -1;
1796
+ const renderOption = (item, prefix, localIndex) => {
1797
+ const selected = isSelected(item);
1798
+ const disabled = settings.disabled || isDisabledItem(item) || limitReached && !selected;
1799
+ optionCursor += 1;
1800
+ const optionIndex = optionCursor;
1801
+ const optionId = getOptionId(item, localIndex, prefix);
1802
+ return /* @__PURE__ */ jsxs(
1803
+ "div",
1804
+ {
1805
+ id: optionId,
1806
+ className: `rmsd-option${selected ? " rmsd-selected" : ""}${disabled ? " rmsd-disabled" : ""}`,
1807
+ role: "option",
1808
+ "aria-selected": selected,
1809
+ "aria-disabled": disabled,
1810
+ tabIndex: disabled ? -1 : 0,
1811
+ "data-rmsd-option": "true",
1812
+ onFocus: () => setActiveDescendantId(optionId),
1813
+ onClick: () => {
1814
+ if (!disabled) {
1815
+ selectItem(item);
1816
+ }
1817
+ },
1818
+ onKeyDown: (event) => handleOptionKeyDown(event, item, optionIndex),
1819
+ children: [
1820
+ settings.showCheckbox ? /* @__PURE__ */ jsx("span", { className: "rmsd-checkbox", "data-checked": selected, "aria-hidden": "true" }) : null,
1821
+ renderItemNode(item)
1822
+ ]
1823
+ },
1824
+ `${prefix}-${getPrimaryValue(item, settings)}-${localIndex}`
1825
+ );
1826
+ };
1827
+ const handleTriggerClick = (event) => {
1828
+ if (event.target.closest("button")) {
1829
+ return;
1830
+ }
1831
+ toggleDropdown();
1832
+ };
1833
+ const menu = isOpen ? /* @__PURE__ */ jsxs(
1834
+ "div",
1835
+ {
1836
+ ref: menuRef,
1837
+ className: `rmsd-menu rmsd-${effectivePosition} skin-${skinName} theme-${skinName}${skinFallbackClass ? ` ${skinFallbackClass}` : ""}${shouldAppendToBody ? " rmsd-body-overlay" : ""}`,
1838
+ style: shouldAppendToBody ? bodyMenuStyle : void 0,
1839
+ onMouseDown: (event) => event.stopPropagation(),
1840
+ onTouchStart: (event) => event.stopPropagation(),
1841
+ children: [
1842
+ /* @__PURE__ */ jsxs("div", { className: "rmsd-toolbar", children: [
1843
+ hasBulkActions ? /* @__PURE__ */ jsxs("div", { className: "rmsd-bulk-actions", children: [
1844
+ settings.enableCheckAll && !settings.singleSelection ? /* @__PURE__ */ jsxs(
1845
+ "button",
1846
+ {
1847
+ type: "button",
1848
+ className: "rmsd-inline-button rmsd-select-all-button",
1849
+ onClick: () => allFilteredSelected ? deSelectAllItems(selectableItems, Boolean(filter.trim())) : selectAllItems(selectableItems, Boolean(filter.trim())),
1850
+ disabled: settings.disabled || selectableItems.length === 0,
1851
+ children: [
1852
+ settings.showCheckbox ? /* @__PURE__ */ jsx("span", { className: "rmsd-checkbox", "data-checked": allFilteredSelected, "aria-hidden": "true" }) : null,
1853
+ /* @__PURE__ */ jsx("span", { children: allFilteredSelected ? filter.trim() ? settings.filterUnSelectAllText : settings.unSelectAllText : filter.trim() ? settings.filterSelectAllText : settings.selectAllText })
1854
+ ]
1855
+ }
1856
+ ) : null,
1857
+ settings.addNewItemOnFilter && filter.trim() ? /* @__PURE__ */ jsxs("button", { type: "button", className: "rmsd-inline-button rmsd-add-button", onClick: handleAddFilterNewItem, children: [
1858
+ settings.addNewButtonText,
1859
+ ' "',
1860
+ filter.trim(),
1861
+ '"'
1862
+ ] }) : null
1863
+ ] }) : null,
1864
+ settings.enableSearchFilter ? renderSearch ? renderSearch({ query: filter, setQuery: setFilter, closeDropdown: () => closeDropdown() }) : /* @__PURE__ */ jsxs("div", { className: "rmsd-search-shell", children: [
1865
+ /* @__PURE__ */ jsx(StacklineIcon, { name: "search", className: "rmsd-search-icon" }),
1866
+ /* @__PURE__ */ jsx(
1867
+ "input",
1868
+ {
1869
+ ref: searchRef,
1870
+ className: "rmsd-search-input",
1871
+ value: filter,
1872
+ onChange: (event) => setFilter(event.target.value),
1873
+ onKeyDown: handleSearchKeyDown,
1874
+ placeholder: settings.searchPlaceholderText,
1875
+ "aria-label": settings.searchAriaLabel
1876
+ }
1877
+ ),
1878
+ filter ? /* @__PURE__ */ jsx(
1879
+ "button",
1880
+ {
1881
+ type: "button",
1882
+ className: "rmsd-search-clear",
1883
+ "aria-label": settings.clearSearchAriaLabel,
1884
+ onKeyDown: stopInlineKey,
1885
+ onClick: () => setFilter(""),
1886
+ children: /* @__PURE__ */ jsx(StacklineIcon, { name: "clear" })
1887
+ }
1888
+ ) : null
1889
+ ] }) : null
1890
+ ] }),
1891
+ /* @__PURE__ */ jsx(
1892
+ "div",
1893
+ {
1894
+ className: "rmsd-list",
1895
+ ref: listRef,
1896
+ style: { maxHeight: shouldAppendToBody ? bodyListMaxHeight ?? settings.maxHeight : settings.maxHeight },
1897
+ onScroll: settings.lazyLoading ? handleListScroll : void 0,
1898
+ id: listboxId,
1899
+ role: "listbox",
1900
+ "aria-label": settings.listboxAriaLabel,
1901
+ "aria-multiselectable": !settings.singleSelection,
1902
+ children: loading ?? settings.loading ? /* @__PURE__ */ jsx("div", { className: "rmsd-state", role: "status", children: settings.loadingText }) : groupedItems.length > 0 ? groupedItems.map((group, groupIndex) => /* @__PURE__ */ jsxs("div", { className: "rmsd-group", role: "group", "aria-label": group.name, children: [
1903
+ /* @__PURE__ */ jsxs("div", { className: "rmsd-group-header", children: [
1904
+ /* @__PURE__ */ jsxs("span", { children: [
1905
+ group.name,
1906
+ " \xB7 ",
1907
+ group.items.length
1908
+ ] }),
1909
+ settings.selectGroup && !settings.singleSelection ? /* @__PURE__ */ jsx("button", { type: "button", className: "rmsd-group-action", onClick: () => toggleGroup(group.name, group.items), children: group.items.filter((item) => !isDisabledItem(item)).every((item) => isSelected(item)) ? "Unselect" : "Select" }) : null
1910
+ ] }),
1911
+ group.items.map((item, index) => renderOption(item, `group-${groupIndex}`, index))
1912
+ ] }, group.name)) : hasFilteredResults ? filteredItems.map((item, index) => renderOption(item, "item", index)) : /* @__PURE__ */ jsx("div", { className: "rmsd-state", children: renderEmptyState ? renderEmptyState(filter) : settings.noDataLabel })
1913
+ }
1914
+ )
1915
+ ]
1916
+ }
1917
+ ) : null;
1918
+ return /* @__PURE__ */ jsxs("div", { className: rootClassName, style, ref: rootRef, "data-open": isOpen, children: [
1919
+ /* @__PURE__ */ jsxs(
1920
+ "div",
1921
+ {
1922
+ ref: triggerRef,
1923
+ className: `rmsd-trigger${settings.disabled ? " rmsd-disabled" : ""}`,
1924
+ onClick: handleTriggerClick,
1925
+ onKeyDown: handleTriggerKeyDown,
1926
+ tabIndex: settings.disabled ? -1 : 0,
1927
+ role: "combobox",
1928
+ "aria-expanded": isOpen,
1929
+ "aria-haspopup": "listbox",
1930
+ "aria-controls": listboxId,
1931
+ "aria-disabled": settings.disabled,
1932
+ "aria-activedescendant": activeDescendantId || void 0,
1933
+ "aria-label": getTriggerAriaLabel(),
1934
+ children: [
1935
+ /* @__PURE__ */ jsx("div", { className: "rmsd-value", children: selectedItems.length === 0 ? /* @__PURE__ */ jsx("span", { className: "rmsd-placeholder", children: settings.text }) : settings.singleSelection ? /* @__PURE__ */ jsx("span", { className: "rmsd-single-value", children: getLabel(selectedItems[0], settings) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1936
+ /* @__PURE__ */ jsx("div", { className: "rmsd-badge-list", children: visibleBadges.map((item) => /* @__PURE__ */ jsxs("span", { className: "rmsd-badge", children: [
1937
+ /* @__PURE__ */ jsx("span", { className: "rmsd-badge-label", children: renderBadgeNode(item) }),
1938
+ !settings.disabled ? /* @__PURE__ */ jsx(
1939
+ "button",
1940
+ {
1941
+ type: "button",
1942
+ className: "rmsd-badge-remove",
1943
+ "aria-label": getRemoveItemAriaLabel(item),
1944
+ onKeyDown: stopInlineKey,
1945
+ onClick: (event) => {
1946
+ event.stopPropagation();
1947
+ removeItem(item);
1948
+ },
1949
+ children: /* @__PURE__ */ jsx(StacklineIcon, { name: "remove" })
1950
+ }
1951
+ ) : null
1952
+ ] }, getPrimaryValue(item, settings))) }),
1953
+ hiddenBadgeCount > 0 ? /* @__PURE__ */ jsxs("span", { className: "rmsd-overflow", children: [
1954
+ "+",
1955
+ hiddenBadgeCount
1956
+ ] }) : null
1957
+ ] }) }),
1958
+ /* @__PURE__ */ jsxs("div", { className: "rmsd-actions", children: [
1959
+ settings.clearAll && selectedItems.length > 0 && !settings.disabled ? /* @__PURE__ */ jsx(
1960
+ "button",
1961
+ {
1962
+ type: "button",
1963
+ className: "rmsd-clear",
1964
+ "aria-label": settings.clearAllAriaLabel,
1965
+ onKeyDown: stopInlineKey,
1966
+ onClick: (event) => {
1967
+ event.stopPropagation();
1968
+ clearSelection();
1969
+ },
1970
+ children: /* @__PURE__ */ jsx(StacklineIcon, { name: "remove" })
1971
+ }
1972
+ ) : null,
1973
+ /* @__PURE__ */ jsx(
1974
+ "button",
1975
+ {
1976
+ type: "button",
1977
+ className: "rmsd-arrow-button",
1978
+ disabled: settings.disabled,
1979
+ "aria-label": isOpen ? settings.closeDropdownAriaLabel : settings.openDropdownAriaLabel,
1980
+ "aria-expanded": isOpen,
1981
+ "aria-controls": listboxId,
1982
+ onKeyDown: handleArrowButtonKeyDown,
1983
+ onClick: (event) => {
1984
+ event.stopPropagation();
1985
+ toggleDropdown();
1986
+ },
1987
+ children: /* @__PURE__ */ jsx("span", { className: "rmsd-arrow", "aria-hidden": "true", children: /* @__PURE__ */ jsx(StacklineIcon, { name: isOpen ? "angle-up" : "angle-down" }) })
1988
+ }
1989
+ )
1990
+ ] })
1991
+ ]
1992
+ }
1993
+ ),
1994
+ shouldAppendToBody && menu && typeof document !== "undefined" ? createPortal(menu, document.body) : menu
1995
+ ] });
1996
+ }
1997
+ var ReactMultiSelectDropdown = forwardRef(InnerMultiSelectDropdown);
1998
+ var MultiSelectDropdown = ReactMultiSelectDropdown;
1999
+ export {
2000
+ MultiSelectDropdown,
2001
+ ReactMultiSelectDropdown
2002
+ };