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
- maxHeight = 320,
33
- groupedOptions
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(nl.slice(Math.max(0, idx - 1)))) score += 5;
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((a, b) => a.score === b.score ? a.idx - b.idx : a.score - b.score);
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((val) => {
211
- if (!treeOptions) return void 0;
212
- const stack = [...treeOptions];
213
- while (stack.length) {
214
- const n = stack.pop();
215
- if (n.value === val) return n.label;
216
- if (n.children) stack.push(...n.children);
217
- }
218
- return void 0;
219
- }, [treeOptions]);
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(new Set(norm(q).split(/\s+/).filter(Boolean))).sort((a, b) => b.length - a.length);
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) merged.push({ ...r });
273
- else merged[merged.length - 1].end = Math.max(merged[merged.length - 1].end, r.end);
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) parts.push(/* @__PURE__ */ React.createElement("span", { key: `t-${i}-pre` }, label.slice(cursor, r.start)));
279
- parts.push(/* @__PURE__ */ React.createElement("span", { key: `t-${i}-hl`, className: "bg-blue-100/60 text-grey-900 rounded-[2px] px-0.5" }, label.slice(r.start, r.end)));
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) parts.push(/* @__PURE__ */ React.createElement("span", { key: "t-last" }, label.slice(cursor)));
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(([categoryName, categoryOptions]) => {
429
- const filtered = categoryOptions.filter(
430
- (opt) => !query || effectiveOptions.some((eff) => eff.value === opt.value && filteredOptions.some((filt) => filt.value === opt.value))
431
- );
432
- if (!filtered.length) return null;
433
- 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) => {
434
- const isSelected = selectedValues.includes(option.value);
435
- return /* @__PURE__ */ React.createElement(
436
- CommandItem,
437
- {
438
- key: option.value,
439
- onSelect: () => toggleOption(option.value),
440
- className: "cursor-pointer"
441
- },
442
- /* @__PURE__ */ React.createElement(
443
- "div",
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
- className: cn(
446
- "flex h-4 w-4 items-center justify-center rounded-sm border-2 border-grey-400",
447
- isSelected ? "bg-blue-600 border-blue-600 text-primary-foreground" : "opacity-50 [&_svg]:invisible"
448
- )
473
+ key: option.value,
474
+ onSelect: () => toggleOption(option.value),
475
+ className: "cursor-pointer"
449
476
  },
450
- /* @__PURE__ */ React.createElement(Check, { className: "h-4 w-4" })
451
- ),
452
- /* @__PURE__ */ React.createElement("span", { className: "text-grey-800" }, highlight(option.label, query))
453
- );
454
- }));
455
- }) : filteredOptions.map((option) => {
456
- const isSelected = selectedValues.includes(option.value);
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("svg", { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, /* @__PURE__ */ React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, 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" })), /* @__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 acc += treeSelectionStrategy === "all" ? 1 + countAll(n.children) : countAll(n.children);
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?: "filled" | "default" | "borderless" | null | undefined;
759
- size?: "small" | "large" | "default" | null | undefined;
760
- radius?: "small" | "large" | "default" | "full" | null | undefined;
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<HTMLButtonElement | HTMLElement | HTMLDivElement | HTMLOListElement | HTMLLIElement | HTMLAnchorElement | HTMLSpanElement | HTMLHeadingElement | HTMLParagraphElement | HTMLInputElement | HTMLLabelElement | 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 | HTMLUListElement | HTMLVideoElement>, "id" | "onResize"> & {
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?: "filled" | "default" | "borderless" | null | undefined;
1101
- size?: "small" | "large" | "default" | null | undefined;
1102
- radius?: "small" | "large" | "default" | "full" | null | undefined;
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> {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lecom-ui",
3
- "version": "5.3.41",
3
+ "version": "5.3.43",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "module": "dist/index.js",