lecom-ui 5.4.43 → 5.4.45
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/README.md +1 -1
- package/dist/components/Accordion/Accordion.js +22 -19
- package/dist/components/Chart/Chart.js +1 -1
- package/dist/components/Combobox/Combobox.js +17 -4
- package/dist/components/CustomTagInput/CustomTagInput.js +107 -33
- package/dist/components/Dialog/Dialog.js +2 -2
- package/dist/components/Input/Input.js +9 -4
- package/dist/components/Label/Label.js +39 -3
- package/dist/components/MultiSelect/MultiSelect.js +214 -179
- package/dist/components/Textarea/Textarea.js +9 -5
- package/dist/hooks/useDynamicMaxHeight.js +49 -0
- package/dist/i18n/locales/en_us.js +4 -0
- package/dist/i18n/locales/es_es.js +4 -0
- package/dist/i18n/locales/pt_br.js +4 -0
- package/dist/index.d.ts +31 -13
- package/dist/index.js +2 -1
- package/dist/plugin/extend.js +79 -79
- package/dist/plugin/fontFaces.js +172 -172
- package/dist/plugin/general.js +12 -12
- package/dist/plugin/pluginDev.cjs +5 -5
- package/dist/plugin/pluginNext.cjs +5 -5
- package/dist/plugin/pluginNextTurbo.cjs +5 -5
- package/dist/plugin/pluginVite.cjs +5 -5
- package/dist/plugin/template.js +31 -31
- package/dist/plugin/typographies.js +152 -152
- package/dist/plugin/varsTheme.js +79 -79
- package/dist/style.min.css +1 -1
- package/package.json +1 -1
- package/dist/components/Collapse/Collapse.js +0 -94
- package/dist/components/CustomIcon/Icons/CadastroFacil.js +0 -23
- package/dist/components/CustomIcon/Icons/LogoLecom.js +0 -30
- package/dist/components/CustomIcon/Icons/LogoLecomBrand.js +0 -23
- package/dist/components/CustomIcon/Icons/ModoTeste.js +0 -23
- package/dist/components/CustomIcon/Icons/Rpa.js +0 -23
- package/dist/components/CustomIcon/Icons/SairModoTeste.js +0 -31
- package/dist/components/IconHandler/IconHandler.js +0 -99
|
@@ -7,6 +7,7 @@ import { Tag } from '../Tag/Tag.js';
|
|
|
7
7
|
import { Typography } from '../Typography/Typography.js';
|
|
8
8
|
import { cn } from '../../lib/utils.js';
|
|
9
9
|
import { X, ChevronUp, ChevronDown, Check, Minus } from 'lucide-react';
|
|
10
|
+
import { useDynamicMaxHeight } from '../../hooks/useDynamicMaxHeight.js';
|
|
10
11
|
import { initializeI18n } from '../../i18n/index.js';
|
|
11
12
|
|
|
12
13
|
initializeI18n();
|
|
@@ -15,6 +16,10 @@ const TRIGGER_HEIGHT_CLASSES = {
|
|
|
15
16
|
medium: "!h-10",
|
|
16
17
|
large: "!h-12"
|
|
17
18
|
};
|
|
19
|
+
const STATUS_STYLES = {
|
|
20
|
+
default: "border-grey-400 hover:border-grey-500 focus:border-grey-400 focus:ring-grey-600",
|
|
21
|
+
error: "border-red-600 hover:border-red-600 focus:border-red-600 focus:ring-0"
|
|
22
|
+
};
|
|
18
23
|
const SEARCH_INPUT_HEIGHT_CLASSES = {
|
|
19
24
|
small: "h-7",
|
|
20
25
|
medium: "h-8",
|
|
@@ -58,7 +63,11 @@ const MultiSelect = React.forwardRef(
|
|
|
58
63
|
classNameContent,
|
|
59
64
|
size = "medium",
|
|
60
65
|
disabled = false,
|
|
61
|
-
readOnly = false
|
|
66
|
+
readOnly = false,
|
|
67
|
+
status = "default",
|
|
68
|
+
dynamicHeight = true,
|
|
69
|
+
dynamicHeightBottomPadding = 50,
|
|
70
|
+
dynamicHeightMinHeight = 120
|
|
62
71
|
}, ref) => {
|
|
63
72
|
const { t } = useTranslation();
|
|
64
73
|
const [selectedValues, setSelectedValues] = React.useState(value);
|
|
@@ -68,6 +77,11 @@ const MultiSelect = React.forwardRef(
|
|
|
68
77
|
selectedValues.length || 1
|
|
69
78
|
);
|
|
70
79
|
const buttonRef = React.useRef(null);
|
|
80
|
+
const { ref: dynamicHeightRef, style: dynamicHeightStyle } = useDynamicMaxHeight({
|
|
81
|
+
enabled: dynamicHeight && isPopoverOpen,
|
|
82
|
+
bottomPadding: dynamicHeightBottomPadding,
|
|
83
|
+
minHeight: dynamicHeightMinHeight
|
|
84
|
+
});
|
|
71
85
|
React.useEffect(() => {
|
|
72
86
|
const shallowEqual = (a, b) => {
|
|
73
87
|
if (a === b) return true;
|
|
@@ -93,13 +107,14 @@ const MultiSelect = React.forwardRef(
|
|
|
93
107
|
setTimeout(() => calculateMaxCount(), 10);
|
|
94
108
|
return;
|
|
95
109
|
}
|
|
96
|
-
const
|
|
97
|
-
const
|
|
98
|
-
const
|
|
99
|
-
const
|
|
100
|
-
const AVG_CHAR_WIDTH =
|
|
101
|
-
const
|
|
102
|
-
const
|
|
110
|
+
const CONTAINER_PADDING = 16;
|
|
111
|
+
const TAG_GAP = 2;
|
|
112
|
+
const COUNTER_TAG_WIDTH = 60;
|
|
113
|
+
const ICONS_WIDTH = 50;
|
|
114
|
+
const AVG_CHAR_WIDTH = 7;
|
|
115
|
+
const MAX_TAG_WIDTH = 250;
|
|
116
|
+
const TAG_BASE_WIDTH = 24;
|
|
117
|
+
const availableWidth = buttonWidth - CONTAINER_PADDING - ICONS_WIDTH;
|
|
103
118
|
if (availableWidth <= 0) {
|
|
104
119
|
setDynamicMaxCount(1);
|
|
105
120
|
return;
|
|
@@ -116,28 +131,33 @@ const MultiSelect = React.forwardRef(
|
|
|
116
131
|
};
|
|
117
132
|
const estimatedWidths = [];
|
|
118
133
|
for (let i = 0; i < selectedValues.length; i++) {
|
|
119
|
-
const
|
|
134
|
+
const option = options.find((option2) => option2.value === selectedValues[i]);
|
|
135
|
+
const label = getTreeLabel(selectedValues[i]) || option?.label || selectedValues[i];
|
|
136
|
+
const prefixWidth = option?.prefix ? 24 : 0;
|
|
137
|
+
const textWidth = label.length * AVG_CHAR_WIDTH;
|
|
138
|
+
const closeButtonWidth = 16;
|
|
120
139
|
const estimatedWidth = Math.min(
|
|
121
|
-
|
|
122
|
-
|
|
140
|
+
TAG_BASE_WIDTH + textWidth + prefixWidth + closeButtonWidth,
|
|
141
|
+
MAX_TAG_WIDTH
|
|
123
142
|
);
|
|
124
143
|
estimatedWidths.push(estimatedWidth);
|
|
125
144
|
}
|
|
126
|
-
let
|
|
145
|
+
let totalWidthWithoutCounter = 0;
|
|
127
146
|
for (let i = 0; i < estimatedWidths.length; i++) {
|
|
128
|
-
|
|
147
|
+
totalWidthWithoutCounter += estimatedWidths[i];
|
|
148
|
+
if (i > 0) totalWidthWithoutCounter += TAG_GAP;
|
|
129
149
|
}
|
|
130
|
-
if (
|
|
150
|
+
if (totalWidthWithoutCounter <= availableWidth) {
|
|
131
151
|
setDynamicMaxCount(selectedValues.length);
|
|
132
152
|
return;
|
|
133
153
|
}
|
|
134
|
-
const
|
|
154
|
+
const availableForTagsWithCounter = availableWidth - COUNTER_TAG_WIDTH - TAG_GAP;
|
|
135
155
|
let count = 0;
|
|
136
|
-
|
|
156
|
+
let accumulatedWidth = 0;
|
|
137
157
|
for (let i = 0; i < estimatedWidths.length; i++) {
|
|
138
|
-
const
|
|
139
|
-
if (
|
|
140
|
-
|
|
158
|
+
const nextTagWidth = estimatedWidths[i] + (i > 0 ? TAG_GAP : 0);
|
|
159
|
+
if (accumulatedWidth + nextTagWidth <= availableForTagsWithCounter) {
|
|
160
|
+
accumulatedWidth += nextTagWidth;
|
|
141
161
|
count++;
|
|
142
162
|
} else {
|
|
143
163
|
break;
|
|
@@ -529,10 +549,10 @@ const MultiSelect = React.forwardRef(
|
|
|
529
549
|
onClick: handleTogglePopover,
|
|
530
550
|
className: cn(
|
|
531
551
|
`flex w-full p-1 rounded-sm h-auto items-center justify-between bg-background
|
|
532
|
-
border
|
|
533
|
-
hover:border-grey-500 focus:border-grey-400 focus:ring-grey-600 focus:ring-opacity-15 focus:ring-4
|
|
552
|
+
border focus:ring-opacity-15 focus:ring-4
|
|
534
553
|
transition-all duration-300 outline-none
|
|
535
554
|
[&_svg]:pointer-events-auto`,
|
|
555
|
+
STATUS_STYLES[status],
|
|
536
556
|
maxCount === void 0 && TRIGGER_HEIGHT_CLASSES[size],
|
|
537
557
|
disabled && "opacity-50 cursor-not-allowed pointer-events-none",
|
|
538
558
|
readOnly && !disabled && "opacity-50 hover:border-grey-400",
|
|
@@ -615,8 +635,10 @@ const MultiSelect = React.forwardRef(
|
|
|
615
635
|
/* @__PURE__ */ React.createElement(
|
|
616
636
|
PopoverContent,
|
|
617
637
|
{
|
|
638
|
+
ref: dynamicHeightRef,
|
|
639
|
+
style: dynamicHeightStyle,
|
|
618
640
|
className: cn(
|
|
619
|
-
"p-0
|
|
641
|
+
"p-0 flex flex-col",
|
|
620
642
|
matchTriggerWidth && "w-[var(--radix-popover-trigger-width)]",
|
|
621
643
|
classNameContent
|
|
622
644
|
),
|
|
@@ -640,115 +662,25 @@ const MultiSelect = React.forwardRef(
|
|
|
640
662
|
disabled: readOnly
|
|
641
663
|
}
|
|
642
664
|
),
|
|
643
|
-
/* @__PURE__ */ React.createElement(
|
|
644
|
-
|
|
645
|
-
{
|
|
646
|
-
className: cn(
|
|
647
|
-
"p-4 text-center text-grey-800",
|
|
648
|
-
getFontVariant(size)
|
|
649
|
-
)
|
|
650
|
-
},
|
|
651
|
-
t("multiSelect.empty")
|
|
652
|
-
), !query && effectiveOptions.length > 0 && /* @__PURE__ */ React.createElement(
|
|
653
|
-
CommandItem,
|
|
665
|
+
/* @__PURE__ */ React.createElement(
|
|
666
|
+
CommandList,
|
|
654
667
|
{
|
|
655
|
-
|
|
656
|
-
onSelect: readOnly ? void 0 : toggleAll,
|
|
657
|
-
className: cn(
|
|
658
|
-
"cursor-pointer",
|
|
659
|
-
readOnly && "cursor-default pointer-events-none hover:bg-transparent"
|
|
660
|
-
)
|
|
668
|
+
className: "[&::-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"
|
|
661
669
|
},
|
|
662
|
-
/* @__PURE__ */ React.createElement(
|
|
663
|
-
|
|
670
|
+
/* @__PURE__ */ React.createElement(CommandGroup, null, (effectiveOptions.length === 0 || query && filteredOptions.length === 0) && /* @__PURE__ */ React.createElement(
|
|
671
|
+
CommandEmpty,
|
|
664
672
|
{
|
|
665
673
|
className: cn(
|
|
666
|
-
"
|
|
667
|
-
|
|
674
|
+
"p-4 text-center text-grey-800",
|
|
675
|
+
getFontVariant(size)
|
|
668
676
|
)
|
|
669
677
|
},
|
|
670
|
-
|
|
671
|
-
|
|
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
|
-
)
|
|
683
|
-
),
|
|
684
|
-
/* @__PURE__ */ React.createElement(
|
|
685
|
-
Typography,
|
|
686
|
-
{
|
|
687
|
-
variant: getFontVariant(size),
|
|
688
|
-
className: "text-grey-800"
|
|
689
|
-
},
|
|
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 truncate 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
|
-
},
|
|
738
|
-
highlight(option.label, query)
|
|
739
|
-
))
|
|
740
|
-
);
|
|
741
|
-
}));
|
|
742
|
-
}
|
|
743
|
-
) : filteredOptions.map((option) => {
|
|
744
|
-
const isSelected = selectedValues.includes(
|
|
745
|
-
option.value
|
|
746
|
-
);
|
|
747
|
-
return /* @__PURE__ */ React.createElement(
|
|
678
|
+
t("multiSelect.empty")
|
|
679
|
+
), !query && effectiveOptions.length > 0 && /* @__PURE__ */ React.createElement(
|
|
748
680
|
CommandItem,
|
|
749
681
|
{
|
|
750
|
-
key:
|
|
751
|
-
onSelect: readOnly ? void 0 :
|
|
682
|
+
key: "all",
|
|
683
|
+
onSelect: readOnly ? void 0 : toggleAll,
|
|
752
684
|
className: cn(
|
|
753
685
|
"cursor-pointer",
|
|
754
686
|
readOnly && "cursor-default pointer-events-none hover:bg-transparent"
|
|
@@ -758,30 +690,126 @@ const MultiSelect = React.forwardRef(
|
|
|
758
690
|
"div",
|
|
759
691
|
{
|
|
760
692
|
className: cn(
|
|
761
|
-
"flex h-4 w-4 items-center justify-center rounded-sm border border-grey-800
|
|
762
|
-
|
|
693
|
+
"flex h-4 w-4 items-center justify-center rounded-sm border border-grey-800",
|
|
694
|
+
selectedValues.length > 0 ? "bg-blue-600 border-blue-600 text-primary-foreground" : "opacity-50 [&_svg]:invisible"
|
|
763
695
|
)
|
|
764
696
|
},
|
|
765
|
-
/* @__PURE__ */ React.createElement(
|
|
697
|
+
selectedValues.length === effectiveOptions.length ? /* @__PURE__ */ React.createElement(
|
|
766
698
|
Check,
|
|
767
699
|
{
|
|
768
700
|
className: "!h-3 !w-3 !text-white",
|
|
769
701
|
strokeWidth: 3
|
|
770
702
|
}
|
|
703
|
+
) : /* @__PURE__ */ React.createElement(
|
|
704
|
+
Minus,
|
|
705
|
+
{
|
|
706
|
+
className: "!h-3 !w-3 !text-white",
|
|
707
|
+
strokeWidth: 3
|
|
708
|
+
}
|
|
771
709
|
)
|
|
772
710
|
),
|
|
773
|
-
/* @__PURE__ */ React.createElement(
|
|
711
|
+
/* @__PURE__ */ React.createElement(
|
|
774
712
|
Typography,
|
|
775
713
|
{
|
|
776
714
|
variant: getFontVariant(size),
|
|
777
|
-
className: "text-grey-800
|
|
715
|
+
className: "text-grey-800"
|
|
778
716
|
},
|
|
779
|
-
|
|
780
|
-
)
|
|
781
|
-
)
|
|
782
|
-
|
|
717
|
+
selectAllLabel ?? t("multiSelect.selectAll")
|
|
718
|
+
)
|
|
719
|
+
), isGrouped ? Object.entries(groupedOptions).map(
|
|
720
|
+
([categoryName, categoryOptions]) => {
|
|
721
|
+
const filtered = categoryOptions.filter(
|
|
722
|
+
(opt) => !query || effectiveOptions.some(
|
|
723
|
+
(eff) => eff.value === opt.value && filteredOptions.some(
|
|
724
|
+
(filt) => filt.value === opt.value
|
|
725
|
+
)
|
|
726
|
+
)
|
|
727
|
+
);
|
|
728
|
+
if (!filtered.length) return null;
|
|
729
|
+
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) => {
|
|
730
|
+
const isSelected = selectedValues.includes(
|
|
731
|
+
option.value
|
|
732
|
+
);
|
|
733
|
+
return /* @__PURE__ */ React.createElement(
|
|
734
|
+
CommandItem,
|
|
735
|
+
{
|
|
736
|
+
key: option.value,
|
|
737
|
+
onSelect: readOnly ? void 0 : () => toggleOption(option.value),
|
|
738
|
+
className: cn(
|
|
739
|
+
"cursor-pointer",
|
|
740
|
+
readOnly && "cursor-default pointer-events-none hover:bg-transparent"
|
|
741
|
+
)
|
|
742
|
+
},
|
|
743
|
+
/* @__PURE__ */ React.createElement(
|
|
744
|
+
"div",
|
|
745
|
+
{
|
|
746
|
+
className: cn(
|
|
747
|
+
"flex h-4 w-4 items-center justify-center rounded-sm border-2 border-grey-400 flex-shrink-0",
|
|
748
|
+
isSelected ? "bg-blue-600 border-blue-600 text-primary-foreground" : "opacity-50 [&_svg]:invisible"
|
|
749
|
+
)
|
|
750
|
+
},
|
|
751
|
+
/* @__PURE__ */ React.createElement(
|
|
752
|
+
Check,
|
|
753
|
+
{
|
|
754
|
+
className: "!h-3 !w-3 !text-white",
|
|
755
|
+
strokeWidth: 3
|
|
756
|
+
}
|
|
757
|
+
)
|
|
758
|
+
),
|
|
759
|
+
/* @__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(
|
|
760
|
+
Typography,
|
|
761
|
+
{
|
|
762
|
+
variant: getFontVariant(size),
|
|
763
|
+
className: "text-grey-800 break-words"
|
|
764
|
+
},
|
|
765
|
+
highlight(option.label, query)
|
|
766
|
+
))
|
|
767
|
+
);
|
|
768
|
+
}));
|
|
769
|
+
}
|
|
770
|
+
) : filteredOptions.map((option) => {
|
|
771
|
+
const isSelected = selectedValues.includes(
|
|
772
|
+
option.value
|
|
773
|
+
);
|
|
774
|
+
return /* @__PURE__ */ React.createElement(
|
|
775
|
+
CommandItem,
|
|
776
|
+
{
|
|
777
|
+
key: option.value,
|
|
778
|
+
onSelect: readOnly ? void 0 : () => toggleOption(option.value),
|
|
779
|
+
className: cn(
|
|
780
|
+
"cursor-pointer",
|
|
781
|
+
readOnly && "cursor-default pointer-events-none hover:bg-transparent"
|
|
782
|
+
)
|
|
783
|
+
},
|
|
784
|
+
/* @__PURE__ */ React.createElement(
|
|
785
|
+
"div",
|
|
786
|
+
{
|
|
787
|
+
className: cn(
|
|
788
|
+
"flex h-4 w-4 items-center justify-center rounded-sm border border-grey-800 flex-shrink-0",
|
|
789
|
+
isSelected ? "bg-blue-600 border-blue-600 text-primary-foreground" : "opacity-50 [&_svg]:invisible"
|
|
790
|
+
)
|
|
791
|
+
},
|
|
792
|
+
/* @__PURE__ */ React.createElement(
|
|
793
|
+
Check,
|
|
794
|
+
{
|
|
795
|
+
className: "!h-3 !w-3 !text-white",
|
|
796
|
+
strokeWidth: 3
|
|
797
|
+
}
|
|
798
|
+
)
|
|
799
|
+
),
|
|
800
|
+
/* @__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(
|
|
801
|
+
Typography,
|
|
802
|
+
{
|
|
803
|
+
variant: getFontVariant(size),
|
|
804
|
+
className: "text-grey-800 break-words"
|
|
805
|
+
},
|
|
806
|
+
highlight(option.label, query)
|
|
807
|
+
))
|
|
808
|
+
);
|
|
809
|
+
}))
|
|
810
|
+
)
|
|
783
811
|
),
|
|
784
|
-
isTree && /* @__PURE__ */ React.createElement("div", { className: "min-w-[260px]
|
|
812
|
+
isTree && /* @__PURE__ */ React.createElement("div", { className: "min-w-[260px] 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(
|
|
785
813
|
"svg",
|
|
786
814
|
{
|
|
787
815
|
className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground",
|
|
@@ -812,65 +840,72 @@ const MultiSelect = React.forwardRef(
|
|
|
812
840
|
SEARCH_INPUT_HEIGHT_CLASSES[size]
|
|
813
841
|
)
|
|
814
842
|
}
|
|
815
|
-
))), /* @__PURE__ */ React.createElement(
|
|
843
|
+
))), /* @__PURE__ */ React.createElement(
|
|
816
844
|
"div",
|
|
817
845
|
{
|
|
818
|
-
className:
|
|
819
|
-
"flex items-center gap-2 px-2 py-1 cursor-pointer rounded-sm hover:bg-accent",
|
|
820
|
-
readOnly && "cursor-default hover:bg-transparent pointer-events-none"
|
|
821
|
-
),
|
|
822
|
-
onClick: readOnly ? void 0 : toggleAll
|
|
846
|
+
className: "px-2 pb-1 flex-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"
|
|
823
847
|
},
|
|
824
|
-
/* @__PURE__ */ React.createElement(
|
|
848
|
+
!treeQuery && treeOptions && treeOptions.length > 0 && /* @__PURE__ */ React.createElement(
|
|
825
849
|
"div",
|
|
826
850
|
{
|
|
827
851
|
className: cn(
|
|
828
|
-
"flex
|
|
829
|
-
|
|
830
|
-
)
|
|
852
|
+
"flex items-center gap-2 px-2 py-1 cursor-pointer rounded-sm hover:bg-accent",
|
|
853
|
+
readOnly && "cursor-default hover:bg-transparent pointer-events-none"
|
|
854
|
+
),
|
|
855
|
+
onClick: readOnly ? void 0 : toggleAll
|
|
831
856
|
},
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
let acc = 0;
|
|
835
|
-
for (const n of nodes) {
|
|
836
|
-
const hasChildren = !!(n.children && n.children.length);
|
|
837
|
-
if (!hasChildren) acc += 1;
|
|
838
|
-
else
|
|
839
|
-
acc += treeSelectionStrategy === "all" ? 1 + countAll(n.children) : countAll(n.children);
|
|
840
|
-
}
|
|
841
|
-
return acc;
|
|
842
|
-
}(treeOptions) ? /* @__PURE__ */ React.createElement(
|
|
843
|
-
Check,
|
|
857
|
+
/* @__PURE__ */ React.createElement(
|
|
858
|
+
"div",
|
|
844
859
|
{
|
|
845
|
-
className:
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
860
|
+
className: cn(
|
|
861
|
+
"flex h-4 w-4 items-center justify-center rounded-sm border border-grey-800",
|
|
862
|
+
selectedValues.length > 0 ? "bg-blue-600 border-blue-600 text-primary-foreground" : "opacity-50 [&_svg]:invisible"
|
|
863
|
+
)
|
|
864
|
+
},
|
|
865
|
+
treeOptions && selectedValues.length === function countAll(nodes) {
|
|
866
|
+
if (!nodes) return 0;
|
|
867
|
+
let acc = 0;
|
|
868
|
+
for (const n of nodes) {
|
|
869
|
+
const hasChildren = !!(n.children && n.children.length);
|
|
870
|
+
if (!hasChildren) acc += 1;
|
|
871
|
+
else
|
|
872
|
+
acc += treeSelectionStrategy === "all" ? 1 + countAll(n.children) : countAll(n.children);
|
|
873
|
+
}
|
|
874
|
+
return acc;
|
|
875
|
+
}(treeOptions) ? /* @__PURE__ */ React.createElement(
|
|
876
|
+
Check,
|
|
877
|
+
{
|
|
878
|
+
className: "!h-3 !w-3 !text-white",
|
|
879
|
+
strokeWidth: 3
|
|
880
|
+
}
|
|
881
|
+
) : /* @__PURE__ */ React.createElement(
|
|
882
|
+
Minus,
|
|
883
|
+
{
|
|
884
|
+
className: "!h-3 !w-3 !text-white",
|
|
885
|
+
strokeWidth: 3
|
|
886
|
+
}
|
|
887
|
+
)
|
|
888
|
+
),
|
|
889
|
+
/* @__PURE__ */ React.createElement(
|
|
890
|
+
Typography,
|
|
850
891
|
{
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
}
|
|
892
|
+
variant: getFontVariant(size),
|
|
893
|
+
className: "text-grey-800"
|
|
894
|
+
},
|
|
895
|
+
selectAllLabel ?? t("multiSelect.selectAll")
|
|
854
896
|
)
|
|
855
897
|
),
|
|
856
|
-
/* @__PURE__ */ React.createElement(
|
|
857
|
-
|
|
898
|
+
!treeOptions || treeOptions.length === 0 || treeQuery && displayedTree.length === 0 ? /* @__PURE__ */ React.createElement(
|
|
899
|
+
"div",
|
|
858
900
|
{
|
|
859
|
-
|
|
860
|
-
|
|
901
|
+
className: cn(
|
|
902
|
+
"p-4 text-center text-grey-800",
|
|
903
|
+
getFontVariant(size)
|
|
904
|
+
)
|
|
861
905
|
},
|
|
862
|
-
|
|
863
|
-
)
|
|
864
|
-
)
|
|
865
|
-
"div",
|
|
866
|
-
{
|
|
867
|
-
className: cn(
|
|
868
|
-
"p-4 text-center text-grey-800",
|
|
869
|
-
getFontVariant(size)
|
|
870
|
-
)
|
|
871
|
-
},
|
|
872
|
-
t("multiSelect.empty")
|
|
873
|
-
) : renderTree(displayedTree)))
|
|
906
|
+
t("multiSelect.empty")
|
|
907
|
+
) : renderTree(displayedTree)
|
|
908
|
+
))
|
|
874
909
|
)
|
|
875
910
|
);
|
|
876
911
|
}
|
|
@@ -3,9 +3,8 @@ import { cn } from '../../lib/utils.js';
|
|
|
3
3
|
import { cva } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
const textareaVariants = cva(
|
|
6
|
-
`flex h-20 w-full rounded-sm border
|
|
6
|
+
`flex h-20 w-full rounded-sm border bg-background px-3 py-2 text-grey-800
|
|
7
7
|
placeholder:text-grey-500 outline-none
|
|
8
|
-
hover:border-grey-500 focus:bg-background focus:border-grey-400 focus:ring-grey-600 focus:ring-opacity-15 focus:ring-4
|
|
9
8
|
disabled:cursor-not-allowed disabled:opacity-50
|
|
10
9
|
transition-[border-color,box-shadow,background-color] duration-300`,
|
|
11
10
|
{
|
|
@@ -32,22 +31,27 @@ const textareaVariants = cva(
|
|
|
32
31
|
horizontal: "resize-x",
|
|
33
32
|
vertical: "resize-y",
|
|
34
33
|
"vertical-limited": "resize-y min-h-[40px] max-h-[480px]"
|
|
34
|
+
},
|
|
35
|
+
status: {
|
|
36
|
+
default: "border-grey-400 hover:border-grey-500 focus:bg-background focus:border-grey-400 focus:ring-grey-600 focus:ring-opacity-15 focus:ring-4",
|
|
37
|
+
error: "border-red-600 hover:border-red-600 focus:border-red-600 focus:ring-0"
|
|
35
38
|
}
|
|
36
39
|
},
|
|
37
40
|
defaultVariants: {
|
|
38
41
|
variant: "default",
|
|
39
42
|
size: "default",
|
|
40
43
|
radius: "default",
|
|
41
|
-
resize: "default"
|
|
44
|
+
resize: "default",
|
|
45
|
+
status: "default"
|
|
42
46
|
}
|
|
43
47
|
}
|
|
44
48
|
);
|
|
45
49
|
const Textarea = React.forwardRef(
|
|
46
|
-
({ className, variant, size, radius, resize, ...props }, ref) => /* @__PURE__ */ React.createElement(
|
|
50
|
+
({ className, variant, size, radius, resize, status, ...props }, ref) => /* @__PURE__ */ React.createElement(
|
|
47
51
|
"textarea",
|
|
48
52
|
{
|
|
49
53
|
className: cn(
|
|
50
|
-
textareaVariants({ variant, size, radius, resize, className })
|
|
54
|
+
textareaVariants({ variant, size, radius, resize, status, className })
|
|
51
55
|
),
|
|
52
56
|
ref,
|
|
53
57
|
...props
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_BOTTOM_PADDING = 50;
|
|
4
|
+
const DEFAULT_MIN_HEIGHT = 120;
|
|
5
|
+
function useDynamicMaxHeight(options = {}) {
|
|
6
|
+
const {
|
|
7
|
+
enabled = false,
|
|
8
|
+
bottomPadding = DEFAULT_BOTTOM_PADDING,
|
|
9
|
+
minHeight = DEFAULT_MIN_HEIGHT
|
|
10
|
+
} = options;
|
|
11
|
+
const ref = React.useRef(null);
|
|
12
|
+
const [maxHeight, setMaxHeight] = React.useState(
|
|
13
|
+
void 0
|
|
14
|
+
);
|
|
15
|
+
const lastCalculatedHeight = React.useRef(void 0);
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
if (!enabled) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const calculateHeight = () => {
|
|
21
|
+
if (!ref.current) return;
|
|
22
|
+
const rect = ref.current.getBoundingClientRect();
|
|
23
|
+
const viewportHeight = window.innerHeight;
|
|
24
|
+
const elementTop = rect.top;
|
|
25
|
+
const availableHeight = viewportHeight - elementTop - bottomPadding;
|
|
26
|
+
const finalHeight = Math.max(availableHeight, minHeight);
|
|
27
|
+
lastCalculatedHeight.current = finalHeight;
|
|
28
|
+
setMaxHeight(finalHeight);
|
|
29
|
+
};
|
|
30
|
+
requestAnimationFrame(() => {
|
|
31
|
+
requestAnimationFrame(() => {
|
|
32
|
+
calculateHeight();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
window.addEventListener("resize", calculateHeight);
|
|
36
|
+
window.addEventListener("scroll", calculateHeight, true);
|
|
37
|
+
return () => {
|
|
38
|
+
window.removeEventListener("resize", calculateHeight);
|
|
39
|
+
window.removeEventListener("scroll", calculateHeight, true);
|
|
40
|
+
};
|
|
41
|
+
}, [enabled, bottomPadding, minHeight]);
|
|
42
|
+
const style = React.useMemo(() => {
|
|
43
|
+
if (maxHeight === void 0) return {};
|
|
44
|
+
return { maxHeight: `${maxHeight}px` };
|
|
45
|
+
}, [maxHeight]);
|
|
46
|
+
return { ref, maxHeight, style };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { useDynamicMaxHeight };
|