lecom-ui 5.4.32 → 5.4.34
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/components/Combobox/Combobox.js +178 -42
- package/dist/components/CustomTagInput/CustomTagInput.js +27 -18
- package/dist/components/DataTable/DataTable.js +2 -2
- package/dist/components/DataTable/DataTable.utils.js +1 -1
- package/dist/components/DataTable/Table.js +1 -1
- package/dist/components/Header/SearchInput.js +4 -1
- package/dist/components/Input/Input.js +2 -2
- package/dist/components/Layout/Layout.js +3 -0
- package/dist/components/MultiSelect/MultiSelect.js +282 -165
- package/dist/components/Pagination/Pagination.js +20 -5
- package/dist/components/ScrollArea/ScrollArea.js +1 -1
- package/dist/components/TagInput/TagInput.js +44 -17
- package/dist/i18n/locales/en_us.js +4 -2
- package/dist/i18n/locales/es_es.js +4 -2
- package/dist/i18n/locales/pt_br.js +4 -2
- package/dist/index.d.ts +21 -11
- package/dist/style.min.css +1 -1
- package/package.json +1 -1
|
@@ -56,14 +56,19 @@ const MultiSelect = React.forwardRef(
|
|
|
56
56
|
allowTypoDistance = 0,
|
|
57
57
|
groupedOptions,
|
|
58
58
|
classNameContent,
|
|
59
|
-
size = "medium"
|
|
59
|
+
size = "medium",
|
|
60
|
+
disabled = false,
|
|
61
|
+
readOnly = false
|
|
60
62
|
}, ref) => {
|
|
61
63
|
const { t } = useTranslation();
|
|
62
64
|
const [selectedValues, setSelectedValues] = React.useState(value);
|
|
63
65
|
const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);
|
|
64
66
|
const [query, setQuery] = React.useState("");
|
|
65
|
-
const [dynamicMaxCount, setDynamicMaxCount] = React.useState(
|
|
67
|
+
const [dynamicMaxCount, setDynamicMaxCount] = React.useState(
|
|
68
|
+
selectedValues.length || 1
|
|
69
|
+
);
|
|
66
70
|
const buttonRef = React.useRef(null);
|
|
71
|
+
const tagsContainerRef = React.useRef(null);
|
|
67
72
|
React.useEffect(() => {
|
|
68
73
|
const shallowEqual = (a, b) => {
|
|
69
74
|
if (a === b) return true;
|
|
@@ -80,7 +85,7 @@ const MultiSelect = React.forwardRef(
|
|
|
80
85
|
}
|
|
81
86
|
if (selectedValues.length === 0) return;
|
|
82
87
|
const calculateMaxCount = () => {
|
|
83
|
-
if (!buttonRef.current) {
|
|
88
|
+
if (!buttonRef.current || !tagsContainerRef.current) {
|
|
84
89
|
setTimeout(() => calculateMaxCount(), 10);
|
|
85
90
|
return;
|
|
86
91
|
}
|
|
@@ -89,57 +94,59 @@ const MultiSelect = React.forwardRef(
|
|
|
89
94
|
setTimeout(() => calculateMaxCount(), 10);
|
|
90
95
|
return;
|
|
91
96
|
}
|
|
92
|
-
const CONTROLS_WIDTH = 80;
|
|
93
|
-
const COUNTER_TAG_WIDTH = 41;
|
|
94
97
|
const TAG_GAP = 4;
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
const
|
|
98
|
-
const
|
|
98
|
+
const BUTTON_PADDING = 4;
|
|
99
|
+
const TAGS_CONTAINER_PADDING = 8;
|
|
100
|
+
const COUNTER_TAG_MAX_WIDTH = 65;
|
|
101
|
+
const ICONS_WIDTH = !disabled && !readOnly ? 48 : 20;
|
|
102
|
+
const availableWidth = buttonWidth - ICONS_WIDTH - BUTTON_PADDING * 2 - TAGS_CONTAINER_PADDING * 2 - TAG_GAP;
|
|
99
103
|
if (availableWidth <= 0) {
|
|
100
104
|
setDynamicMaxCount(1);
|
|
101
105
|
return;
|
|
102
106
|
}
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
const tagElements = tagsContainerRef.current.querySelectorAll("[data-tag-item]");
|
|
108
|
+
if (tagElements.length === 0) {
|
|
109
|
+
setDynamicMaxCount(selectedValues.length);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const tagWidths = [];
|
|
113
|
+
tagElements.forEach((element) => {
|
|
114
|
+
if (!element.hasAttribute("data-counter-tag")) {
|
|
115
|
+
tagWidths.push(element.offsetWidth);
|
|
110
116
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const label = getTreeLabel(selectedValues[i]) || options.find((o) => o.value === selectedValues[i])?.label || selectedValues[i];
|
|
116
|
-
const estimatedWidth = Math.min(
|
|
117
|
-
label.length * AVG_CHAR_WIDTH + TAG_PADDING,
|
|
118
|
-
250
|
|
119
|
-
);
|
|
120
|
-
estimatedWidths.push(estimatedWidth);
|
|
117
|
+
});
|
|
118
|
+
if (tagWidths.length === 0) {
|
|
119
|
+
setTimeout(() => calculateMaxCount(), 10);
|
|
120
|
+
return;
|
|
121
121
|
}
|
|
122
|
-
let
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
let totalWidthWithoutCounter = 0;
|
|
123
|
+
let countWithoutCounter = 0;
|
|
124
|
+
for (let i = 0; i < tagWidths.length; i++) {
|
|
125
|
+
const widthNeeded = tagWidths[i] + (i > 0 ? TAG_GAP : 0);
|
|
126
|
+
if (totalWidthWithoutCounter + widthNeeded <= availableWidth) {
|
|
127
|
+
totalWidthWithoutCounter += widthNeeded;
|
|
128
|
+
countWithoutCounter++;
|
|
129
|
+
} else {
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
125
132
|
}
|
|
126
|
-
if (
|
|
133
|
+
if (countWithoutCounter >= selectedValues.length) {
|
|
127
134
|
setDynamicMaxCount(selectedValues.length);
|
|
128
135
|
return;
|
|
129
136
|
}
|
|
130
|
-
const
|
|
131
|
-
let
|
|
132
|
-
|
|
133
|
-
for (let i = 0; i <
|
|
134
|
-
const
|
|
135
|
-
if (
|
|
136
|
-
|
|
137
|
-
|
|
137
|
+
const availableWidthWithCounter = availableWidth - COUNTER_TAG_MAX_WIDTH - TAG_GAP;
|
|
138
|
+
let totalWidthWithCounter = 0;
|
|
139
|
+
let countWithCounter = 0;
|
|
140
|
+
for (let i = 0; i < tagWidths.length; i++) {
|
|
141
|
+
const widthNeeded = tagWidths[i] + (i > 0 ? TAG_GAP : 0);
|
|
142
|
+
if (totalWidthWithCounter + widthNeeded <= availableWidthWithCounter) {
|
|
143
|
+
totalWidthWithCounter += widthNeeded;
|
|
144
|
+
countWithCounter++;
|
|
138
145
|
} else {
|
|
139
146
|
break;
|
|
140
147
|
}
|
|
141
148
|
}
|
|
142
|
-
setDynamicMaxCount(Math.max(1,
|
|
149
|
+
setDynamicMaxCount(Math.max(1, countWithCounter));
|
|
143
150
|
};
|
|
144
151
|
const rafId = requestAnimationFrame(() => {
|
|
145
152
|
calculateMaxCount();
|
|
@@ -154,7 +161,7 @@ const MultiSelect = React.forwardRef(
|
|
|
154
161
|
cancelAnimationFrame(rafId);
|
|
155
162
|
resizeObserver.disconnect();
|
|
156
163
|
};
|
|
157
|
-
}, [maxCount, selectedValues, treeOptions, options]);
|
|
164
|
+
}, [maxCount, selectedValues, treeOptions, options, disabled, readOnly]);
|
|
158
165
|
const handleInputKeyDown = (event) => {
|
|
159
166
|
if (event.key === "Enter") {
|
|
160
167
|
setIsPopoverOpen(true);
|
|
@@ -166,11 +173,13 @@ const MultiSelect = React.forwardRef(
|
|
|
166
173
|
}
|
|
167
174
|
};
|
|
168
175
|
const toggleOption = (option) => {
|
|
176
|
+
if (readOnly) return;
|
|
169
177
|
const newSelectedValues = selectedValues.includes(option) ? selectedValues.filter((value2) => value2 !== option) : [...selectedValues, option];
|
|
170
178
|
setSelectedValues(newSelectedValues);
|
|
171
179
|
onValueChange(newSelectedValues);
|
|
172
180
|
};
|
|
173
181
|
const handleClear = () => {
|
|
182
|
+
if (readOnly) return;
|
|
174
183
|
setSelectedValues([]);
|
|
175
184
|
onValueChange([]);
|
|
176
185
|
};
|
|
@@ -178,6 +187,7 @@ const MultiSelect = React.forwardRef(
|
|
|
178
187
|
setIsPopoverOpen((prev) => !prev);
|
|
179
188
|
};
|
|
180
189
|
const toggleAll = () => {
|
|
190
|
+
if (readOnly) return;
|
|
181
191
|
if (treeOptions && treeOptions.length) {
|
|
182
192
|
const gather = (acc, nodes) => {
|
|
183
193
|
for (const n of nodes) {
|
|
@@ -340,7 +350,10 @@ const MultiSelect = React.forwardRef(
|
|
|
340
350
|
if (!node.children || node.children.length === 0) {
|
|
341
351
|
return [node.value];
|
|
342
352
|
}
|
|
343
|
-
return [
|
|
353
|
+
return [
|
|
354
|
+
node.value,
|
|
355
|
+
...node.children.flatMap((c) => collectAllValues(c))
|
|
356
|
+
];
|
|
344
357
|
}
|
|
345
358
|
};
|
|
346
359
|
const isNodeFullySelected = (node) => {
|
|
@@ -371,6 +384,7 @@ const MultiSelect = React.forwardRef(
|
|
|
371
384
|
}
|
|
372
385
|
};
|
|
373
386
|
const toggleTreeNode = (node) => {
|
|
387
|
+
if (readOnly) return;
|
|
374
388
|
if (treeSelectionStrategy === "all") {
|
|
375
389
|
const isSelected = selectedValues.includes(node.value);
|
|
376
390
|
const next = isSelected ? selectedValues.filter((v) => v !== node.value) : [...selectedValues, node.value];
|
|
@@ -454,7 +468,8 @@ const MultiSelect = React.forwardRef(
|
|
|
454
468
|
{
|
|
455
469
|
className: cn(
|
|
456
470
|
"flex items-center gap-2 px-2 py-1 cursor-pointer rounded-sm text-grey-800 hover:bg-grey-100",
|
|
457
|
-
(fully || isSelectedLeaf) && "bg-blue-50"
|
|
471
|
+
(fully || isSelectedLeaf) && "bg-blue-50",
|
|
472
|
+
readOnly && "cursor-default hover:bg-transparent"
|
|
458
473
|
),
|
|
459
474
|
style: { paddingLeft: depth * 14 + 8 }
|
|
460
475
|
},
|
|
@@ -467,7 +482,9 @@ const MultiSelect = React.forwardRef(
|
|
|
467
482
|
),
|
|
468
483
|
onClick: (e) => {
|
|
469
484
|
e.stopPropagation();
|
|
470
|
-
|
|
485
|
+
if (!readOnly) {
|
|
486
|
+
toggleTreeNode(n);
|
|
487
|
+
}
|
|
471
488
|
}
|
|
472
489
|
},
|
|
473
490
|
fully && /* @__PURE__ */ React.createElement(Check, { className: "!h-3 !w-3 !text-white", strokeWidth: 3 }),
|
|
@@ -480,7 +497,9 @@ const MultiSelect = React.forwardRef(
|
|
|
480
497
|
className: "flex-1 truncate cursor-pointer overflow-hidden",
|
|
481
498
|
onClick: (e) => {
|
|
482
499
|
e.stopPropagation();
|
|
483
|
-
|
|
500
|
+
if (!readOnly) {
|
|
501
|
+
toggleTreeNode(n);
|
|
502
|
+
}
|
|
484
503
|
},
|
|
485
504
|
title: n.label
|
|
486
505
|
},
|
|
@@ -514,43 +533,65 @@ const MultiSelect = React.forwardRef(
|
|
|
514
533
|
transition-all duration-300 outline-none
|
|
515
534
|
[&_svg]:pointer-events-auto`,
|
|
516
535
|
maxCount === void 0 && TRIGGER_HEIGHT_CLASSES[size],
|
|
536
|
+
disabled && "opacity-50 cursor-not-allowed pointer-events-none",
|
|
537
|
+
readOnly && !disabled && "opacity-50 hover:border-grey-400",
|
|
517
538
|
className
|
|
518
539
|
),
|
|
519
|
-
"aria-expanded": isPopoverOpen
|
|
540
|
+
"aria-expanded": isPopoverOpen,
|
|
541
|
+
disabled
|
|
520
542
|
},
|
|
521
|
-
selectedValues.length > 0 ? /* @__PURE__ */ React.createElement("div", { className: "flex justify-between items-center w-full" }, /* @__PURE__ */ React.createElement("div", { className: "flex
|
|
522
|
-
const selectedOption = options.find(
|
|
543
|
+
selectedValues.length > 0 ? /* @__PURE__ */ React.createElement("div", { className: "flex justify-between items-center w-full px-2" }, /* @__PURE__ */ React.createElement("div", { ref: tagsContainerRef, className: "flex items-center gap-1 flex-nowrap overflow-hidden" }, selectedValues.slice(0, dynamicMaxCount).map((value2) => {
|
|
544
|
+
const selectedOption = options.find(
|
|
545
|
+
(option) => option.value === value2
|
|
546
|
+
);
|
|
523
547
|
const label = findTreeLabel(value2) || selectedOption?.label || value2;
|
|
524
548
|
const prefix = selectedOption?.prefix;
|
|
525
|
-
return /* @__PURE__ */ React.createElement(
|
|
526
|
-
|
|
527
|
-
{
|
|
528
|
-
className: "flex items-center flex-shrink-0 [&_svg]:text-blue-600",
|
|
529
|
-
textColor: "text-blue-600"
|
|
530
|
-
},
|
|
531
|
-
prefix
|
|
532
|
-
), /* @__PURE__ */ React.createElement(
|
|
533
|
-
Typography,
|
|
549
|
+
return /* @__PURE__ */ React.createElement(
|
|
550
|
+
Tag,
|
|
534
551
|
{
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
className: "
|
|
552
|
+
key: value2,
|
|
553
|
+
color: "blue",
|
|
554
|
+
className: "focus:ring-0 flex items-center gap-2 max-w-[15.625rem]",
|
|
555
|
+
"data-tag-item": true
|
|
538
556
|
},
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
557
|
+
/* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 truncate min-w-0" }, prefix && /* @__PURE__ */ React.createElement(
|
|
558
|
+
Typography,
|
|
559
|
+
{
|
|
560
|
+
className: "flex items-center flex-shrink-0 [&_svg]:text-blue-600",
|
|
561
|
+
textColor: "text-blue-600"
|
|
562
|
+
},
|
|
563
|
+
prefix
|
|
564
|
+
), /* @__PURE__ */ React.createElement(
|
|
565
|
+
Typography,
|
|
566
|
+
{
|
|
567
|
+
variant: getFontVariant(size),
|
|
568
|
+
textColor: "text-blue-600",
|
|
569
|
+
className: "truncate"
|
|
570
|
+
},
|
|
571
|
+
label
|
|
572
|
+
)),
|
|
573
|
+
!disabled && !readOnly && /* @__PURE__ */ React.createElement(
|
|
574
|
+
X,
|
|
575
|
+
{
|
|
576
|
+
className: "h-5 w-5 cursor-pointer flex-shrink-0",
|
|
577
|
+
onClick: (event) => {
|
|
578
|
+
event.stopPropagation();
|
|
579
|
+
toggleOption(value2);
|
|
580
|
+
}
|
|
547
581
|
}
|
|
548
|
-
|
|
549
|
-
)
|
|
550
|
-
}), selectedValues.length > dynamicMaxCount && /* @__PURE__ */ React.createElement(Tag, { color: "blue", className: "focus:ring-0"
|
|
582
|
+
)
|
|
583
|
+
);
|
|
584
|
+
}), selectedValues.length > dynamicMaxCount && /* @__PURE__ */ React.createElement(Tag, { color: "blue", className: "focus:ring-0", "data-tag-item": true, "data-counter-tag": true }, /* @__PURE__ */ React.createElement(
|
|
585
|
+
Typography,
|
|
586
|
+
{
|
|
587
|
+
variant: getFontVariant(size),
|
|
588
|
+
className: "text-blue-600"
|
|
589
|
+
},
|
|
590
|
+
`+ ${selectedValues.length - dynamicMaxCount}`
|
|
591
|
+
))), /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-between" }, !disabled && !readOnly && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
551
592
|
X,
|
|
552
593
|
{
|
|
553
|
-
className: "h-
|
|
594
|
+
className: "h-5 w-5 cursor-pointer text-grey-800",
|
|
554
595
|
onClick: (event) => {
|
|
555
596
|
event.stopPropagation();
|
|
556
597
|
handleClear();
|
|
@@ -560,13 +601,13 @@ const MultiSelect = React.forwardRef(
|
|
|
560
601
|
Separator,
|
|
561
602
|
{
|
|
562
603
|
orientation: "vertical",
|
|
563
|
-
className: "flex min-h-
|
|
604
|
+
className: "flex min-h-5 mx-1 h-full"
|
|
564
605
|
}
|
|
565
|
-
), isPopoverOpen ? /* @__PURE__ */ React.createElement(ChevronUp, { className: "h-
|
|
606
|
+
)), isPopoverOpen ? /* @__PURE__ */ React.createElement(ChevronUp, { className: "h-5 w-5 cursor-pointer text-grey-800" }) : /* @__PURE__ */ React.createElement(ChevronDown, { className: "h-5 w-5 cursor-pointer text-grey-800" }))) : /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-between w-full mx-auto" }, /* @__PURE__ */ React.createElement(
|
|
566
607
|
Typography,
|
|
567
608
|
{
|
|
568
609
|
variant: getFontVariant(size),
|
|
569
|
-
className: "text-grey-
|
|
610
|
+
className: "text-grey-500 mx-3"
|
|
570
611
|
},
|
|
571
612
|
placeholder
|
|
572
613
|
), isPopoverOpen ? /* @__PURE__ */ React.createElement(ChevronUp, { className: "h-4 cursor-pointer text-grey-800 mx-2" }) : /* @__PURE__ */ React.createElement(ChevronDown, { className: "h-4 cursor-pointer text-grey-800 mx-2" }))
|
|
@@ -583,114 +624,165 @@ const MultiSelect = React.forwardRef(
|
|
|
583
624
|
align: "start",
|
|
584
625
|
onEscapeKeyDown: () => setIsPopoverOpen(false)
|
|
585
626
|
},
|
|
586
|
-
!isTree && /* @__PURE__ */ React.createElement(
|
|
587
|
-
|
|
588
|
-
{
|
|
589
|
-
placeholder: treeSearchPlaceholder || t("multiSelect.search"),
|
|
590
|
-
onKeyDown: handleInputKeyDown,
|
|
591
|
-
value: query,
|
|
592
|
-
onValueChange: (v) => setQuery(v)
|
|
593
|
-
}
|
|
594
|
-
), /* @__PURE__ */ React.createElement(CommandList, null, /* @__PURE__ */ React.createElement(CommandGroup, null, (effectiveOptions.length === 0 || query && filteredOptions.length === 0) && /* @__PURE__ */ React.createElement(CommandEmpty, { className: cn("p-4 text-center text-grey-800", getFontVariant(size)) }, t("multiSelect.empty")), !query && effectiveOptions.length > 0 && /* @__PURE__ */ React.createElement(
|
|
595
|
-
CommandItem,
|
|
627
|
+
!isTree && /* @__PURE__ */ React.createElement(
|
|
628
|
+
Command,
|
|
596
629
|
{
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
className: "cursor-pointer"
|
|
630
|
+
shouldFilter: false,
|
|
631
|
+
className: SEARCH_INPUT_CLASSES[size]
|
|
600
632
|
},
|
|
601
633
|
/* @__PURE__ */ React.createElement(
|
|
602
|
-
|
|
634
|
+
CommandInput,
|
|
603
635
|
{
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
)
|
|
608
|
-
|
|
609
|
-
|
|
636
|
+
placeholder: treeSearchPlaceholder || t("multiSelect.search"),
|
|
637
|
+
onKeyDown: handleInputKeyDown,
|
|
638
|
+
value: query,
|
|
639
|
+
onValueChange: (v) => setQuery(v),
|
|
640
|
+
disabled: readOnly
|
|
641
|
+
}
|
|
610
642
|
),
|
|
611
|
-
/* @__PURE__ */ React.createElement(
|
|
612
|
-
|
|
643
|
+
/* @__PURE__ */ React.createElement(CommandList, null, /* @__PURE__ */ React.createElement(CommandGroup, null, (effectiveOptions.length === 0 || query && filteredOptions.length === 0) && /* @__PURE__ */ React.createElement(
|
|
644
|
+
CommandEmpty,
|
|
613
645
|
{
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
selectAllLabel ?? t("multiSelect.selectAll")
|
|
618
|
-
)
|
|
619
|
-
), isGrouped ? Object.entries(groupedOptions).map(
|
|
620
|
-
([categoryName, categoryOptions]) => {
|
|
621
|
-
const filtered = categoryOptions.filter(
|
|
622
|
-
(opt) => !query || effectiveOptions.some(
|
|
623
|
-
(eff) => eff.value === opt.value && filteredOptions.some(
|
|
624
|
-
(filt) => filt.value === opt.value
|
|
625
|
-
)
|
|
646
|
+
className: cn(
|
|
647
|
+
"p-4 text-center text-grey-800",
|
|
648
|
+
getFontVariant(size)
|
|
626
649
|
)
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
const isSelected = selectedValues.includes(
|
|
631
|
-
option.value
|
|
632
|
-
);
|
|
633
|
-
return /* @__PURE__ */ React.createElement(
|
|
634
|
-
CommandItem,
|
|
635
|
-
{
|
|
636
|
-
key: option.value,
|
|
637
|
-
onSelect: () => toggleOption(option.value),
|
|
638
|
-
className: "cursor-pointer"
|
|
639
|
-
},
|
|
640
|
-
/* @__PURE__ */ React.createElement(
|
|
641
|
-
"div",
|
|
642
|
-
{
|
|
643
|
-
className: cn(
|
|
644
|
-
"flex h-4 w-4 items-center justify-center rounded-sm border-2 border-grey-400 flex-shrink-0",
|
|
645
|
-
isSelected ? "bg-blue-600 border-blue-600 text-primary-foreground" : "opacity-50 [&_svg]:invisible"
|
|
646
|
-
)
|
|
647
|
-
},
|
|
648
|
-
/* @__PURE__ */ React.createElement(Check, { className: "!h-3 !w-3 !text-white", strokeWidth: 3 })
|
|
649
|
-
),
|
|
650
|
-
/* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 truncate min-w-0" }, option.prefix && /* @__PURE__ */ React.createElement(Typography, { className: "flex items-center flex-shrink-0" }, option.prefix), /* @__PURE__ */ React.createElement(
|
|
651
|
-
Typography,
|
|
652
|
-
{
|
|
653
|
-
variant: getFontVariant(size),
|
|
654
|
-
className: "text-grey-800 truncate overflow-hidden",
|
|
655
|
-
title: option.label
|
|
656
|
-
},
|
|
657
|
-
highlight(option.label, query)
|
|
658
|
-
))
|
|
659
|
-
);
|
|
660
|
-
}));
|
|
661
|
-
}
|
|
662
|
-
) : filteredOptions.map((option) => {
|
|
663
|
-
const isSelected = selectedValues.includes(
|
|
664
|
-
option.value
|
|
665
|
-
);
|
|
666
|
-
return /* @__PURE__ */ React.createElement(
|
|
650
|
+
},
|
|
651
|
+
t("multiSelect.empty")
|
|
652
|
+
), !query && effectiveOptions.length > 0 && /* @__PURE__ */ React.createElement(
|
|
667
653
|
CommandItem,
|
|
668
654
|
{
|
|
669
|
-
key:
|
|
670
|
-
onSelect:
|
|
671
|
-
className:
|
|
655
|
+
key: "all",
|
|
656
|
+
onSelect: readOnly ? void 0 : toggleAll,
|
|
657
|
+
className: cn(
|
|
658
|
+
"cursor-pointer",
|
|
659
|
+
readOnly && "cursor-default pointer-events-none hover:bg-transparent"
|
|
660
|
+
)
|
|
672
661
|
},
|
|
673
662
|
/* @__PURE__ */ React.createElement(
|
|
674
663
|
"div",
|
|
675
664
|
{
|
|
676
665
|
className: cn(
|
|
677
|
-
"flex h-4 w-4 items-center justify-center rounded-sm border border-grey-800
|
|
678
|
-
|
|
666
|
+
"flex h-4 w-4 items-center justify-center rounded-sm border border-grey-800",
|
|
667
|
+
selectedValues.length > 0 ? "bg-blue-600 border-blue-600 text-primary-foreground" : "opacity-50 [&_svg]:invisible"
|
|
679
668
|
)
|
|
680
669
|
},
|
|
681
|
-
/* @__PURE__ */ React.createElement(
|
|
670
|
+
selectedValues.length === effectiveOptions.length ? /* @__PURE__ */ React.createElement(
|
|
671
|
+
Check,
|
|
672
|
+
{
|
|
673
|
+
className: "!h-3 !w-3 !text-white",
|
|
674
|
+
strokeWidth: 3
|
|
675
|
+
}
|
|
676
|
+
) : /* @__PURE__ */ React.createElement(
|
|
677
|
+
Minus,
|
|
678
|
+
{
|
|
679
|
+
className: "!h-3 !w-3 !text-white",
|
|
680
|
+
strokeWidth: 3
|
|
681
|
+
}
|
|
682
|
+
)
|
|
682
683
|
),
|
|
683
|
-
/* @__PURE__ */ React.createElement(
|
|
684
|
+
/* @__PURE__ */ React.createElement(
|
|
684
685
|
Typography,
|
|
685
686
|
{
|
|
686
687
|
variant: getFontVariant(size),
|
|
687
|
-
className: "text-grey-800
|
|
688
|
-
title: option.label
|
|
688
|
+
className: "text-grey-800"
|
|
689
689
|
},
|
|
690
|
-
|
|
691
|
-
)
|
|
692
|
-
)
|
|
693
|
-
|
|
690
|
+
selectAllLabel ?? t("multiSelect.selectAll")
|
|
691
|
+
)
|
|
692
|
+
), isGrouped ? Object.entries(groupedOptions).map(
|
|
693
|
+
([categoryName, categoryOptions]) => {
|
|
694
|
+
const filtered = categoryOptions.filter(
|
|
695
|
+
(opt) => !query || effectiveOptions.some(
|
|
696
|
+
(eff) => eff.value === opt.value && filteredOptions.some(
|
|
697
|
+
(filt) => filt.value === opt.value
|
|
698
|
+
)
|
|
699
|
+
)
|
|
700
|
+
);
|
|
701
|
+
if (!filtered.length) return null;
|
|
702
|
+
return /* @__PURE__ */ React.createElement("div", { key: categoryName }, /* @__PURE__ */ React.createElement("div", { className: "px-2 py-2 text-xs font-medium text-muted-foreground" }, categoryName), filtered.map((option) => {
|
|
703
|
+
const isSelected = selectedValues.includes(
|
|
704
|
+
option.value
|
|
705
|
+
);
|
|
706
|
+
return /* @__PURE__ */ React.createElement(
|
|
707
|
+
CommandItem,
|
|
708
|
+
{
|
|
709
|
+
key: option.value,
|
|
710
|
+
onSelect: readOnly ? void 0 : () => toggleOption(option.value),
|
|
711
|
+
className: cn(
|
|
712
|
+
"cursor-pointer",
|
|
713
|
+
readOnly && "cursor-default pointer-events-none hover:bg-transparent"
|
|
714
|
+
)
|
|
715
|
+
},
|
|
716
|
+
/* @__PURE__ */ React.createElement(
|
|
717
|
+
"div",
|
|
718
|
+
{
|
|
719
|
+
className: cn(
|
|
720
|
+
"flex h-4 w-4 items-center justify-center rounded-sm border-2 border-grey-400 flex-shrink-0",
|
|
721
|
+
isSelected ? "bg-blue-600 border-blue-600 text-primary-foreground" : "opacity-50 [&_svg]:invisible"
|
|
722
|
+
)
|
|
723
|
+
},
|
|
724
|
+
/* @__PURE__ */ React.createElement(
|
|
725
|
+
Check,
|
|
726
|
+
{
|
|
727
|
+
className: "!h-3 !w-3 !text-white",
|
|
728
|
+
strokeWidth: 3
|
|
729
|
+
}
|
|
730
|
+
)
|
|
731
|
+
),
|
|
732
|
+
/* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 min-w-0" }, option.prefix && /* @__PURE__ */ React.createElement(Typography, { className: "flex items-center flex-shrink-0" }, option.prefix), /* @__PURE__ */ React.createElement(
|
|
733
|
+
Typography,
|
|
734
|
+
{
|
|
735
|
+
variant: getFontVariant(size),
|
|
736
|
+
className: "text-grey-800 break-words",
|
|
737
|
+
title: option.label
|
|
738
|
+
},
|
|
739
|
+
highlight(option.label, query)
|
|
740
|
+
))
|
|
741
|
+
);
|
|
742
|
+
}));
|
|
743
|
+
}
|
|
744
|
+
) : filteredOptions.map((option) => {
|
|
745
|
+
const isSelected = selectedValues.includes(
|
|
746
|
+
option.value
|
|
747
|
+
);
|
|
748
|
+
return /* @__PURE__ */ React.createElement(
|
|
749
|
+
CommandItem,
|
|
750
|
+
{
|
|
751
|
+
key: option.value,
|
|
752
|
+
onSelect: readOnly ? void 0 : () => toggleOption(option.value),
|
|
753
|
+
className: cn(
|
|
754
|
+
"cursor-pointer",
|
|
755
|
+
readOnly && "cursor-default pointer-events-none hover:bg-transparent"
|
|
756
|
+
)
|
|
757
|
+
},
|
|
758
|
+
/* @__PURE__ */ React.createElement(
|
|
759
|
+
"div",
|
|
760
|
+
{
|
|
761
|
+
className: cn(
|
|
762
|
+
"flex h-4 w-4 items-center justify-center rounded-sm border border-grey-800 flex-shrink-0",
|
|
763
|
+
isSelected ? "bg-blue-600 border-blue-600 text-primary-foreground" : "opacity-50 [&_svg]:invisible"
|
|
764
|
+
)
|
|
765
|
+
},
|
|
766
|
+
/* @__PURE__ */ React.createElement(
|
|
767
|
+
Check,
|
|
768
|
+
{
|
|
769
|
+
className: "!h-3 !w-3 !text-white",
|
|
770
|
+
strokeWidth: 3
|
|
771
|
+
}
|
|
772
|
+
)
|
|
773
|
+
),
|
|
774
|
+
/* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 min-w-0" }, option.prefix && /* @__PURE__ */ React.createElement(Typography, { className: "flex items-center flex-shrink-0" }, option.prefix), /* @__PURE__ */ React.createElement(
|
|
775
|
+
Typography,
|
|
776
|
+
{
|
|
777
|
+
variant: getFontVariant(size),
|
|
778
|
+
className: "text-grey-800 break-words",
|
|
779
|
+
title: option.label
|
|
780
|
+
},
|
|
781
|
+
highlight(option.label, query)
|
|
782
|
+
))
|
|
783
|
+
);
|
|
784
|
+
})))
|
|
785
|
+
),
|
|
694
786
|
isTree && /* @__PURE__ */ React.createElement("div", { className: "min-w-[260px] max-h-80 overflow-hidden flex flex-col" }, treeSearch && /* @__PURE__ */ React.createElement("div", { className: "px-1 pt-2 pb-0 border-b border-grey-300 flex-shrink-0" }, /* @__PURE__ */ React.createElement("div", { className: "relative" }, /* @__PURE__ */ React.createElement(
|
|
695
787
|
"svg",
|
|
696
788
|
{
|
|
@@ -715,6 +807,7 @@ const MultiSelect = React.forwardRef(
|
|
|
715
807
|
value: treeQuery,
|
|
716
808
|
onChange: (e) => setTreeQuery(e.target.value),
|
|
717
809
|
placeholder: treeSearchPlaceholder || t("multiSelect.search"),
|
|
810
|
+
disabled: readOnly,
|
|
718
811
|
className: cn(
|
|
719
812
|
"w-full pl-9 pr-3 border-0 focus:outline-none focus:ring-0 bg-transparent placeholder:text-muted-foreground",
|
|
720
813
|
getFontVariant(size),
|
|
@@ -724,8 +817,11 @@ const MultiSelect = React.forwardRef(
|
|
|
724
817
|
))), /* @__PURE__ */ React.createElement("div", { className: "px-2 pb-1 overflow-y-auto overflow-x-hidden [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-grey-300 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb:hover]:bg-grey-400" }, !treeQuery && treeOptions && treeOptions.length > 0 && /* @__PURE__ */ React.createElement(
|
|
725
818
|
"div",
|
|
726
819
|
{
|
|
727
|
-
className:
|
|
728
|
-
|
|
820
|
+
className: cn(
|
|
821
|
+
"flex items-center gap-2 px-2 py-1 cursor-pointer rounded-sm hover:bg-accent",
|
|
822
|
+
readOnly && "cursor-default hover:bg-transparent pointer-events-none"
|
|
823
|
+
),
|
|
824
|
+
onClick: readOnly ? void 0 : toggleAll
|
|
729
825
|
},
|
|
730
826
|
/* @__PURE__ */ React.createElement(
|
|
731
827
|
"div",
|
|
@@ -745,7 +841,19 @@ const MultiSelect = React.forwardRef(
|
|
|
745
841
|
acc += treeSelectionStrategy === "all" ? 1 + countAll(n.children) : countAll(n.children);
|
|
746
842
|
}
|
|
747
843
|
return acc;
|
|
748
|
-
}(treeOptions) ? /* @__PURE__ */ React.createElement(
|
|
844
|
+
}(treeOptions) ? /* @__PURE__ */ React.createElement(
|
|
845
|
+
Check,
|
|
846
|
+
{
|
|
847
|
+
className: "!h-3 !w-3 !text-white",
|
|
848
|
+
strokeWidth: 3
|
|
849
|
+
}
|
|
850
|
+
) : /* @__PURE__ */ React.createElement(
|
|
851
|
+
Minus,
|
|
852
|
+
{
|
|
853
|
+
className: "!h-3 !w-3 !text-white",
|
|
854
|
+
strokeWidth: 3
|
|
855
|
+
}
|
|
856
|
+
)
|
|
749
857
|
),
|
|
750
858
|
/* @__PURE__ */ React.createElement(
|
|
751
859
|
Typography,
|
|
@@ -755,7 +863,16 @@ const MultiSelect = React.forwardRef(
|
|
|
755
863
|
},
|
|
756
864
|
selectAllLabel ?? t("multiSelect.selectAll")
|
|
757
865
|
)
|
|
758
|
-
), !treeOptions || treeOptions.length === 0 || treeQuery && displayedTree.length === 0 ? /* @__PURE__ */ React.createElement(
|
|
866
|
+
), !treeOptions || treeOptions.length === 0 || treeQuery && displayedTree.length === 0 ? /* @__PURE__ */ React.createElement(
|
|
867
|
+
"div",
|
|
868
|
+
{
|
|
869
|
+
className: cn(
|
|
870
|
+
"p-4 text-center text-grey-800",
|
|
871
|
+
getFontVariant(size)
|
|
872
|
+
)
|
|
873
|
+
},
|
|
874
|
+
t("multiSelect.empty")
|
|
875
|
+
) : renderTree(displayedTree)))
|
|
759
876
|
)
|
|
760
877
|
);
|
|
761
878
|
}
|