@trsys-tech/matrix-library 0.5.2-alpha.2 → 0.5.2-beta.2
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/form-multi-select/FormMultiSelect.d.ts +2 -2
- package/dist/components/form-multi-select/FormMultiSelect.d.ts.map +1 -1
- package/dist/components/multi-select/MultiSelect.d.ts +15 -0
- package/dist/components/multi-select/MultiSelect.d.ts.map +1 -1
- package/dist/formmultiselect.es.js.map +1 -1
- package/dist/multiselect.es.js +133 -114
- package/dist/multiselect.es.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ControllerProps, FieldPath, FieldValues } from 'react-hook-form';
|
|
2
2
|
import { FormItem } from '../form/Form';
|
|
3
|
-
import { MultiSelect
|
|
3
|
+
import { MultiSelect } from '../multi-select/MultiSelect';
|
|
4
4
|
type FormMultiSelectProps<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = Omit<ControllerProps<TFieldValues, TName>, "render"> & React.ComponentProps<typeof FormItem> & {
|
|
5
5
|
label: string;
|
|
6
6
|
loading?: boolean;
|
|
7
7
|
loadingText?: string;
|
|
8
|
-
options:
|
|
8
|
+
options: React.ComponentPropsWithoutRef<typeof MultiSelect>["options"];
|
|
9
9
|
placeholder?: string;
|
|
10
10
|
required?: boolean;
|
|
11
11
|
readOnly?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormMultiSelect.d.ts","sourceRoot":"","sources":["../../../src/components/form-multi-select/FormMultiSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE1E,OAAO,EAA0B,QAAQ,EAA0B,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"FormMultiSelect.d.ts","sourceRoot":"","sources":["../../../src/components/form-multi-select/FormMultiSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE1E,OAAO,EAA0B,QAAQ,EAA0B,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE1D,KAAK,oBAAoB,CAAC,YAAY,SAAS,WAAW,EAAE,KAAK,SAAS,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,IAAI,IAAI,CACjI,eAAe,CAAC,YAAY,EAAE,KAAK,CAAC,EACpC,QAAQ,CACT,GACC,KAAK,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,GAAG;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,KAAK,CAAC,wBAAwB,CAAC,OAAO,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC;IACvE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE;QACV,gBAAgB,CAAC,EAAE,IAAI,CACrB,KAAK,CAAC,cAAc,CAAC,OAAO,WAAW,CAAC,EACxC,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,GAAG,UAAU,CAC/F,CAAC;QACF,cAAc,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;QAChG,gBAAgB,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,oBAAoB,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC;KAC3G,CAAC;CACH,CAAC;AAEJ,QAAA,MAAM,eAAe,GAAI,YAAY,SAAS,WAAW,EAAE,KAAK,SAAS,SAAS,CAAC,YAAY,CAAC,mCACvF,oBAAoB,CAAC,YAAY,EAAE,KAAK,CAAC,4CAwDjD,CAAC;AACF,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,CAAC"}
|
|
@@ -62,6 +62,8 @@ interface MultiSelectProps<T extends string | number> extends Omit<React.ButtonH
|
|
|
62
62
|
/**
|
|
63
63
|
* An array of option objects to be displayed in the multi-select component.
|
|
64
64
|
* Each option object has a label, value, and an optional icon.
|
|
65
|
+
*
|
|
66
|
+
* *Important: Use a constant Array*
|
|
65
67
|
*/
|
|
66
68
|
options: {
|
|
67
69
|
/** The text to display for the option. */
|
|
@@ -114,10 +116,23 @@ interface MultiSelectProps<T extends string | number> extends Omit<React.ButtonH
|
|
|
114
116
|
* Text to display on the close button when the multi-select component is open.
|
|
115
117
|
*/
|
|
116
118
|
closeText?: string;
|
|
119
|
+
/**
|
|
120
|
+
* Whether to show the select all option or not
|
|
121
|
+
*/
|
|
122
|
+
showSelectAll?: boolean;
|
|
117
123
|
/**
|
|
118
124
|
* Text to display on the select all button when the multi-select component is open.
|
|
119
125
|
*/
|
|
120
126
|
selectAllText?: string;
|
|
127
|
+
/**
|
|
128
|
+
* Text to display in the search input.
|
|
129
|
+
*/
|
|
130
|
+
searchText?: string;
|
|
131
|
+
/**
|
|
132
|
+
* If true, a new option will be added when the user submits a search query if it doesn't already exist.
|
|
133
|
+
* Optional, defaults to false.
|
|
134
|
+
*/
|
|
135
|
+
addOptionOnSearchNotFound?: boolean;
|
|
121
136
|
/**
|
|
122
137
|
* Text to display on the clear button when the multi-select component is open.
|
|
123
138
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiSelect.d.ts","sourceRoot":"","sources":["../../../src/components/multi-select/MultiSelect.tsx"],"names":[],"mappings":";AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAU1D;;;GAGG;AACH,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCAavB,CAAC;AAEH;;GAEG;AACH,UAAU,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAClD,SAAQ,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,OAAO,GAAG,cAAc,CAAC,EACnF,YAAY,CAAC,OAAO,mBAAmB,CAAC;IAC1C
|
|
1
|
+
{"version":3,"file":"MultiSelect.d.ts","sourceRoot":"","sources":["../../../src/components/multi-select/MultiSelect.tsx"],"names":[],"mappings":";AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAU1D;;;GAGG;AACH,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCAavB,CAAC;AAEH;;GAEG;AACH,UAAU,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAClD,SAAQ,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,OAAO,GAAG,cAAc,CAAC,EACnF,YAAY,CAAC,OAAO,mBAAmB,CAAC;IAC1C;;;;;OAKG;IACH,OAAO,EAAE;QACP,0CAA0C;QAC1C,KAAK,EAAE,MAAM,CAAC;QACd,mDAAmD;QACnD,KAAK,EAAE,CAAC,CAAC;QACT,+DAA+D;QAC/D,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;YAAE,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACpD,EAAE,CAAC;IAEJ;;;OAGG;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC;IAEpC;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;IAEZ,6DAA6D;IAC7D,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC;IAEnB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IAEpC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAqQD,QAAA,MAAM,oBAAoB,EAAoC,CAAC,CAAC,CAAyB,SAAf,MAAM,GAAG,MAAM,EACvF,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;CAAE,KAChE,KAAK,CAAC,YAAY,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAIpD,OAAO,EAAE,oBAAoB,IAAI,WAAW,EAAE,KAAK,gBAAgB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formmultiselect.es.js","sources":["../src/components/form-multi-select/FormMultiSelect.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { ControllerProps, FieldPath, FieldValues } from \"react-hook-form\";\r\n\r\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage } from \"../form/Form\";\r\nimport { MultiSelect
|
|
1
|
+
{"version":3,"file":"formmultiselect.es.js","sources":["../src/components/form-multi-select/FormMultiSelect.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { ControllerProps, FieldPath, FieldValues } from \"react-hook-form\";\r\n\r\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage } from \"../form/Form\";\r\nimport { MultiSelect } from \"../multi-select/MultiSelect\";\r\n\r\ntype FormMultiSelectProps<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = Omit<\r\n ControllerProps<TFieldValues, TName>,\r\n \"render\"\r\n> &\r\n React.ComponentProps<typeof FormItem> & {\r\n label: string;\r\n loading?: boolean;\r\n loadingText?: string;\r\n options: React.ComponentPropsWithoutRef<typeof MultiSelect>[\"options\"];\r\n placeholder?: string;\r\n required?: boolean;\r\n readOnly?: boolean;\r\n slotProps?: {\r\n multiSelectProps?: Omit<\r\n React.ComponentProps<typeof MultiSelect>,\r\n \"onValueChange\" | \"value\" | \"options\" | \"loading\" | \"loadingText\" | \"placeholder\" | \"disabled\"\r\n >;\r\n formLabelProps?: React.HTMLAttributes<HTMLLabelElement> & React.RefAttributes<HTMLLabelElement>;\r\n formMessageProps?: React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>;\r\n };\r\n };\r\n\r\nconst FormMultiSelect = <TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>(\r\n props: FormMultiSelectProps<TFieldValues, TName>,\r\n) => {\r\n const {\r\n name,\r\n control,\r\n defaultValue,\r\n disabled,\r\n readOnly,\r\n rules,\r\n shouldUnregister,\r\n label,\r\n options,\r\n loading,\r\n loadingText,\r\n placeholder,\r\n slotProps,\r\n required,\r\n ...formItemProps\r\n } = props;\r\n\r\n return (\r\n <FormField\r\n control={control}\r\n name={name}\r\n defaultValue={defaultValue}\r\n disabled={disabled}\r\n rules={rules}\r\n shouldUnregister={shouldUnregister}\r\n render={({ field }) => {\r\n return (\r\n <FormItem {...formItemProps}>\r\n <FormLabel {...(slotProps?.formLabelProps ?? {})}>\r\n {label}\r\n {required && <span className=\"text-danger text-sm leading-4\">*</span>}\r\n </FormLabel>\r\n <FormControl>\r\n <MultiSelect\r\n aria-required={required}\r\n options={options}\r\n onValueChange={field.onChange}\r\n onBlur={field.onBlur}\r\n placeholder={placeholder}\r\n value={field.value}\r\n loading={loading}\r\n loadingText={loadingText}\r\n disabled={disabled || readOnly}\r\n {...(slotProps?.multiSelectProps ?? {})}\r\n />\r\n </FormControl>\r\n\r\n <FormMessage {...(slotProps?.formMessageProps ?? {})} />\r\n </FormItem>\r\n );\r\n }}\r\n />\r\n );\r\n};\r\nexport { FormMultiSelect, type FormMultiSelectProps };\r\n"],"names":["FormMultiSelect","props","name","control","defaultValue","disabled","readOnly","rules","shouldUnregister","label","options","loading","loadingText","placeholder","slotProps","required","formItemProps","jsx","FormField","field","jsxs","FormItem","FormLabel","FormControl","MultiSelect","FormMessage"],"mappings":";;;AA6BA,MAAMA,IAAkB,CACtBC,MACG;AACH,QAAM;AAAA,IACJ,MAAAC;AAAA,IACA,SAAAC;AAAA,IACA,cAAAC;AAAA,IACA,UAAAC;AAAA,IACA,UAAAC;AAAA,IACA,OAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,OAAAC;AAAA,IACA,SAAAC;AAAA,IACA,SAAAC;AAAA,IACA,aAAAC;AAAA,IACA,aAAAC;AAAA,IACA,WAAAC;AAAA,IACA,UAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,IACDf;AAEJ,SACE,gBAAAgB;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,SAAAf;AAAA,MACA,MAAAD;AAAA,MACA,cAAAE;AAAA,MACA,UAAAC;AAAA,MACA,OAAAE;AAAA,MACA,kBAAAC;AAAA,MACA,QAAQ,CAAC,EAAE,OAAAW,QAEP,gBAAAC,EAACC,GAAA,EAAU,GAAGL,GACZ,UAAA;AAAA,QAAA,gBAAAI,EAACE,GAAA,EAAW,GAAIR,GAAW,kBAAkB,CAAA,GAC1C,UAAA;AAAA,UAAAL;AAAA,UACAM,KAAY,gBAAAE,EAAC,QAAA,EAAK,WAAU,iCAAgC,UAAA,IAAA,CAAC;AAAA,QAAA,GAChE;AAAA,0BACCM,GAAA,EACC,UAAA,gBAAAN;AAAA,UAACO;AAAAA,UAAA;AAAA,YACC,iBAAeT;AAAA,YACf,SAAAL;AAAA,YACA,eAAeS,EAAM;AAAA,YACrB,QAAQA,EAAM;AAAA,YACd,aAAAN;AAAA,YACA,OAAOM,EAAM;AAAA,YACb,SAAAR;AAAA,YACA,aAAAC;AAAA,YACA,UAAUP,KAAYC;AAAA,YACrB,GAAIQ,GAAW,oBAAoB,CAAA;AAAA,UAAC;AAAA,QAAA,GAEzC;AAAA,0BAECW,GAAA,EAAa,GAAIX,GAAW,oBAAoB,CAAA,EAAC,CAAI;AAAA,MAAA,GACxD;AAAA,IAEJ;AAAA,EAAA;AAGN;"}
|
package/dist/multiselect.es.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { jsxs as
|
|
1
|
+
import { jsxs as l, jsx as r, Fragment as S } from "react/jsx-runtime";
|
|
2
2
|
import * as s from "react";
|
|
3
|
-
import { tv as
|
|
4
|
-
import { XMark as
|
|
5
|
-
import { cn as
|
|
6
|
-
import { Badge as
|
|
7
|
-
import { Button as
|
|
8
|
-
import { Separator as
|
|
9
|
-
import { Popover as
|
|
10
|
-
import { Command as
|
|
11
|
-
const
|
|
3
|
+
import { tv as re } from "tailwind-variants";
|
|
4
|
+
import { XMark as M, CircleXmark as te, ChevronDown as ae, Check as I } from "@trsys-tech/matrix-icons";
|
|
5
|
+
import { cn as p } from "./utils.es.js";
|
|
6
|
+
import { Badge as D } from "./badge.es.js";
|
|
7
|
+
import { Button as se } from "./button.es.js";
|
|
8
|
+
import { Separator as T } from "./separator.es.js";
|
|
9
|
+
import { Popover as le, PopoverTrigger as oe, PopoverContent as ne } from "./popover.es.js";
|
|
10
|
+
import { Command as ce, CommandInput as ie, CommandList as de, CommandEmpty as ue, CommandGroup as A, CommandItem as y, CommandSeparator as me } from "./command.es.js";
|
|
11
|
+
const R = re({
|
|
12
12
|
base: "flex gap-1 items-center py-0.5 px-2 rounded-xl",
|
|
13
13
|
variants: {
|
|
14
14
|
variant: {
|
|
@@ -21,165 +21,184 @@ const M = H({
|
|
|
21
21
|
defaultVariants: {
|
|
22
22
|
variant: "default"
|
|
23
23
|
}
|
|
24
|
-
}),
|
|
25
|
-
options:
|
|
26
|
-
onValueChange:
|
|
27
|
-
value:
|
|
28
|
-
variant:
|
|
29
|
-
disabled:
|
|
30
|
-
defaultValue:
|
|
31
|
-
placeholder:
|
|
24
|
+
}), pe = ({
|
|
25
|
+
options: u,
|
|
26
|
+
onValueChange: o,
|
|
27
|
+
value: w,
|
|
28
|
+
variant: k,
|
|
29
|
+
disabled: C,
|
|
30
|
+
defaultValue: B = [],
|
|
31
|
+
placeholder: K = "Select options",
|
|
32
32
|
maxCount: m = 3,
|
|
33
|
-
modalPopover:
|
|
33
|
+
modalPopover: L = !1,
|
|
34
34
|
// asChild = false,
|
|
35
|
-
className:
|
|
36
|
-
moreText:
|
|
37
|
-
clearText:
|
|
38
|
-
closeText:
|
|
39
|
-
selectAllText:
|
|
40
|
-
noResultsText:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
35
|
+
className: z,
|
|
36
|
+
moreText: V = "more",
|
|
37
|
+
clearText: W = "Clear",
|
|
38
|
+
closeText: X = "Close",
|
|
39
|
+
selectAllText: $ = "Select All",
|
|
40
|
+
noResultsText: G = "No results found.",
|
|
41
|
+
searchText: O = "Search...",
|
|
42
|
+
addOptionOnSearchNotFound: f = !1,
|
|
43
|
+
showSelectAll: q = !0,
|
|
44
|
+
loading: h,
|
|
45
|
+
loadingText: b = "Loading...",
|
|
46
|
+
...H
|
|
47
|
+
}, J) => {
|
|
48
|
+
const [t, c] = s.useState(B ?? w), [Q, d] = s.useState(!1), g = s.useRef(null), [U, j] = s.useState(""), [Y, P] = s.useState(!1), [n, x] = s.useState(
|
|
49
|
+
new Map(u.map((e) => [e.value, e]))
|
|
50
|
+
), Z = s.useCallback(
|
|
51
|
+
(e) => {
|
|
52
|
+
if (e.key === "Enter" && f) {
|
|
53
|
+
if (d(!0), e.preventDefault(), e.stopPropagation(), !e.currentTarget.value) return;
|
|
54
|
+
const a = { value: e.currentTarget.value, label: e.currentTarget.value };
|
|
55
|
+
if (n.get(a.value) === void 0) {
|
|
56
|
+
x((N) => new Map(N).set(a.value, a));
|
|
57
|
+
const i = [...t, a.value];
|
|
58
|
+
c(i), o(i), j("");
|
|
59
|
+
}
|
|
60
|
+
} else if (e.key === "Enter")
|
|
61
|
+
d(!0);
|
|
62
|
+
else if (e.key === "Backspace" && !e.currentTarget.value) {
|
|
63
|
+
const a = [...t];
|
|
64
|
+
a.pop(), c(a), o(a);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
[f, o, n, t]
|
|
68
|
+
), E = s.useCallback(
|
|
69
|
+
(e) => {
|
|
70
|
+
const a = t.includes(e) ? t.filter((i) => i !== e) : [...t, e];
|
|
71
|
+
c(a), o(a);
|
|
72
|
+
},
|
|
73
|
+
[o, t]
|
|
74
|
+
), v = s.useCallback(() => {
|
|
75
|
+
c([]), o([]), f && x(new Map(u.map((e) => [e.value, e])));
|
|
76
|
+
}, [o, f, u]), F = s.useCallback(() => {
|
|
77
|
+
d((e) => !e);
|
|
78
|
+
}, []), _ = s.useCallback(() => {
|
|
64
79
|
const e = t.slice(0, m);
|
|
65
|
-
|
|
66
|
-
},
|
|
67
|
-
if (t.length === n.
|
|
68
|
-
|
|
80
|
+
c(e), o(e);
|
|
81
|
+
}, [m, t, o]), ee = s.useCallback(() => {
|
|
82
|
+
if (t.length === n.size)
|
|
83
|
+
v();
|
|
69
84
|
else {
|
|
70
|
-
const e = n.
|
|
71
|
-
|
|
85
|
+
const e = Array.from(n.keys());
|
|
86
|
+
c(e), o(e);
|
|
72
87
|
}
|
|
73
|
-
};
|
|
74
|
-
return s.
|
|
75
|
-
|
|
76
|
-
}, [
|
|
77
|
-
|
|
78
|
-
|
|
88
|
+
}, [v, o, n, t.length]);
|
|
89
|
+
return s.useEffect(() => {
|
|
90
|
+
x(new Map(u.map((e) => [e.value, e])));
|
|
91
|
+
}, [u]), s.useEffect(() => {
|
|
92
|
+
c(w ?? []);
|
|
93
|
+
}, [w]), s.useLayoutEffect(() => {
|
|
94
|
+
g.current && (g?.current?.firstChild?.offsetTop < g?.current?.lastChild?.offsetTop ? P(!0) : P(!1));
|
|
95
|
+
}, [t]), /* @__PURE__ */ l(le, { open: Q, onOpenChange: d, modal: L, children: [
|
|
96
|
+
/* @__PURE__ */ r(oe, { asChild: !0, children: /* @__PURE__ */ r(
|
|
97
|
+
se,
|
|
79
98
|
{
|
|
80
|
-
ref:
|
|
99
|
+
ref: J,
|
|
81
100
|
variant: "text",
|
|
82
|
-
loading:
|
|
83
|
-
disabled:
|
|
84
|
-
...
|
|
85
|
-
onClick:
|
|
86
|
-
className:
|
|
101
|
+
loading: h,
|
|
102
|
+
disabled: C,
|
|
103
|
+
...H,
|
|
104
|
+
onClick: F,
|
|
105
|
+
className: p(
|
|
87
106
|
"group flex max-h-14 h-8 w-full items-center justify-between whitespace-nowrap rounded-sm border border-input bg-transparent px-3 py-1.5 text-sm ring-offset-background data-[placeholder]:text-muted-foreground hover:border hover:border-primary hover:bg-transparent focus:border focus:border-primary focus:outline-none focus:ring focus:ring-primary-100 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:text-text-300 disabled:border-gray-100 [&>span]:line-clamp-1 [&_svg]:disabled:text-text-300",
|
|
88
|
-
|
|
89
|
-
|
|
107
|
+
Y && "h-auto",
|
|
108
|
+
z
|
|
90
109
|
),
|
|
91
110
|
"data-placeholder": t.length ? void 0 : "",
|
|
92
111
|
endIcon: /* @__PURE__ */ r(
|
|
93
|
-
|
|
112
|
+
ae,
|
|
94
113
|
{
|
|
95
114
|
role: "button",
|
|
96
115
|
"aria-label": "Expand dropdown",
|
|
97
116
|
className: "!h-4.5 !w-4.5 cursor-pointer group-data-[state=open]:rotate-180 transition-transform"
|
|
98
117
|
}
|
|
99
118
|
),
|
|
100
|
-
children: /* @__PURE__ */ r(
|
|
101
|
-
/* @__PURE__ */
|
|
119
|
+
children: /* @__PURE__ */ r(S, { children: t.length > 0 ? /* @__PURE__ */ l("div", { className: "flex justify-between items-center w-full", children: [
|
|
120
|
+
/* @__PURE__ */ l("div", { className: "flex flex-wrap items-center gap-2", ref: g, children: [
|
|
102
121
|
t.slice(0, m).map((e) => {
|
|
103
|
-
const
|
|
104
|
-
return /* @__PURE__ */
|
|
122
|
+
const a = n.get(e), i = a?.icon;
|
|
123
|
+
return /* @__PURE__ */ l(D, { className: p(R({ variant: k }), { "text-gray-400 bg-gray-200": C || h }), children: [
|
|
105
124
|
/* @__PURE__ */ r(
|
|
106
|
-
|
|
125
|
+
M,
|
|
107
126
|
{
|
|
108
127
|
className: "h-4 w-4 cursor-pointer",
|
|
109
|
-
onClick: (
|
|
110
|
-
|
|
128
|
+
onClick: (N) => {
|
|
129
|
+
N.stopPropagation(), E(e);
|
|
111
130
|
}
|
|
112
131
|
}
|
|
113
132
|
),
|
|
114
|
-
|
|
115
|
-
|
|
133
|
+
i && /* @__PURE__ */ r(i, { className: "h-4 w-4 mr-2" }),
|
|
134
|
+
a?.label
|
|
116
135
|
] }, e);
|
|
117
136
|
}),
|
|
118
|
-
t.length > m && /* @__PURE__ */
|
|
119
|
-
`+ ${t.length - m} ${
|
|
137
|
+
t.length > m && /* @__PURE__ */ l(D, { className: p(R({ variant: k })), children: [
|
|
138
|
+
`+ ${t.length - m} ${V}`,
|
|
120
139
|
/* @__PURE__ */ r(
|
|
121
|
-
|
|
140
|
+
te,
|
|
122
141
|
{
|
|
123
142
|
role: "button",
|
|
124
143
|
className: "ml-2 h-4.5 w-4.5 cursor-pointer",
|
|
125
144
|
onClick: (e) => {
|
|
126
|
-
e.stopPropagation(),
|
|
145
|
+
e.stopPropagation(), _();
|
|
127
146
|
}
|
|
128
147
|
}
|
|
129
148
|
)
|
|
130
149
|
] }),
|
|
131
|
-
|
|
150
|
+
h && b ? b : null
|
|
132
151
|
] }),
|
|
133
|
-
/* @__PURE__ */
|
|
152
|
+
/* @__PURE__ */ l("div", { className: "flex items-center justify-between gap-1", children: [
|
|
134
153
|
/* @__PURE__ */ r(
|
|
135
|
-
|
|
154
|
+
M,
|
|
136
155
|
{
|
|
137
156
|
role: "button",
|
|
138
157
|
className: "h-5 w-5 text-muted-foreground cursor-pointer",
|
|
139
158
|
onClick: (e) => {
|
|
140
|
-
e.stopPropagation(),
|
|
159
|
+
e.stopPropagation(), v();
|
|
141
160
|
},
|
|
142
161
|
"aria-label": "Clear"
|
|
143
162
|
}
|
|
144
163
|
),
|
|
145
|
-
/* @__PURE__ */ r(
|
|
164
|
+
/* @__PURE__ */ r(T, { orientation: "vertical", className: "flex min-h-5 h-full" })
|
|
146
165
|
] })
|
|
147
|
-
] }) : /* @__PURE__ */ r(
|
|
166
|
+
] }) : /* @__PURE__ */ r(S, { children: h && b ? b : K }) })
|
|
148
167
|
}
|
|
149
168
|
) }),
|
|
150
|
-
/* @__PURE__ */ r(
|
|
151
|
-
/* @__PURE__ */ r(
|
|
152
|
-
/* @__PURE__ */
|
|
153
|
-
/* @__PURE__ */ r(
|
|
154
|
-
/* @__PURE__ */
|
|
155
|
-
/* @__PURE__ */
|
|
169
|
+
/* @__PURE__ */ r(ne, { className: "w-auto p-0", align: "start", onEscapeKeyDown: () => d(!1), children: /* @__PURE__ */ l(ce, { className: "w-[--radix-popper-anchor-width] max-h-[--radix-popper-available-height]", children: [
|
|
170
|
+
/* @__PURE__ */ r(ie, { placeholder: O, onKeyDown: Z, value: U, onValueChange: j }),
|
|
171
|
+
/* @__PURE__ */ l(de, { className: "", children: [
|
|
172
|
+
/* @__PURE__ */ r(ue, { children: G }),
|
|
173
|
+
/* @__PURE__ */ l(A, { children: [
|
|
174
|
+
q && /* @__PURE__ */ l(y, { onSelect: ee, className: "cursor-pointer", children: [
|
|
156
175
|
/* @__PURE__ */ r(
|
|
157
176
|
"div",
|
|
158
177
|
{
|
|
159
|
-
className:
|
|
178
|
+
className: p(
|
|
160
179
|
"mr-2 flex h-4.5 w-4.5 items-center justify-center rounded-sm border border-primary",
|
|
161
|
-
t.length === n.
|
|
180
|
+
t.length === n.size ? "bg-primary text-primary-foreground" : "opacity-50 [&_svg]:invisible"
|
|
162
181
|
),
|
|
163
|
-
children: /* @__PURE__ */ r(
|
|
182
|
+
children: /* @__PURE__ */ r(I, { className: "h-4.5 w-4.5" })
|
|
164
183
|
}
|
|
165
184
|
),
|
|
166
|
-
/* @__PURE__ */
|
|
185
|
+
/* @__PURE__ */ l("span", { children: [
|
|
167
186
|
"(",
|
|
168
|
-
|
|
187
|
+
$,
|
|
169
188
|
")"
|
|
170
189
|
] })
|
|
171
190
|
] }, "all"),
|
|
172
|
-
n.map((e) => {
|
|
173
|
-
const
|
|
174
|
-
return /* @__PURE__ */
|
|
191
|
+
Array.from(n.values()).map((e) => {
|
|
192
|
+
const a = t.includes(e.value);
|
|
193
|
+
return /* @__PURE__ */ l(y, { onSelect: () => E(e.value), className: "cursor-pointer", children: [
|
|
175
194
|
/* @__PURE__ */ r(
|
|
176
195
|
"div",
|
|
177
196
|
{
|
|
178
|
-
className:
|
|
197
|
+
className: p(
|
|
179
198
|
"mr-2 flex h-4.5 w-4.5 items-center justify-center rounded-sm border border-primary",
|
|
180
|
-
|
|
199
|
+
a ? "bg-primary text-primary-foreground" : "opacity-50 [&_svg]:invisible"
|
|
181
200
|
),
|
|
182
|
-
children: /* @__PURE__ */ r(
|
|
201
|
+
children: /* @__PURE__ */ r(I, { className: "h-4.5 w-4.5" })
|
|
183
202
|
}
|
|
184
203
|
),
|
|
185
204
|
e.icon && /* @__PURE__ */ r(e.icon, { className: "mr-2 h-4.5 w-4.5 text-muted-foreground" }),
|
|
@@ -187,20 +206,20 @@ const M = H({
|
|
|
187
206
|
] }, e.value);
|
|
188
207
|
})
|
|
189
208
|
] }),
|
|
190
|
-
/* @__PURE__ */ r(
|
|
191
|
-
/* @__PURE__ */ r(
|
|
192
|
-
t.length > 0 && /* @__PURE__ */
|
|
193
|
-
/* @__PURE__ */ r(
|
|
194
|
-
/* @__PURE__ */ r(
|
|
209
|
+
/* @__PURE__ */ r(me, {}),
|
|
210
|
+
/* @__PURE__ */ r(A, { children: /* @__PURE__ */ l("div", { className: "flex items-center justify-between", children: [
|
|
211
|
+
t.length > 0 && /* @__PURE__ */ l(S, { children: [
|
|
212
|
+
/* @__PURE__ */ r(y, { onSelect: v, className: "flex-1 justify-center cursor-pointer", children: W }),
|
|
213
|
+
/* @__PURE__ */ r(T, { orientation: "vertical", className: "flex min-h-6 h-full" })
|
|
195
214
|
] }),
|
|
196
|
-
/* @__PURE__ */ r(
|
|
215
|
+
/* @__PURE__ */ r(y, { onSelect: () => d(!1), className: "flex-1 justify-center cursor-pointer max-w-full", children: X })
|
|
197
216
|
] }) })
|
|
198
217
|
] })
|
|
199
218
|
] }) })
|
|
200
219
|
] });
|
|
201
|
-
},
|
|
202
|
-
|
|
220
|
+
}, fe = s.forwardRef(pe);
|
|
221
|
+
fe.displayName = "MultiSelect";
|
|
203
222
|
export {
|
|
204
|
-
|
|
223
|
+
fe as MultiSelect
|
|
205
224
|
};
|
|
206
225
|
//# sourceMappingURL=multiselect.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multiselect.es.js","sources":["../src/components/multi-select/MultiSelect.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { tv, type VariantProps } from \"tailwind-variants\";\r\nimport { Check, ChevronDown, CircleXmark, XMark } from \"@trsys-tech/matrix-icons\";\r\n\r\nimport { cn } from \"../../lib/utils\";\r\nimport { Badge } from \"../badge/Badge\";\r\nimport { Button } from \"../button/Button\";\r\nimport { Separator } from \"../separator/Separator\";\r\nimport { Popover, PopoverContent, PopoverTrigger } from \"../popover/Popover\";\r\nimport { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from \"../command/Command\";\r\n\r\n/**\r\n * Variants for the multi-select component to handle different styles.\r\n * Uses tailwind-variants (cva) to define different styles based on \"variant\" prop.\r\n */\r\nconst multiSelectVariants = tv({\r\n base: \"flex gap-1 items-center py-0.5 px-2 rounded-xl\",\r\n variants: {\r\n variant: {\r\n default: \"border-none shadow-none bg-primary-50 text-primary hover:bg-primary-50\",\r\n secondary: \"border-foreground/10 bg-secondary text-secondary-foreground hover:bg-secondary/80\",\r\n destructive: \"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80\",\r\n inverted: \"inverted\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n});\r\n\r\n/**\r\n * Props for MultiSelect component\r\n */\r\ninterface MultiSelectProps<T extends string | number>\r\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"value\" | \"defaultValue\">,\r\n VariantProps<typeof multiSelectVariants> {\r\n /**\r\n * An array of option objects to be displayed in the multi-select component.\r\n * Each option object has a label, value, and an optional icon.\r\n */\r\n options: {\r\n /** The text to display for the option. */\r\n label: string;\r\n /** The unique value associated with the option. */\r\n value: T;\r\n /** Optional icon component to display alongside the option. */\r\n icon?: React.ComponentType<{ className?: string }>;\r\n }[];\r\n\r\n /**\r\n * Callback function triggered when the selected values change.\r\n * Receives an array of the new selected values.\r\n */\r\n onValueChange: (value: T[]) => void;\r\n\r\n /**\r\n * selected values in the multi-select component.\r\n */\r\n value?: T[];\r\n\r\n /** The default selected values when the component mounts. */\r\n defaultValue?: T[];\r\n\r\n /**\r\n * Placeholder text to be displayed when no values are selected.\r\n * Optional, defaults to \"Select options\".\r\n */\r\n placeholder?: string;\r\n\r\n /**\r\n * Maximum number of items to display. Extra selected items will be summarized.\r\n * Optional, defaults to 3.\r\n */\r\n maxCount?: number;\r\n\r\n /**\r\n * The modality of the popover. When set to true, interaction with outside elements\r\n * will be disabled and only popover content will be visible to screen readers.\r\n * Optional, defaults to false.\r\n */\r\n modalPopover?: boolean;\r\n\r\n /**\r\n * If true, renders the multi-select component as a child of another component.\r\n * Optional, defaults to false.\r\n */\r\n asChild?: boolean;\r\n\r\n /**\r\n * Additional class names to apply custom styles to the multi-select component.\r\n * Optional, can be used to add custom styles.\r\n */\r\n className?: string;\r\n\r\n /**\r\n * Text to display on the close button when the multi-select component is open.\r\n */\r\n closeText?: string;\r\n\r\n /**\r\n * Text to display on the select all button when the multi-select component is open.\r\n */\r\n selectAllText?: string;\r\n\r\n /**\r\n * Text to display on the clear button when the multi-select component is open.\r\n */\r\n clearText?: string;\r\n\r\n /**\r\n * Text to display on the more button when the multi-select component is open.\r\n */\r\n moreText?: string;\r\n\r\n /**\r\n * Text to display when no results are found in the search input.\r\n */\r\n noResultsText?: string;\r\n\r\n /**\r\n * If true, the multi-select component will be in a loading state.\r\n */\r\n loading?: boolean;\r\n\r\n /**\r\n * Text to display when the multi-select component is in a loading state.\r\n */\r\n loadingText?: string;\r\n}\r\n\r\nconst MultiSelect = <T extends string | number>(\r\n {\r\n options,\r\n onValueChange,\r\n value,\r\n variant,\r\n disabled,\r\n defaultValue = [],\r\n placeholder = \"Select options\",\r\n maxCount = 3,\r\n modalPopover = false,\r\n // asChild = false,\r\n className,\r\n moreText = \"more\",\r\n clearText = \"Clear\",\r\n closeText = \"Close\",\r\n selectAllText = \"Select All\",\r\n noResultsText = \"No results found.\",\r\n loading,\r\n loadingText = \"Loading...\",\r\n ...props\r\n }: MultiSelectProps<T>,\r\n ref: React.ForwardedRef<HTMLButtonElement>,\r\n) => {\r\n const [selectedValues, setSelectedValues] = React.useState<T[]>(defaultValue ?? value);\r\n const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);\r\n const containerRef = React.useRef<HTMLDivElement>(null);\r\n const [isWrapped, setIsWrapped] = React.useState(false);\r\n\r\n React.useEffect(() => {\r\n setSelectedValues(value ?? []);\r\n }, [value]);\r\n\r\n const handleInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\r\n if (event.key === \"Enter\") {\r\n setIsPopoverOpen(true);\r\n } else if (event.key === \"Backspace\" && !event.currentTarget.value) {\r\n const newSelectedValues = [...selectedValues];\r\n newSelectedValues.pop();\r\n setSelectedValues(newSelectedValues);\r\n onValueChange(newSelectedValues);\r\n }\r\n };\r\n\r\n const toggleOption = (option: T) => {\r\n const newSelectedValues = selectedValues.includes(option) ? selectedValues.filter(value => value !== option) : [...selectedValues, option];\r\n setSelectedValues(newSelectedValues);\r\n onValueChange(newSelectedValues);\r\n };\r\n\r\n const handleClear = () => {\r\n setSelectedValues([]);\r\n onValueChange([]);\r\n };\r\n\r\n const handleTogglePopover = () => {\r\n setIsPopoverOpen(prev => !prev);\r\n };\r\n\r\n const clearExtraOptions = () => {\r\n const newSelectedValues = selectedValues.slice(0, maxCount);\r\n setSelectedValues(newSelectedValues);\r\n onValueChange(newSelectedValues);\r\n };\r\n\r\n const toggleAll = () => {\r\n if (selectedValues.length === options.length) {\r\n handleClear();\r\n } else {\r\n const allValues = options.map(option => option.value);\r\n setSelectedValues(allValues);\r\n onValueChange(allValues);\r\n }\r\n };\r\n\r\n React.useLayoutEffect(() => {\r\n if (containerRef.current) {\r\n if ((containerRef?.current?.firstChild as HTMLElement)?.offsetTop < (containerRef?.current?.lastChild as HTMLElement)?.offsetTop) {\r\n setIsWrapped(true);\r\n } else {\r\n setIsWrapped(false);\r\n }\r\n }\r\n }, [selectedValues]);\r\n\r\n return (\r\n <Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen} modal={modalPopover}>\r\n <PopoverTrigger asChild>\r\n <Button\r\n ref={ref}\r\n variant=\"text\"\r\n loading={loading}\r\n disabled={disabled}\r\n {...props}\r\n onClick={handleTogglePopover}\r\n className={cn(\r\n \"group flex max-h-14 h-8 w-full items-center justify-between whitespace-nowrap rounded-sm border border-input bg-transparent px-3 py-1.5 text-sm ring-offset-background data-[placeholder]:text-muted-foreground hover:border hover:border-primary hover:bg-transparent focus:border focus:border-primary focus:outline-none focus:ring focus:ring-primary-100 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:text-text-300 disabled:border-gray-100 [&>span]:line-clamp-1 [&_svg]:disabled:text-text-300\",\r\n isWrapped && \"h-auto\",\r\n className,\r\n )}\r\n data-placeholder={!selectedValues.length ? \"\" : undefined}\r\n endIcon={\r\n <ChevronDown\r\n role=\"button\"\r\n aria-label=\"Expand dropdown\"\r\n className=\"!h-4.5 !w-4.5 cursor-pointer group-data-[state=open]:rotate-180 transition-transform\"\r\n />\r\n }\r\n >\r\n <>\r\n {selectedValues.length > 0 ? (\r\n <div className=\"flex justify-between items-center w-full\">\r\n <div className=\"flex flex-wrap items-center gap-2\" ref={containerRef}>\r\n {selectedValues.slice(0, maxCount).map(value => {\r\n const option = options.find(o => o.value === value);\r\n const IconComponent = option?.icon;\r\n return (\r\n <Badge key={value} className={cn(multiSelectVariants({ variant }), { \"text-gray-400 bg-gray-200\": disabled || loading })}>\r\n <XMark\r\n className=\"h-4 w-4 cursor-pointer\"\r\n onClick={event => {\r\n event.stopPropagation();\r\n toggleOption(value);\r\n }}\r\n />\r\n {IconComponent && <IconComponent className=\"h-4 w-4 mr-2\" />}\r\n {option?.label}\r\n </Badge>\r\n );\r\n })}\r\n {selectedValues.length > maxCount && (\r\n <Badge className={cn(multiSelectVariants({ variant }))}>\r\n {`+ ${selectedValues.length - maxCount} ${moreText}`}\r\n <CircleXmark\r\n role=\"button\"\r\n className=\"ml-2 h-4.5 w-4.5 cursor-pointer\"\r\n onClick={event => {\r\n event.stopPropagation();\r\n clearExtraOptions();\r\n }}\r\n />\r\n </Badge>\r\n )}\r\n {loading && loadingText ? loadingText : null}\r\n </div>\r\n <div className=\"flex items-center justify-between gap-1\">\r\n <XMark\r\n role=\"button\"\r\n className=\"h-5 w-5 text-muted-foreground cursor-pointer\"\r\n onClick={event => {\r\n event.stopPropagation();\r\n handleClear();\r\n }}\r\n aria-label=\"Clear\"\r\n />\r\n <Separator orientation=\"vertical\" className=\"flex min-h-5 h-full\" />\r\n </div>\r\n </div>\r\n ) : (\r\n <>{loading && loadingText ? loadingText : placeholder}</>\r\n )}\r\n </>\r\n </Button>\r\n </PopoverTrigger>\r\n <PopoverContent className=\"w-auto p-0\" align=\"start\" onEscapeKeyDown={() => setIsPopoverOpen(false)}>\r\n <Command className=\"w-[--radix-popper-anchor-width]\">\r\n <CommandInput placeholder=\"Search...\" onKeyDown={handleInputKeyDown} />\r\n <CommandList className=\"max-h-[--radix-popper-available-height]\">\r\n <CommandEmpty>{noResultsText}</CommandEmpty>\r\n <CommandGroup>\r\n <CommandItem key=\"all\" onSelect={toggleAll} className=\"cursor-pointer\">\r\n <div\r\n className={cn(\r\n \"mr-2 flex h-4.5 w-4.5 items-center justify-center rounded-sm border border-primary\",\r\n selectedValues.length === options.length ? \"bg-primary text-primary-foreground\" : \"opacity-50 [&_svg]:invisible\",\r\n )}\r\n >\r\n <Check className=\"h-4.5 w-4.5\" />\r\n </div>\r\n <span>({selectAllText})</span>\r\n </CommandItem>\r\n {options.map(option => {\r\n const isSelected = selectedValues.includes(option.value);\r\n return (\r\n <CommandItem key={option.value} onSelect={() => toggleOption(option.value)} className=\"cursor-pointer\">\r\n <div\r\n className={cn(\r\n \"mr-2 flex h-4.5 w-4.5 items-center justify-center rounded-sm border border-primary\",\r\n isSelected ? \"bg-primary text-primary-foreground\" : \"opacity-50 [&_svg]:invisible\",\r\n )}\r\n >\r\n <Check className=\"h-4.5 w-4.5\" />\r\n </div>\r\n {option.icon && <option.icon className=\"mr-2 h-4.5 w-4.5 text-muted-foreground\" />}\r\n <span>{option.label}</span>\r\n </CommandItem>\r\n );\r\n })}\r\n </CommandGroup>\r\n <CommandSeparator />\r\n <CommandGroup>\r\n <div className=\"flex items-center justify-between\">\r\n {selectedValues.length > 0 && (\r\n <>\r\n <CommandItem onSelect={handleClear} className=\"flex-1 justify-center cursor-pointer\">\r\n {clearText}\r\n </CommandItem>\r\n <Separator orientation=\"vertical\" className=\"flex min-h-6 h-full\" />\r\n </>\r\n )}\r\n <CommandItem onSelect={() => setIsPopoverOpen(false)} className=\"flex-1 justify-center cursor-pointer max-w-full\">\r\n {closeText}\r\n </CommandItem>\r\n </div>\r\n </CommandGroup>\r\n </CommandList>\r\n </Command>\r\n </PopoverContent>\r\n </Popover>\r\n );\r\n};\r\n\r\nconst ForwardedMultiSelect = React.forwardRef(MultiSelect) as (<T extends string | number>(\r\n props: MultiSelectProps<T> & { ref?: React.Ref<HTMLButtonElement> },\r\n) => React.ReactElement) & { displayName?: string };\r\n\r\nForwardedMultiSelect.displayName = \"MultiSelect\";\r\n\r\nexport { ForwardedMultiSelect as MultiSelect, type MultiSelectProps };\r\n"],"names":["multiSelectVariants","tv","MultiSelect","options","onValueChange","value","variant","disabled","defaultValue","placeholder","maxCount","modalPopover","className","moreText","clearText","closeText","selectAllText","noResultsText","loading","loadingText","props","ref","selectedValues","setSelectedValues","React","isPopoverOpen","setIsPopoverOpen","containerRef","isWrapped","setIsWrapped","handleInputKeyDown","event","newSelectedValues","toggleOption","option","handleClear","handleTogglePopover","prev","clearExtraOptions","toggleAll","allValues","Popover","jsx","PopoverTrigger","Button","cn","ChevronDown","jsxs","o","IconComponent","Badge","XMark","CircleXmark","Separator","Fragment","PopoverContent","Command","CommandInput","CommandList","CommandEmpty","CommandGroup","CommandItem","Check","isSelected","CommandSeparator","ForwardedMultiSelect"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"multiselect.es.js","sources":["../src/components/multi-select/MultiSelect.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { tv, type VariantProps } from \"tailwind-variants\";\r\nimport { Check, ChevronDown, CircleXmark, XMark } from \"@trsys-tech/matrix-icons\";\r\n\r\nimport { cn } from \"../../lib/utils\";\r\nimport { Badge } from \"../badge/Badge\";\r\nimport { Button } from \"../button/Button\";\r\nimport { Separator } from \"../separator/Separator\";\r\nimport { Popover, PopoverContent, PopoverTrigger } from \"../popover/Popover\";\r\nimport { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from \"../command/Command\";\r\n\r\n/**\r\n * Variants for the multi-select component to handle different styles.\r\n * Uses tailwind-variants (cva) to define different styles based on \"variant\" prop.\r\n */\r\nconst multiSelectVariants = tv({\r\n base: \"flex gap-1 items-center py-0.5 px-2 rounded-xl\",\r\n variants: {\r\n variant: {\r\n default: \"border-none shadow-none bg-primary-50 text-primary hover:bg-primary-50\",\r\n secondary: \"border-foreground/10 bg-secondary text-secondary-foreground hover:bg-secondary/80\",\r\n destructive: \"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80\",\r\n inverted: \"inverted\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n});\r\n\r\n/**\r\n * Props for MultiSelect component\r\n */\r\ninterface MultiSelectProps<T extends string | number>\r\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"value\" | \"defaultValue\">,\r\n VariantProps<typeof multiSelectVariants> {\r\n /**\r\n * An array of option objects to be displayed in the multi-select component.\r\n * Each option object has a label, value, and an optional icon.\r\n *\r\n * *Important: Use a constant Array*\r\n */\r\n options: {\r\n /** The text to display for the option. */\r\n label: string;\r\n /** The unique value associated with the option. */\r\n value: T;\r\n /** Optional icon component to display alongside the option. */\r\n icon?: React.ComponentType<{ className?: string }>;\r\n }[];\r\n\r\n /**\r\n * Callback function triggered when the selected values change.\r\n * Receives an array of the new selected values.\r\n */\r\n onValueChange: (value: T[]) => void;\r\n\r\n /**\r\n * selected values in the multi-select component.\r\n */\r\n value?: T[];\r\n\r\n /** The default selected values when the component mounts. */\r\n defaultValue?: T[];\r\n\r\n /**\r\n * Placeholder text to be displayed when no values are selected.\r\n * Optional, defaults to \"Select options\".\r\n */\r\n placeholder?: string;\r\n\r\n /**\r\n * Maximum number of items to display. Extra selected items will be summarized.\r\n * Optional, defaults to 3.\r\n */\r\n maxCount?: number;\r\n\r\n /**\r\n * The modality of the popover. When set to true, interaction with outside elements\r\n * will be disabled and only popover content will be visible to screen readers.\r\n * Optional, defaults to false.\r\n */\r\n modalPopover?: boolean;\r\n\r\n /**\r\n * If true, renders the multi-select component as a child of another component.\r\n * Optional, defaults to false.\r\n */\r\n asChild?: boolean;\r\n\r\n /**\r\n * Additional class names to apply custom styles to the multi-select component.\r\n * Optional, can be used to add custom styles.\r\n */\r\n className?: string;\r\n\r\n /**\r\n * Text to display on the close button when the multi-select component is open.\r\n */\r\n closeText?: string;\r\n\r\n /**\r\n * Whether to show the select all option or not\r\n */\r\n showSelectAll?: boolean;\r\n\r\n /**\r\n * Text to display on the select all button when the multi-select component is open.\r\n */\r\n selectAllText?: string;\r\n\r\n /**\r\n * Text to display in the search input.\r\n */\r\n searchText?: string;\r\n\r\n /**\r\n * If true, a new option will be added when the user submits a search query if it doesn't already exist.\r\n * Optional, defaults to false.\r\n */\r\n addOptionOnSearchNotFound?: boolean;\r\n\r\n /**\r\n * Text to display on the clear button when the multi-select component is open.\r\n */\r\n clearText?: string;\r\n\r\n /**\r\n * Text to display on the more button when the multi-select component is open.\r\n */\r\n moreText?: string;\r\n\r\n /**\r\n * Text to display when no results are found in the search input.\r\n */\r\n noResultsText?: string;\r\n\r\n /**\r\n * If true, the multi-select component will be in a loading state.\r\n */\r\n loading?: boolean;\r\n\r\n /**\r\n * Text to display when the multi-select component is in a loading state.\r\n */\r\n loadingText?: string;\r\n}\r\n\r\nconst MultiSelect = <T extends string | number>(\r\n {\r\n options: _options,\r\n onValueChange,\r\n value,\r\n variant,\r\n disabled,\r\n defaultValue = [],\r\n placeholder = \"Select options\",\r\n maxCount = 3,\r\n modalPopover = false,\r\n // asChild = false,\r\n className,\r\n moreText = \"more\",\r\n clearText = \"Clear\",\r\n closeText = \"Close\",\r\n selectAllText = \"Select All\",\r\n noResultsText = \"No results found.\",\r\n searchText = \"Search...\",\r\n addOptionOnSearchNotFound = false,\r\n showSelectAll = true,\r\n loading,\r\n loadingText = \"Loading...\",\r\n ...props\r\n }: MultiSelectProps<T>,\r\n ref: React.ForwardedRef<HTMLButtonElement>,\r\n) => {\r\n const [selectedValues, setSelectedValues] = React.useState<T[]>(defaultValue ?? value);\r\n const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);\r\n const containerRef = React.useRef<HTMLDivElement>(null);\r\n const [searchValue, setSearchValue] = React.useState(\"\");\r\n const [isWrapped, setIsWrapped] = React.useState(false);\r\n const [options, setOptions] = React.useState<Map<T, MultiSelectProps<T>[\"options\"][number]>>(\r\n new Map(_options.map(option => [option.value, option])),\r\n );\r\n\r\n const handleInputKeyDown = React.useCallback(\r\n (event: React.KeyboardEvent<HTMLInputElement>) => {\r\n if (event.key === \"Enter\" && addOptionOnSearchNotFound) {\r\n setIsPopoverOpen(true);\r\n event.preventDefault();\r\n event.stopPropagation();\r\n if (!event.currentTarget.value) return;\r\n const newOption = { value: event.currentTarget.value as T, label: event.currentTarget.value };\r\n if (options.get(newOption.value) === undefined) {\r\n setOptions(prev => {\r\n return new Map(prev).set(newOption.value, newOption);\r\n });\r\n const newSelectedValues = [...selectedValues, newOption.value];\r\n setSelectedValues(newSelectedValues);\r\n onValueChange(newSelectedValues);\r\n setSearchValue(\"\");\r\n }\r\n } else if (event.key === \"Enter\") {\r\n setIsPopoverOpen(true);\r\n } else if (event.key === \"Backspace\" && !event.currentTarget.value) {\r\n const newSelectedValues = [...selectedValues];\r\n newSelectedValues.pop();\r\n setSelectedValues(newSelectedValues);\r\n onValueChange(newSelectedValues);\r\n }\r\n },\r\n [addOptionOnSearchNotFound, onValueChange, options, selectedValues],\r\n );\r\n\r\n const toggleOption = React.useCallback(\r\n (option: T) => {\r\n const newSelectedValues = selectedValues.includes(option) ? selectedValues.filter(value => value !== option) : [...selectedValues, option];\r\n setSelectedValues(newSelectedValues);\r\n onValueChange(newSelectedValues);\r\n },\r\n [onValueChange, selectedValues],\r\n );\r\n\r\n const handleClear = React.useCallback(() => {\r\n setSelectedValues([]);\r\n onValueChange([]);\r\n if (addOptionOnSearchNotFound) {\r\n setOptions(new Map(_options.map(option => [option.value, option])));\r\n }\r\n }, [onValueChange, addOptionOnSearchNotFound, _options]);\r\n\r\n const handleTogglePopover = React.useCallback(() => {\r\n setIsPopoverOpen(prev => !prev);\r\n }, []);\r\n\r\n const clearExtraOptions = React.useCallback(() => {\r\n const newSelectedValues = selectedValues.slice(0, maxCount);\r\n setSelectedValues(newSelectedValues);\r\n onValueChange(newSelectedValues);\r\n }, [maxCount, selectedValues, onValueChange]);\r\n\r\n const toggleAll = React.useCallback(() => {\r\n if (selectedValues.length === options.size) {\r\n handleClear();\r\n } else {\r\n const allValues = Array.from(options.keys());\r\n setSelectedValues(allValues);\r\n onValueChange(allValues);\r\n }\r\n }, [handleClear, onValueChange, options, selectedValues.length]);\r\n\r\n React.useEffect(() => {\r\n setOptions(new Map(_options.map(option => [option.value, option])));\r\n }, [_options]);\r\n\r\n React.useEffect(() => {\r\n setSelectedValues(value ?? []);\r\n }, [value]);\r\n\r\n React.useLayoutEffect(() => {\r\n if (containerRef.current) {\r\n if ((containerRef?.current?.firstChild as HTMLElement)?.offsetTop < (containerRef?.current?.lastChild as HTMLElement)?.offsetTop) {\r\n setIsWrapped(true);\r\n } else {\r\n setIsWrapped(false);\r\n }\r\n }\r\n }, [selectedValues]);\r\n\r\n return (\r\n <Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen} modal={modalPopover}>\r\n <PopoverTrigger asChild>\r\n <Button\r\n ref={ref}\r\n variant=\"text\"\r\n loading={loading}\r\n disabled={disabled}\r\n {...props}\r\n onClick={handleTogglePopover}\r\n className={cn(\r\n \"group flex max-h-14 h-8 w-full items-center justify-between whitespace-nowrap rounded-sm border border-input bg-transparent px-3 py-1.5 text-sm ring-offset-background data-[placeholder]:text-muted-foreground hover:border hover:border-primary hover:bg-transparent focus:border focus:border-primary focus:outline-none focus:ring focus:ring-primary-100 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:text-text-300 disabled:border-gray-100 [&>span]:line-clamp-1 [&_svg]:disabled:text-text-300\",\r\n isWrapped && \"h-auto\",\r\n className,\r\n )}\r\n data-placeholder={!selectedValues.length ? \"\" : undefined}\r\n endIcon={\r\n <ChevronDown\r\n role=\"button\"\r\n aria-label=\"Expand dropdown\"\r\n className=\"!h-4.5 !w-4.5 cursor-pointer group-data-[state=open]:rotate-180 transition-transform\"\r\n />\r\n }\r\n >\r\n <>\r\n {selectedValues.length > 0 ? (\r\n <div className=\"flex justify-between items-center w-full\">\r\n <div className=\"flex flex-wrap items-center gap-2\" ref={containerRef}>\r\n {selectedValues.slice(0, maxCount).map(value => {\r\n const option = options.get(value);\r\n const IconComponent = option?.icon;\r\n return (\r\n <Badge key={value} className={cn(multiSelectVariants({ variant }), { \"text-gray-400 bg-gray-200\": disabled || loading })}>\r\n <XMark\r\n className=\"h-4 w-4 cursor-pointer\"\r\n onClick={event => {\r\n event.stopPropagation();\r\n toggleOption(value);\r\n }}\r\n />\r\n {IconComponent && <IconComponent className=\"h-4 w-4 mr-2\" />}\r\n {option?.label}\r\n </Badge>\r\n );\r\n })}\r\n {selectedValues.length > maxCount && (\r\n <Badge className={cn(multiSelectVariants({ variant }))}>\r\n {`+ ${selectedValues.length - maxCount} ${moreText}`}\r\n <CircleXmark\r\n role=\"button\"\r\n className=\"ml-2 h-4.5 w-4.5 cursor-pointer\"\r\n onClick={event => {\r\n event.stopPropagation();\r\n clearExtraOptions();\r\n }}\r\n />\r\n </Badge>\r\n )}\r\n {loading && loadingText ? loadingText : null}\r\n </div>\r\n <div className=\"flex items-center justify-between gap-1\">\r\n <XMark\r\n role=\"button\"\r\n className=\"h-5 w-5 text-muted-foreground cursor-pointer\"\r\n onClick={event => {\r\n event.stopPropagation();\r\n handleClear();\r\n }}\r\n aria-label=\"Clear\"\r\n />\r\n <Separator orientation=\"vertical\" className=\"flex min-h-5 h-full\" />\r\n </div>\r\n </div>\r\n ) : (\r\n <>{loading && loadingText ? loadingText : placeholder}</>\r\n )}\r\n </>\r\n </Button>\r\n </PopoverTrigger>\r\n <PopoverContent className=\"w-auto p-0\" align=\"start\" onEscapeKeyDown={() => setIsPopoverOpen(false)}>\r\n <Command className=\"w-[--radix-popper-anchor-width] max-h-[--radix-popper-available-height]\">\r\n <CommandInput placeholder={searchText} onKeyDown={handleInputKeyDown} value={searchValue} onValueChange={setSearchValue} />\r\n <CommandList className=\"\">\r\n <CommandEmpty>{noResultsText}</CommandEmpty>\r\n <CommandGroup>\r\n {showSelectAll && (\r\n <CommandItem key=\"all\" onSelect={toggleAll} className=\"cursor-pointer\">\r\n <div\r\n className={cn(\r\n \"mr-2 flex h-4.5 w-4.5 items-center justify-center rounded-sm border border-primary\",\r\n selectedValues.length === options.size ? \"bg-primary text-primary-foreground\" : \"opacity-50 [&_svg]:invisible\",\r\n )}\r\n >\r\n <Check className=\"h-4.5 w-4.5\" />\r\n </div>\r\n <span>({selectAllText})</span>\r\n </CommandItem>\r\n )}\r\n {Array.from(options.values()).map(option => {\r\n const isSelected = selectedValues.includes(option.value);\r\n return (\r\n <CommandItem key={option.value} onSelect={() => toggleOption(option.value)} className=\"cursor-pointer\">\r\n <div\r\n className={cn(\r\n \"mr-2 flex h-4.5 w-4.5 items-center justify-center rounded-sm border border-primary\",\r\n isSelected ? \"bg-primary text-primary-foreground\" : \"opacity-50 [&_svg]:invisible\",\r\n )}\r\n >\r\n <Check className=\"h-4.5 w-4.5\" />\r\n </div>\r\n {option.icon && <option.icon className=\"mr-2 h-4.5 w-4.5 text-muted-foreground\" />}\r\n <span>{option.label}</span>\r\n </CommandItem>\r\n );\r\n })}\r\n </CommandGroup>\r\n <CommandSeparator />\r\n <CommandGroup>\r\n <div className=\"flex items-center justify-between\">\r\n {selectedValues.length > 0 && (\r\n <>\r\n <CommandItem onSelect={handleClear} className=\"flex-1 justify-center cursor-pointer\">\r\n {clearText}\r\n </CommandItem>\r\n <Separator orientation=\"vertical\" className=\"flex min-h-6 h-full\" />\r\n </>\r\n )}\r\n <CommandItem onSelect={() => setIsPopoverOpen(false)} className=\"flex-1 justify-center cursor-pointer max-w-full\">\r\n {closeText}\r\n </CommandItem>\r\n </div>\r\n </CommandGroup>\r\n </CommandList>\r\n </Command>\r\n </PopoverContent>\r\n </Popover>\r\n );\r\n};\r\n\r\nconst ForwardedMultiSelect = React.forwardRef(MultiSelect) as (<T extends string | number>(\r\n props: MultiSelectProps<T> & { ref?: React.Ref<HTMLButtonElement> },\r\n) => React.ReactElement) & { displayName?: string };\r\n\r\nForwardedMultiSelect.displayName = \"MultiSelect\";\r\n\r\nexport { ForwardedMultiSelect as MultiSelect, type MultiSelectProps };\r\n"],"names":["multiSelectVariants","tv","MultiSelect","_options","onValueChange","value","variant","disabled","defaultValue","placeholder","maxCount","modalPopover","className","moreText","clearText","closeText","selectAllText","noResultsText","searchText","addOptionOnSearchNotFound","showSelectAll","loading","loadingText","props","ref","selectedValues","setSelectedValues","React","isPopoverOpen","setIsPopoverOpen","containerRef","searchValue","setSearchValue","isWrapped","setIsWrapped","options","setOptions","option","handleInputKeyDown","event","newOption","prev","newSelectedValues","toggleOption","handleClear","handleTogglePopover","clearExtraOptions","toggleAll","allValues","Popover","jsx","PopoverTrigger","Button","cn","ChevronDown","jsxs","IconComponent","Badge","XMark","CircleXmark","Separator","Fragment","PopoverContent","Command","CommandInput","CommandList","CommandEmpty","CommandGroup","CommandItem","Check","isSelected","CommandSeparator","ForwardedMultiSelect"],"mappings":";;;;;;;;;;AAiBA,MAAMA,IAAsBC,GAAG;AAAA,EAC7B,MAAM;AAAA,EACN,UAAU;AAAA,IACR,SAAS;AAAA,MACP,SAAS;AAAA,MACT,WAAW;AAAA,MACX,aAAa;AAAA,MACb,UAAU;AAAA,IAAA;AAAA,EACZ;AAAA,EAEF,iBAAiB;AAAA,IACf,SAAS;AAAA,EAAA;AAEb,CAAC,GAwHKC,KAAc,CAClB;AAAA,EACE,SAASC;AAAA,EACT,eAAAC;AAAA,EACA,OAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,cAAAC,IAAe,CAAA;AAAA,EACf,aAAAC,IAAc;AAAA,EACd,UAAAC,IAAW;AAAA,EACX,cAAAC,IAAe;AAAA;AAAA,EAEf,WAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,WAAAC,IAAY;AAAA,EACZ,WAAAC,IAAY;AAAA,EACZ,eAAAC,IAAgB;AAAA,EAChB,eAAAC,IAAgB;AAAA,EAChB,YAAAC,IAAa;AAAA,EACb,2BAAAC,IAA4B;AAAA,EAC5B,eAAAC,IAAgB;AAAA,EAChB,SAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,GAAGC;AACL,GACAC,MACG;AACH,QAAM,CAACC,GAAgBC,CAAiB,IAAIC,EAAM,SAAcnB,KAAgBH,CAAK,GAC/E,CAACuB,GAAeC,CAAgB,IAAIF,EAAM,SAAS,EAAK,GACxDG,IAAeH,EAAM,OAAuB,IAAI,GAChD,CAACI,GAAaC,CAAc,IAAIL,EAAM,SAAS,EAAE,GACjD,CAACM,GAAWC,CAAY,IAAIP,EAAM,SAAS,EAAK,GAChD,CAACQ,GAASC,CAAU,IAAIT,EAAM;AAAA,IAClC,IAAI,IAAIxB,EAAS,IAAI,CAAAkC,MAAU,CAACA,EAAO,OAAOA,CAAM,CAAC,CAAC;AAAA,EAAA,GAGlDC,IAAqBX,EAAM;AAAA,IAC/B,CAACY,MAAiD;AAChD,UAAIA,EAAM,QAAQ,WAAWpB,GAA2B;AAItD,YAHAU,EAAiB,EAAI,GACrBU,EAAM,eAAA,GACNA,EAAM,gBAAA,GACF,CAACA,EAAM,cAAc,MAAO;AAChC,cAAMC,IAAY,EAAE,OAAOD,EAAM,cAAc,OAAY,OAAOA,EAAM,cAAc,MAAA;AACtF,YAAIJ,EAAQ,IAAIK,EAAU,KAAK,MAAM,QAAW;AAC9C,UAAAJ,EAAW,CAAAK,MACF,IAAI,IAAIA,CAAI,EAAE,IAAID,EAAU,OAAOA,CAAS,CACpD;AACD,gBAAME,IAAoB,CAAC,GAAGjB,GAAgBe,EAAU,KAAK;AAC7D,UAAAd,EAAkBgB,CAAiB,GACnCtC,EAAcsC,CAAiB,GAC/BV,EAAe,EAAE;AAAA,QACnB;AAAA,MACF,WAAWO,EAAM,QAAQ;AACvB,QAAAV,EAAiB,EAAI;AAAA,eACZU,EAAM,QAAQ,eAAe,CAACA,EAAM,cAAc,OAAO;AAClE,cAAMG,IAAoB,CAAC,GAAGjB,CAAc;AAC5C,QAAAiB,EAAkB,IAAA,GAClBhB,EAAkBgB,CAAiB,GACnCtC,EAAcsC,CAAiB;AAAA,MACjC;AAAA,IACF;AAAA,IACA,CAACvB,GAA2Bf,GAAe+B,GAASV,CAAc;AAAA,EAAA,GAG9DkB,IAAehB,EAAM;AAAA,IACzB,CAACU,MAAc;AACb,YAAMK,IAAoBjB,EAAe,SAASY,CAAM,IAAIZ,EAAe,OAAO,CAAApB,MAASA,MAAUgC,CAAM,IAAI,CAAC,GAAGZ,GAAgBY,CAAM;AACzI,MAAAX,EAAkBgB,CAAiB,GACnCtC,EAAcsC,CAAiB;AAAA,IACjC;AAAA,IACA,CAACtC,GAAeqB,CAAc;AAAA,EAAA,GAG1BmB,IAAcjB,EAAM,YAAY,MAAM;AAC1C,IAAAD,EAAkB,CAAA,CAAE,GACpBtB,EAAc,CAAA,CAAE,GACZe,KACFiB,EAAW,IAAI,IAAIjC,EAAS,IAAI,CAAAkC,MAAU,CAACA,EAAO,OAAOA,CAAM,CAAC,CAAC,CAAC;AAAA,EAEtE,GAAG,CAACjC,GAAee,GAA2BhB,CAAQ,CAAC,GAEjD0C,IAAsBlB,EAAM,YAAY,MAAM;AAClD,IAAAE,EAAiB,CAAAY,MAAQ,CAACA,CAAI;AAAA,EAChC,GAAG,CAAA,CAAE,GAECK,IAAoBnB,EAAM,YAAY,MAAM;AAChD,UAAMe,IAAoBjB,EAAe,MAAM,GAAGf,CAAQ;AAC1D,IAAAgB,EAAkBgB,CAAiB,GACnCtC,EAAcsC,CAAiB;AAAA,EACjC,GAAG,CAAChC,GAAUe,GAAgBrB,CAAa,CAAC,GAEtC2C,KAAYpB,EAAM,YAAY,MAAM;AACxC,QAAIF,EAAe,WAAWU,EAAQ;AACpC,MAAAS,EAAA;AAAA,SACK;AACL,YAAMI,IAAY,MAAM,KAAKb,EAAQ,MAAM;AAC3C,MAAAT,EAAkBsB,CAAS,GAC3B5C,EAAc4C,CAAS;AAAA,IACzB;AAAA,EACF,GAAG,CAACJ,GAAaxC,GAAe+B,GAASV,EAAe,MAAM,CAAC;AAE/D,SAAAE,EAAM,UAAU,MAAM;AACpB,IAAAS,EAAW,IAAI,IAAIjC,EAAS,IAAI,CAAAkC,MAAU,CAACA,EAAO,OAAOA,CAAM,CAAC,CAAC,CAAC;AAAA,EACpE,GAAG,CAAClC,CAAQ,CAAC,GAEbwB,EAAM,UAAU,MAAM;AACpB,IAAAD,EAAkBrB,KAAS,EAAE;AAAA,EAC/B,GAAG,CAACA,CAAK,CAAC,GAEVsB,EAAM,gBAAgB,MAAM;AAC1B,IAAIG,EAAa,YACVA,GAAc,SAAS,YAA4B,YAAaA,GAAc,SAAS,WAA2B,YACrHI,EAAa,EAAI,IAEjBA,EAAa,EAAK;AAAA,EAGxB,GAAG,CAACT,CAAc,CAAC,qBAGhBwB,IAAA,EAAQ,MAAMrB,GAAe,cAAcC,GAAkB,OAAOlB,GACnE,UAAA;AAAA,IAAA,gBAAAuC,EAACC,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAAD;AAAA,MAACE;AAAA,MAAA;AAAA,QACC,KAAA5B;AAAA,QACA,SAAQ;AAAA,QACR,SAAAH;AAAA,QACA,UAAAd;AAAA,QACC,GAAGgB;AAAA,QACJ,SAASsB;AAAA,QACT,WAAWQ;AAAA,UACT;AAAA,UACApB,KAAa;AAAA,UACbrB;AAAA,QAAA;AAAA,QAEF,oBAAmBa,EAAe,SAAc,SAAL;AAAA,QAC3C,SACE,gBAAAyB;AAAA,UAACI;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,cAAW;AAAA,YACX,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAId,iCACG,UAAA7B,EAAe,SAAS,IACvB,gBAAA8B,EAAC,OAAA,EAAI,WAAU,4CACb,UAAA;AAAA,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,qCAAoC,KAAKzB,GACrD,UAAA;AAAA,YAAAL,EAAe,MAAM,GAAGf,CAAQ,EAAE,IAAI,CAAAL,MAAS;AAC9C,oBAAMgC,IAASF,EAAQ,IAAI9B,CAAK,GAC1BmD,IAAgBnB,GAAQ;AAC9B,qBACE,gBAAAkB,EAACE,GAAA,EAAkB,WAAWJ,EAAGrD,EAAoB,EAAE,SAAAM,EAAA,CAAS,GAAG,EAAE,6BAA6BC,KAAYc,EAAA,CAAS,GACrH,UAAA;AAAA,gBAAA,gBAAA6B;AAAA,kBAACQ;AAAA,kBAAA;AAAA,oBACC,WAAU;AAAA,oBACV,SAAS,CAAAnB,MAAS;AAChB,sBAAAA,EAAM,gBAAA,GACNI,EAAatC,CAAK;AAAA,oBACpB;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEDmD,KAAiB,gBAAAN,EAACM,GAAA,EAAc,WAAU,eAAA,CAAe;AAAA,gBACzDnB,GAAQ;AAAA,cAAA,EAAA,GATChC,CAUZ;AAAA,YAEJ,CAAC;AAAA,YACAoB,EAAe,SAASf,KACvB,gBAAA6C,EAACE,GAAA,EAAM,WAAWJ,EAAGrD,EAAoB,EAAE,SAAAM,GAAS,CAAC,GAClD,UAAA;AAAA,cAAA,KAAKmB,EAAe,SAASf,CAAQ,IAAIG,CAAQ;AAAA,cAClD,gBAAAqC;AAAA,gBAACS;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAU;AAAA,kBACV,SAAS,CAAApB,MAAS;AAChB,oBAAAA,EAAM,gBAAA,GACNO,EAAA;AAAA,kBACF;AAAA,gBAAA;AAAA,cAAA;AAAA,YACF,GACF;AAAA,YAEDzB,KAAWC,IAAcA,IAAc;AAAA,UAAA,GAC1C;AAAA,UACA,gBAAAiC,EAAC,OAAA,EAAI,WAAU,2CACb,UAAA;AAAA,YAAA,gBAAAL;AAAA,cAACQ;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,SAAS,CAAAnB,MAAS;AAChB,kBAAAA,EAAM,gBAAA,GACNK,EAAA;AAAA,gBACF;AAAA,gBACA,cAAW;AAAA,cAAA;AAAA,YAAA;AAAA,YAEb,gBAAAM,EAACU,GAAA,EAAU,aAAY,YAAW,WAAU,sBAAA,CAAsB;AAAA,UAAA,EAAA,CACpE;AAAA,QAAA,GACF,IAEA,gBAAAV,EAAAW,GAAA,EAAG,UAAAxC,KAAWC,IAAcA,IAAcb,GAAY,EAAA,CAE1D;AAAA,MAAA;AAAA,IAAA,GAEJ;AAAA,IACA,gBAAAyC,EAACY,IAAA,EAAe,WAAU,cAAa,OAAM,SAAQ,iBAAiB,MAAMjC,EAAiB,EAAK,GAChG,UAAA,gBAAA0B,EAACQ,IAAA,EAAQ,WAAU,2EACjB,UAAA;AAAA,MAAA,gBAAAb,EAACc,IAAA,EAAa,aAAa9C,GAAY,WAAWoB,GAAoB,OAAOP,GAAa,eAAeC,EAAA,CAAgB;AAAA,MACzH,gBAAAuB,EAACU,IAAA,EAAY,WAAU,IACrB,UAAA;AAAA,QAAA,gBAAAf,EAACgB,MAAc,UAAAjD,EAAA,CAAc;AAAA,0BAC5BkD,GAAA,EACE,UAAA;AAAA,UAAA/C,KACC,gBAAAmC,EAACa,GAAA,EAAsB,UAAUrB,IAAW,WAAU,kBACpD,UAAA;AAAA,YAAA,gBAAAG;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAWG;AAAA,kBACT;AAAA,kBACA5B,EAAe,WAAWU,EAAQ,OAAO,uCAAuC;AAAA,gBAAA;AAAA,gBAGlF,UAAA,gBAAAe,EAACmB,GAAA,EAAM,WAAU,cAAA,CAAc;AAAA,cAAA;AAAA,YAAA;AAAA,8BAEhC,QAAA,EAAK,UAAA;AAAA,cAAA;AAAA,cAAErD;AAAA,cAAc;AAAA,YAAA,EAAA,CAAC;AAAA,UAAA,EAAA,GATR,KAUjB;AAAA,UAED,MAAM,KAAKmB,EAAQ,QAAQ,EAAE,IAAI,CAAAE,MAAU;AAC1C,kBAAMiC,IAAa7C,EAAe,SAASY,EAAO,KAAK;AACvD,mBACE,gBAAAkB,EAACa,KAA+B,UAAU,MAAMzB,EAAaN,EAAO,KAAK,GAAG,WAAU,kBACpF,UAAA;AAAA,cAAA,gBAAAa;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAWG;AAAA,oBACT;AAAA,oBACAiB,IAAa,uCAAuC;AAAA,kBAAA;AAAA,kBAGtD,UAAA,gBAAApB,EAACmB,GAAA,EAAM,WAAU,cAAA,CAAc;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEhChC,EAAO,QAAQ,gBAAAa,EAACb,EAAO,MAAP,EAAY,WAAU,0CAAyC;AAAA,cAChF,gBAAAa,EAAC,QAAA,EAAM,UAAAb,EAAO,MAAA,CAAM;AAAA,YAAA,EAAA,GAVJA,EAAO,KAWzB;AAAA,UAEJ,CAAC;AAAA,QAAA,GACH;AAAA,0BACCkC,IAAA,EAAiB;AAAA,QAClB,gBAAArB,EAACiB,GAAA,EACC,UAAA,gBAAAZ,EAAC,OAAA,EAAI,WAAU,qCACZ,UAAA;AAAA,UAAA9B,EAAe,SAAS,KACvB,gBAAA8B,EAAAM,GAAA,EACE,UAAA;AAAA,YAAA,gBAAAX,EAACkB,GAAA,EAAY,UAAUxB,GAAa,WAAU,wCAC3C,UAAA9B,GACH;AAAA,YACA,gBAAAoC,EAACU,GAAA,EAAU,aAAY,YAAW,WAAU,sBAAA,CAAsB;AAAA,UAAA,GACpE;AAAA,UAEF,gBAAAV,EAACkB,KAAY,UAAU,MAAMvC,EAAiB,EAAK,GAAG,WAAU,mDAC7D,UAAAd,EAAA,CACH;AAAA,QAAA,EAAA,CACF,EAAA,CACF;AAAA,MAAA,EAAA,CACF;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,EAAA,GACF;AAEJ,GAEMyD,KAAuB7C,EAAM,WAAWzB,EAAW;AAIzDsE,GAAqB,cAAc;"}
|