lecom-ui 5.3.41 → 5.3.43
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.
|
@@ -18,6 +18,7 @@ const MultiSelect = React.forwardRef(
|
|
|
18
18
|
maxCount = 3,
|
|
19
19
|
modalPopover = false,
|
|
20
20
|
className,
|
|
21
|
+
side = "bottom",
|
|
21
22
|
treeOptions,
|
|
22
23
|
treeSelectionStrategy = "leaf",
|
|
23
24
|
selectAllLabel,
|
|
@@ -29,8 +30,8 @@ const MultiSelect = React.forwardRef(
|
|
|
29
30
|
searchStrategy = "ranked",
|
|
30
31
|
highlightMatches = true,
|
|
31
32
|
allowTypoDistance = 0,
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
groupedOptions,
|
|
34
|
+
classNameContent
|
|
34
35
|
}, ref) => {
|
|
35
36
|
const { t } = useTranslation();
|
|
36
37
|
const [selectedValues, setSelectedValues] = React.useState(value);
|
|
@@ -162,7 +163,10 @@ const MultiSelect = React.forwardRef(
|
|
|
162
163
|
return false;
|
|
163
164
|
}
|
|
164
165
|
if (idx === 0) score += 0;
|
|
165
|
-
else if (new RegExp(`(^|s)${escapeRegex(t2)}`).test(
|
|
166
|
+
else if (new RegExp(`(^|s)${escapeRegex(t2)}`).test(
|
|
167
|
+
nl.slice(Math.max(0, idx - 1))
|
|
168
|
+
))
|
|
169
|
+
score += 5;
|
|
166
170
|
else score += 10;
|
|
167
171
|
}
|
|
168
172
|
if (approximate) score += 5;
|
|
@@ -177,7 +181,9 @@ const MultiSelect = React.forwardRef(
|
|
|
177
181
|
const scored = options.map((o, idx) => {
|
|
178
182
|
const res = searchStrategy === "simple" ? norm(o.label).includes(norm(query)) ? 0 : false : effFilterFn(query, o);
|
|
179
183
|
return { o, score: res === false ? Infinity : res, idx };
|
|
180
|
-
}).filter((x) => x.score !== Infinity).sort(
|
|
184
|
+
}).filter((x) => x.score !== Infinity).sort(
|
|
185
|
+
(a, b) => a.score === b.score ? a.idx - b.idx : a.score - b.score
|
|
186
|
+
);
|
|
181
187
|
return scored.map((s) => s.o);
|
|
182
188
|
}, [options, query, effFilterFn, searchStrategy, norm, isTree]);
|
|
183
189
|
const filterTree = React.useCallback(
|
|
@@ -207,25 +213,25 @@ const MultiSelect = React.forwardRef(
|
|
|
207
213
|
React.useEffect(() => {
|
|
208
214
|
if (!treeOptions) return;
|
|
209
215
|
}, [treeQuery, treeOptions]);
|
|
210
|
-
const findTreeLabel = React.useCallback(
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
216
|
+
const findTreeLabel = React.useCallback(
|
|
217
|
+
(val) => {
|
|
218
|
+
if (!treeOptions) return void 0;
|
|
219
|
+
const stack = [...treeOptions];
|
|
220
|
+
while (stack.length) {
|
|
221
|
+
const n = stack.pop();
|
|
222
|
+
if (n.value === val) return n.label;
|
|
223
|
+
if (n.children) stack.push(...n.children);
|
|
224
|
+
}
|
|
225
|
+
return void 0;
|
|
226
|
+
},
|
|
227
|
+
[treeOptions]
|
|
228
|
+
);
|
|
220
229
|
const collectAllValues = (node) => {
|
|
221
230
|
const self = treeSelectionStrategy === "all" ? [node.value] : [];
|
|
222
231
|
if (!node.children || node.children.length === 0) {
|
|
223
232
|
return treeSelectionStrategy === "all" ? [node.value] : [node.value];
|
|
224
233
|
}
|
|
225
|
-
return [
|
|
226
|
-
...self,
|
|
227
|
-
...node.children.flatMap((c) => collectAllValues(c))
|
|
228
|
-
];
|
|
234
|
+
return [...self, ...node.children.flatMap((c) => collectAllValues(c))];
|
|
229
235
|
};
|
|
230
236
|
const isNodeFullySelected = (node) => {
|
|
231
237
|
const values = collectAllValues(node);
|
|
@@ -253,7 +259,9 @@ const MultiSelect = React.forwardRef(
|
|
|
253
259
|
(label, q) => {
|
|
254
260
|
if (!highlightMatches || !q) return label;
|
|
255
261
|
const nl = norm(label);
|
|
256
|
-
const tokens = Array.from(
|
|
262
|
+
const tokens = Array.from(
|
|
263
|
+
new Set(norm(q).split(/\s+/).filter(Boolean))
|
|
264
|
+
).sort((a, b) => b.length - a.length);
|
|
257
265
|
if (!tokens.length) return label;
|
|
258
266
|
const ranges = [];
|
|
259
267
|
for (const t2 of tokens) {
|
|
@@ -269,17 +277,35 @@ const MultiSelect = React.forwardRef(
|
|
|
269
277
|
ranges.sort((a, b) => a.start - b.start);
|
|
270
278
|
const merged = [];
|
|
271
279
|
for (const r of ranges) {
|
|
272
|
-
if (!merged.length || r.start > merged[merged.length - 1].end)
|
|
273
|
-
|
|
280
|
+
if (!merged.length || r.start > merged[merged.length - 1].end)
|
|
281
|
+
merged.push({ ...r });
|
|
282
|
+
else
|
|
283
|
+
merged[merged.length - 1].end = Math.max(
|
|
284
|
+
merged[merged.length - 1].end,
|
|
285
|
+
r.end
|
|
286
|
+
);
|
|
274
287
|
}
|
|
275
288
|
const parts = [];
|
|
276
289
|
let cursor = 0;
|
|
277
290
|
merged.forEach((r, i) => {
|
|
278
|
-
if (cursor < r.start)
|
|
279
|
-
|
|
291
|
+
if (cursor < r.start)
|
|
292
|
+
parts.push(
|
|
293
|
+
/* @__PURE__ */ React.createElement("span", { key: `t-${i}-pre` }, label.slice(cursor, r.start))
|
|
294
|
+
);
|
|
295
|
+
parts.push(
|
|
296
|
+
/* @__PURE__ */ React.createElement(
|
|
297
|
+
"span",
|
|
298
|
+
{
|
|
299
|
+
key: `t-${i}-hl`,
|
|
300
|
+
className: "bg-blue-100/60 text-grey-900 rounded-[2px] px-0.5"
|
|
301
|
+
},
|
|
302
|
+
label.slice(r.start, r.end)
|
|
303
|
+
)
|
|
304
|
+
);
|
|
280
305
|
cursor = r.end;
|
|
281
306
|
});
|
|
282
|
-
if (cursor < label.length)
|
|
307
|
+
if (cursor < label.length)
|
|
308
|
+
parts.push(/* @__PURE__ */ React.createElement("span", { key: "t-last" }, label.slice(cursor)));
|
|
283
309
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, parts);
|
|
284
310
|
},
|
|
285
311
|
[highlightMatches, norm]
|
|
@@ -394,8 +420,10 @@ const MultiSelect = React.forwardRef(
|
|
|
394
420
|
{
|
|
395
421
|
className: cn(
|
|
396
422
|
"p-0 max-h-80",
|
|
397
|
-
matchTriggerWidth && "w-[var(--radix-popover-trigger-width)]"
|
|
423
|
+
matchTriggerWidth && "w-[var(--radix-popover-trigger-width)]",
|
|
424
|
+
classNameContent
|
|
398
425
|
),
|
|
426
|
+
side,
|
|
399
427
|
align: "start",
|
|
400
428
|
onEscapeKeyDown: () => setIsPopoverOpen(false)
|
|
401
429
|
},
|
|
@@ -425,35 +453,45 @@ const MultiSelect = React.forwardRef(
|
|
|
425
453
|
selectedValues.length === effectiveOptions.length ? /* @__PURE__ */ React.createElement(Check, { className: "h-4 w-4" }) : /* @__PURE__ */ React.createElement(Minus, { className: "h-4 w-4" })
|
|
426
454
|
),
|
|
427
455
|
/* @__PURE__ */ React.createElement("span", { className: "text-grey-800" }, selectAllLabel ?? t("multiSelect.selectAll"))
|
|
428
|
-
), isGrouped ? Object.entries(groupedOptions).map(
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
/* @__PURE__ */ React.createElement(
|
|
443
|
-
|
|
456
|
+
), isGrouped ? Object.entries(groupedOptions).map(
|
|
457
|
+
([categoryName, categoryOptions]) => {
|
|
458
|
+
const filtered = categoryOptions.filter(
|
|
459
|
+
(opt) => !query || effectiveOptions.some(
|
|
460
|
+
(eff) => eff.value === opt.value && filteredOptions.some(
|
|
461
|
+
(filt) => filt.value === opt.value
|
|
462
|
+
)
|
|
463
|
+
)
|
|
464
|
+
);
|
|
465
|
+
if (!filtered.length) return null;
|
|
466
|
+
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) => {
|
|
467
|
+
const isSelected = selectedValues.includes(
|
|
468
|
+
option.value
|
|
469
|
+
);
|
|
470
|
+
return /* @__PURE__ */ React.createElement(
|
|
471
|
+
CommandItem,
|
|
444
472
|
{
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
)
|
|
473
|
+
key: option.value,
|
|
474
|
+
onSelect: () => toggleOption(option.value),
|
|
475
|
+
className: "cursor-pointer"
|
|
449
476
|
},
|
|
450
|
-
/* @__PURE__ */ React.createElement(
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
477
|
+
/* @__PURE__ */ React.createElement(
|
|
478
|
+
"div",
|
|
479
|
+
{
|
|
480
|
+
className: cn(
|
|
481
|
+
"flex h-4 w-4 items-center justify-center rounded-sm border-2 border-grey-400",
|
|
482
|
+
isSelected ? "bg-blue-600 border-blue-600 text-primary-foreground" : "opacity-50 [&_svg]:invisible"
|
|
483
|
+
)
|
|
484
|
+
},
|
|
485
|
+
/* @__PURE__ */ React.createElement(Check, { className: "h-4 w-4" })
|
|
486
|
+
),
|
|
487
|
+
/* @__PURE__ */ React.createElement("span", { className: "text-grey-800" }, highlight(option.label, query))
|
|
488
|
+
);
|
|
489
|
+
}));
|
|
490
|
+
}
|
|
491
|
+
) : filteredOptions.map((option) => {
|
|
492
|
+
const isSelected = selectedValues.includes(
|
|
493
|
+
option.value
|
|
494
|
+
);
|
|
457
495
|
return /* @__PURE__ */ React.createElement(
|
|
458
496
|
CommandItem,
|
|
459
497
|
{
|
|
@@ -474,7 +512,24 @@ const MultiSelect = React.forwardRef(
|
|
|
474
512
|
/* @__PURE__ */ React.createElement("span", { className: "text-grey-800" }, highlight(option.label, query))
|
|
475
513
|
);
|
|
476
514
|
})))),
|
|
477
|
-
isTree && /* @__PURE__ */ React.createElement("div", { className: "min-w-[260px]" }, treeSearch && /* @__PURE__ */ React.createElement("div", { className: "px-1 pt-2 pb-0 border-b border-grey-300" }, /* @__PURE__ */ React.createElement("div", { className: "relative" }, /* @__PURE__ */ React.createElement(
|
|
515
|
+
isTree && /* @__PURE__ */ React.createElement("div", { className: "min-w-[260px]" }, treeSearch && /* @__PURE__ */ React.createElement("div", { className: "px-1 pt-2 pb-0 border-b border-grey-300" }, /* @__PURE__ */ React.createElement("div", { className: "relative" }, /* @__PURE__ */ React.createElement(
|
|
516
|
+
"svg",
|
|
517
|
+
{
|
|
518
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground",
|
|
519
|
+
fill: "none",
|
|
520
|
+
stroke: "currentColor",
|
|
521
|
+
viewBox: "0 0 24 24"
|
|
522
|
+
},
|
|
523
|
+
/* @__PURE__ */ React.createElement(
|
|
524
|
+
"path",
|
|
525
|
+
{
|
|
526
|
+
strokeLinecap: "round",
|
|
527
|
+
strokeLinejoin: "round",
|
|
528
|
+
strokeWidth: 2,
|
|
529
|
+
d: "M21 21l-4.35-4.35m0 0A7.5 7.5 0 1 0 5.25 5.25a7.5 7.5 0 0 0 11.4 11.4z"
|
|
530
|
+
}
|
|
531
|
+
)
|
|
532
|
+
), /* @__PURE__ */ React.createElement(
|
|
478
533
|
"input",
|
|
479
534
|
{
|
|
480
535
|
type: "text",
|
|
@@ -503,7 +558,8 @@ const MultiSelect = React.forwardRef(
|
|
|
503
558
|
for (const n of nodes) {
|
|
504
559
|
const hasChildren = !!(n.children && n.children.length);
|
|
505
560
|
if (!hasChildren) acc += 1;
|
|
506
|
-
else
|
|
561
|
+
else
|
|
562
|
+
acc += treeSelectionStrategy === "all" ? 1 + countAll(n.children) : countAll(n.children);
|
|
507
563
|
}
|
|
508
564
|
return acc;
|
|
509
565
|
}(treeOptions) ? /* @__PURE__ */ React.createElement(Check, { className: "h-4 w-4" }) : /* @__PURE__ */ React.createElement(Minus, { className: "h-4 w-4" })
|
package/dist/index.d.ts
CHANGED
|
@@ -755,9 +755,9 @@ interface HeaderProps extends React$1.HTMLAttributes<HTMLElement>, VariantProps<
|
|
|
755
755
|
}
|
|
756
756
|
|
|
757
757
|
declare const inputVariants: (props?: ({
|
|
758
|
-
variant?: "
|
|
759
|
-
size?: "
|
|
760
|
-
radius?: "
|
|
758
|
+
variant?: "default" | "filled" | "borderless" | null | undefined;
|
|
759
|
+
size?: "default" | "small" | "large" | null | undefined;
|
|
760
|
+
radius?: "default" | "small" | "large" | "full" | null | undefined;
|
|
761
761
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
762
762
|
interface InputProps extends Omit<React$1.InputHTMLAttributes<HTMLInputElement>, 'size' | 'sufix' | 'prefix'>, VariantProps<typeof inputVariants> {
|
|
763
763
|
sufix?: React$1.ReactNode;
|
|
@@ -811,6 +811,7 @@ interface MultiSelectProps extends React$1.ButtonHTMLAttributes<HTMLButtonElemen
|
|
|
811
811
|
asChild?: boolean;
|
|
812
812
|
className?: string;
|
|
813
813
|
matchTriggerWidth?: boolean;
|
|
814
|
+
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
814
815
|
treeOptions?: MultiSelectTreeOption[];
|
|
815
816
|
treeSelectionStrategy?: 'leaf' | 'all';
|
|
816
817
|
selectAllLabel?: string;
|
|
@@ -831,6 +832,7 @@ interface MultiSelectProps extends React$1.ButtonHTMLAttributes<HTMLButtonElemen
|
|
|
831
832
|
value: string;
|
|
832
833
|
}[];
|
|
833
834
|
};
|
|
835
|
+
classNameContent?: string;
|
|
834
836
|
}
|
|
835
837
|
interface MultiSelectTreeOption {
|
|
836
838
|
label: string;
|
|
@@ -942,7 +944,7 @@ declare const RadioGroup: React$1.ForwardRefExoticComponent<Omit<RadioGroupPrimi
|
|
|
942
944
|
declare const RadioGroupItem: React$1.ForwardRefExoticComponent<Omit<RadioGroupPrimitive.RadioGroupItemProps & React$1.RefAttributes<HTMLButtonElement>, "ref"> & React$1.RefAttributes<HTMLButtonElement>>;
|
|
943
945
|
|
|
944
946
|
declare const ResizablePanelGroup: ({ className, ...props }: React$1.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => React$1.JSX.Element;
|
|
945
|
-
declare const ResizablePanel: React$1.ForwardRefExoticComponent<Omit<React$1.HTMLAttributes<
|
|
947
|
+
declare const ResizablePanel: React$1.ForwardRefExoticComponent<Omit<React$1.HTMLAttributes<HTMLDivElement | HTMLElement | HTMLButtonElement | HTMLOListElement | HTMLLIElement | HTMLAnchorElement | HTMLSpanElement | HTMLHeadingElement | HTMLParagraphElement | HTMLLabelElement | HTMLInputElement | HTMLUListElement | HTMLObjectElement | HTMLAreaElement | HTMLAudioElement | HTMLBaseElement | HTMLQuoteElement | HTMLBodyElement | HTMLBRElement | HTMLCanvasElement | HTMLTableCaptionElement | HTMLTableColElement | HTMLDataElement | HTMLDataListElement | HTMLModElement | HTMLDetailsElement | HTMLDialogElement | HTMLDListElement | HTMLEmbedElement | HTMLFieldSetElement | HTMLFormElement | HTMLHeadElement | HTMLHRElement | HTMLHtmlElement | HTMLIFrameElement | HTMLImageElement | HTMLLegendElement | HTMLLinkElement | HTMLMapElement | HTMLMenuElement | HTMLMetaElement | HTMLMeterElement | HTMLOptGroupElement | HTMLOptionElement | HTMLOutputElement | HTMLPictureElement | HTMLPreElement | HTMLProgressElement | HTMLScriptElement | HTMLSelectElement | HTMLSlotElement | HTMLSourceElement | HTMLStyleElement | HTMLTableElement | HTMLTableSectionElement | HTMLTableCellElement | HTMLTemplateElement | HTMLTextAreaElement | HTMLTimeElement | HTMLTitleElement | HTMLTableRowElement | HTMLTrackElement | HTMLVideoElement>, "id" | "onResize"> & {
|
|
946
948
|
className?: string;
|
|
947
949
|
collapsedSize?: number | undefined;
|
|
948
950
|
collapsible?: boolean | undefined;
|
|
@@ -1097,9 +1099,9 @@ declare const TabsTrigger: React$1.ForwardRefExoticComponent<Omit<TabsPrimitive.
|
|
|
1097
1099
|
declare const TabsContent: React$1.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
1098
1100
|
|
|
1099
1101
|
declare const textareaVariants: (props?: ({
|
|
1100
|
-
variant?: "
|
|
1101
|
-
size?: "
|
|
1102
|
-
radius?: "
|
|
1102
|
+
variant?: "default" | "filled" | "borderless" | null | undefined;
|
|
1103
|
+
size?: "default" | "small" | "large" | null | undefined;
|
|
1104
|
+
radius?: "default" | "small" | "large" | "full" | null | undefined;
|
|
1103
1105
|
resize?: "default" | "both" | "horizontal" | "vertical" | "vertical-limited" | null | undefined;
|
|
1104
1106
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
1105
1107
|
interface TextareaProps extends React$1.ComponentProps<'textarea'>, VariantProps<typeof textareaVariants> {
|