lecom-ui 5.3.69 → 5.3.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1 +1 @@
1
- lecom-ui
1
+ lecom-ui
@@ -0,0 +1,94 @@
1
+ import * as React from 'react';
2
+ import { cn } from '../../lib/utils.js';
3
+ import * as AccordionPrimitive from '@radix-ui/react-accordion';
4
+ import { cva } from 'class-variance-authority';
5
+ import { ChevronRight } from 'lucide-react';
6
+
7
+ const collapseTriggerVariants = cva(
8
+ "flex items-center justify-between w-full transition-all text-left outline-none data-[state=open]:font-semibold",
9
+ {
10
+ variants: {
11
+ size: {
12
+ small: "text-sm py-1.5 px-4 min-h-8",
13
+ medium: "text-base py-2.5 px-4 min-h-10",
14
+ large: "text-lg py-3 px-4 min-h-12"
15
+ },
16
+ ghost: {
17
+ true: "bg-transparent border-none",
18
+ false: "border-t-none border-grey-400"
19
+ }
20
+ },
21
+ defaultVariants: {
22
+ size: "large",
23
+ ghost: false
24
+ }
25
+ }
26
+ );
27
+ const CollapseRoot = AccordionPrimitive.Root;
28
+ const CollapseItem = AccordionPrimitive.Item;
29
+ const CollapsePanel = React.forwardRef(
30
+ ({
31
+ header,
32
+ children,
33
+ extra,
34
+ expandIconPosition = "start",
35
+ size = "large",
36
+ ghost = false,
37
+ disabled = false,
38
+ className,
39
+ ...props
40
+ }, ref) => /* @__PURE__ */ React.createElement(
41
+ CollapseItem,
42
+ {
43
+ ref,
44
+ ...props,
45
+ className: cn(
46
+ "group w-full",
47
+ disabled && "pointer-events-none opacity-50",
48
+ className
49
+ )
50
+ },
51
+ /* @__PURE__ */ React.createElement(AccordionPrimitive.Header, { asChild: true }, /* @__PURE__ */ React.createElement(
52
+ AccordionPrimitive.Trigger,
53
+ {
54
+ disabled,
55
+ className: cn(
56
+ collapseTriggerVariants({ size, ghost }),
57
+ "flex gap-2 items-center text-left font-normal"
58
+ )
59
+ },
60
+ /* @__PURE__ */ React.createElement(
61
+ "div",
62
+ {
63
+ className: cn(
64
+ "flex flex-1 items-center justify-between gap-4 w-full",
65
+ expandIconPosition === "end" ? "flex-row-reverse" : ""
66
+ )
67
+ },
68
+ /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 truncate" }, /* @__PURE__ */ React.createElement(
69
+ "span",
70
+ {
71
+ className: "flex items-center justify-center flex-shrink-0 min-w-4 min-h-4 transition-transform duration-300 group-data-[state=open]:rotate-90 text-grey-700 text-lg select-none font-normal"
72
+ },
73
+ /* @__PURE__ */ React.createElement(ChevronRight, { className: "size-4" })
74
+ ), /* @__PURE__ */ React.createElement("span", { className: "font-normal" }, header)),
75
+ extra && /* @__PURE__ */ React.createElement("div", { className: "text-sm text-grey-500" }, extra)
76
+ )
77
+ )),
78
+ /* @__PURE__ */ React.createElement(
79
+ AccordionPrimitive.Content,
80
+ {
81
+ className: cn(
82
+ "overflow-hidden data-[state=open]:animate-accordion-down data-[state=closed]:animate-accordion-up"
83
+ )
84
+ },
85
+ /* @__PURE__ */ React.createElement("div", { className: "text-sm text-grey-800 pt-2 pb-4 px-4" }, children)
86
+ )
87
+ )
88
+ );
89
+ CollapsePanel.displayName = "CollapsePanel";
90
+ const Collapse = Object.assign(CollapseRoot, {
91
+ Panel: CollapsePanel
92
+ });
93
+
94
+ export { Collapse, collapseTriggerVariants };
@@ -22,19 +22,21 @@ const SEARCH_INPUT_CLASSES = {
22
22
  large: "[&_[cmdk-input]]:h-9 [&_[cmdk-input]]:body-large-400 [&_svg]:text-grey-800 [&_svg]:opacity-100 [&_svg]:h-4 [&_svg]:w-4"
23
23
  };
24
24
  const isComboboxGroup = (item) => "options" in item && Array.isArray(item.options);
25
- const matchesSearch = (text, searchTerm) => text.toLowerCase().includes(searchTerm);
26
- const filterOption = (option, searchLower) => matchesSearch(option.label, searchLower) || matchesSearch(option.value, searchLower);
27
- const filterComboboxOptions = (opts, searchLower) => {
28
- if (!searchLower.trim()) return opts;
25
+ const normalize = (s) => s.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim();
26
+ const matchesSearch = (text, searchTerm) => normalize(text).includes(normalize(searchTerm));
27
+ const filterOption = (option, search) => matchesSearch(option.label, search) || matchesSearch(option.value, search);
28
+ const filterComboboxOptions = (opts, search) => {
29
+ const normalizedSearch = normalize(search);
30
+ if (!normalizedSearch) return opts;
29
31
  return opts.reduce((acc, item) => {
30
32
  if (isComboboxGroup(item)) {
31
33
  const filteredOptions = item.options.filter(
32
- (opt) => filterOption(opt, searchLower)
34
+ (opt) => filterOption(opt, normalizedSearch)
33
35
  );
34
36
  if (filteredOptions.length > 0) {
35
37
  acc.push({ ...item, options: filteredOptions });
36
38
  }
37
- } else if (filterOption(item, searchLower)) {
39
+ } else if (filterOption(item, normalizedSearch)) {
38
40
  acc.push(item);
39
41
  }
40
42
  return acc;
@@ -90,11 +92,14 @@ const ComboboxItemContent = ({
90
92
  const checkIconSize = CHECK_ICON_SIZES[size];
91
93
  const isDisabled = option.disabled || false;
92
94
  const textColor = isDisabled ? "text-grey-400" : "text-grey-800";
95
+ const isSelected = option.value === value;
93
96
  return /* @__PURE__ */ React.createElement(
94
97
  CommandItem,
95
98
  {
96
99
  key: option.value,
97
100
  onSelect: handleSelect,
101
+ "data-combobox-value": option.value,
102
+ tabIndex: isSelected ? 0 : -1,
98
103
  className: cn(
99
104
  comboboxItemVariants({
100
105
  size,
@@ -258,8 +263,9 @@ function Combobox({
258
263
  }) {
259
264
  const [open, setOpen] = React.useState(false);
260
265
  const [search, setSearch] = React.useState("");
266
+ const commandListRef = React.useRef(null);
261
267
  const filteredOptions = React.useMemo(
262
- () => !search ? options : filterComboboxOptions(options, search.toLowerCase()),
268
+ () => !search ? options : filterComboboxOptions(options, search),
263
269
  [options, search]
264
270
  );
265
271
  const selectedOption = React.useMemo(
@@ -271,6 +277,19 @@ function Combobox({
271
277
  const handleClose = React.useCallback(() => {
272
278
  setOpen(false);
273
279
  }, []);
280
+ React.useEffect(() => {
281
+ if (!open) return;
282
+ if (!value) return;
283
+ requestAnimationFrame(() => {
284
+ const el = commandListRef.current?.querySelector(
285
+ `[data-combobox-value="${value}"]`
286
+ );
287
+ if (el) {
288
+ el.focus();
289
+ el.scrollIntoView({ block: "nearest" });
290
+ }
291
+ });
292
+ }, [open, value]);
274
293
  React.useEffect(() => {
275
294
  if (!open) {
276
295
  setSearch("");
@@ -308,6 +327,8 @@ function Combobox({
308
327
  ), /* @__PURE__ */ React.createElement(
309
328
  CommandList,
310
329
  {
330
+ ref: commandListRef,
331
+ key: search,
311
332
  className: cn(
312
333
  "max-h-44 overflow-y-auto overflow-x-hidden",
313
334
  "[&::-webkit-scrollbar]:w-1.5",
@@ -9,22 +9,28 @@ const NumberControl = ({
9
9
  label,
10
10
  value,
11
11
  onChange,
12
- placeholder = "",
12
+ placeholder,
13
13
  required = false,
14
- min = 0,
14
+ min,
15
+ max,
16
+ maxDigits,
15
17
  className = "",
16
18
  labelClassName = "",
17
19
  info = false,
18
20
  labelPosition = "top"
19
21
  }) => {
22
+ const defaultPlaceholder = maxDigits ? "0".repeat(maxDigits) : "0";
23
+ const finalPlaceholder = placeholder ?? defaultPlaceholder;
20
24
  const handleIncrement = () => {
21
- const current = parseInt(value, 10) || 0;
22
- const newValue = (current + 1).toString();
23
- onChange(newValue);
25
+ const current = typeof value === "number" ? value : parseInt(value, 10) || 0;
26
+ if (max === void 0 || current < max) {
27
+ const newValue = (current + 1).toString();
28
+ onChange(newValue);
29
+ }
24
30
  };
25
31
  const handleDecrement = () => {
26
- const current = parseInt(value, 10) || 0;
27
- if (current > min) {
32
+ const current = typeof value === "number" ? value : parseInt(value, 10) || 0;
33
+ if (min === void 0 || current > min) {
28
34
  const newValue = (current - 1).toString();
29
35
  onChange(newValue);
30
36
  }
@@ -35,8 +41,13 @@ const NumberControl = ({
35
41
  onChange("");
36
42
  return;
37
43
  }
44
+ if (maxDigits && numbersOnly.length > maxDigits) {
45
+ return;
46
+ }
38
47
  const numValue = parseInt(numbersOnly, 10);
39
- if (numValue >= min) {
48
+ const isAboveMin = min === void 0 || numValue >= min;
49
+ const isBelowMax = max === void 0 || numValue <= max;
50
+ if (isAboveMin && isBelowMax) {
40
51
  onChange(numbersOnly);
41
52
  }
42
53
  };
@@ -58,7 +69,7 @@ const NumberControl = ({
58
69
  onChange: (e) => handleInputChange(e.target.value),
59
70
  className: "text-center flex-1 px-10 w-full",
60
71
  containerClassName: "w-full",
61
- placeholder,
72
+ placeholder: finalPlaceholder,
62
73
  prefixInset: /* @__PURE__ */ React__default.createElement(
63
74
  Minus,
64
75
  {
package/dist/index.d.ts CHANGED
@@ -756,9 +756,9 @@ interface HeaderProps extends React$1.HTMLAttributes<HTMLElement>, VariantProps<
756
756
  }
757
757
 
758
758
  declare const inputVariants: (props?: ({
759
- variant?: "filled" | "default" | "borderless" | null | undefined;
760
- size?: "small" | "large" | "default" | null | undefined;
761
- radius?: "small" | "large" | "default" | "full" | null | undefined;
759
+ variant?: "default" | "filled" | "borderless" | null | undefined;
760
+ size?: "default" | "small" | "large" | null | undefined;
761
+ radius?: "default" | "small" | "large" | "full" | null | undefined;
762
762
  } & class_variance_authority_types.ClassProp) | undefined) => string;
763
763
  interface InputProps extends Omit<React$1.InputHTMLAttributes<HTMLInputElement>, 'size' | 'sufix' | 'prefix'>, VariantProps<typeof inputVariants> {
764
764
  sufix?: React$1.ReactNode;
@@ -939,17 +939,19 @@ declare function useNotificationToast(): {
939
939
 
940
940
  interface NumberControlProps {
941
941
  label: string;
942
- value: string;
942
+ value: string | number;
943
943
  onChange: (value: string) => void;
944
944
  placeholder?: string;
945
945
  required?: boolean;
946
946
  min?: number;
947
+ max?: number;
948
+ maxDigits?: number;
947
949
  className?: string;
948
950
  labelClassName?: string;
949
951
  info?: boolean;
950
952
  labelPosition?: 'top' | 'bottom';
951
953
  }
952
- declare const NumberControl: ({ label, value, onChange, placeholder, required, min, className, labelClassName, info, labelPosition, }: NumberControlProps) => React__default.JSX.Element;
954
+ declare const NumberControl: ({ label, value, onChange, placeholder, required, min, max, maxDigits, className, labelClassName, info, labelPosition, }: NumberControlProps) => React__default.JSX.Element;
953
955
 
954
956
  declare const Popover: React$1.FC<PopoverPrimitive.PopoverProps>;
955
957
  declare const PopoverTrigger: React$1.ForwardRefExoticComponent<PopoverPrimitive.PopoverTriggerProps & React$1.RefAttributes<HTMLButtonElement>>;
@@ -959,7 +961,7 @@ declare const RadioGroup: React$1.ForwardRefExoticComponent<Omit<RadioGroupPrimi
959
961
  declare const RadioGroupItem: React$1.ForwardRefExoticComponent<Omit<RadioGroupPrimitive.RadioGroupItemProps & React$1.RefAttributes<HTMLButtonElement>, "ref"> & React$1.RefAttributes<HTMLButtonElement>>;
960
962
 
961
963
  declare const ResizablePanelGroup: ({ className, ...props }: React$1.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => React$1.JSX.Element;
962
- declare const ResizablePanel: React$1.ForwardRefExoticComponent<Omit<React$1.HTMLAttributes<HTMLElement | HTMLOListElement | HTMLLIElement | HTMLAnchorElement | HTMLSpanElement | HTMLDivElement | HTMLButtonElement | 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"> & {
964
+ 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"> & {
963
965
  className?: string;
964
966
  collapsedSize?: number | undefined;
965
967
  collapsible?: boolean | undefined;
@@ -1124,10 +1126,10 @@ declare const TabsTrigger: React$1.ForwardRefExoticComponent<Omit<TabsPrimitive.
1124
1126
  declare const TabsContent: React$1.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
1125
1127
 
1126
1128
  declare const textareaVariants: (props?: ({
1127
- variant?: "filled" | "default" | "borderless" | null | undefined;
1128
- size?: "small" | "large" | "default" | null | undefined;
1129
- radius?: "small" | "large" | "default" | "full" | null | undefined;
1130
- resize?: "both" | "horizontal" | "vertical" | "default" | "vertical-limited" | null | undefined;
1129
+ variant?: "default" | "filled" | "borderless" | null | undefined;
1130
+ size?: "default" | "small" | "large" | null | undefined;
1131
+ radius?: "default" | "small" | "large" | "full" | null | undefined;
1132
+ resize?: "default" | "both" | "horizontal" | "vertical" | "vertical-limited" | null | undefined;
1131
1133
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1132
1134
  interface TextareaProps extends React$1.ComponentProps<'textarea'>, VariantProps<typeof textareaVariants> {
1133
1135
  }
@@ -1264,7 +1266,7 @@ declare const SheetClose: React$1.ForwardRefExoticComponent<DialogPrimitive.Dial
1264
1266
  declare const SheetPortal: React$1.FC<DialogPrimitive.DialogPortalProps>;
1265
1267
  declare const SheetOverlay: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
1266
1268
  declare const sheetVariants: (props?: ({
1267
- side?: "top" | "bottom" | "left" | "right" | null | undefined;
1269
+ side?: "left" | "right" | "top" | "bottom" | null | undefined;
1268
1270
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1269
1271
  interface SheetContentProps extends React$1.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>, VariantProps<typeof sheetVariants> {
1270
1272
  }
@@ -1,78 +1,78 @@
1
- const extend = {
2
- colors: {
3
- background: 'hsl(var(--background))',
4
- foreground: 'hsl(var(--foreground))',
5
- card: {
6
- DEFAULT: 'hsl(var(--card))',
7
- foreground: 'hsl(var(--card-foreground))',
8
- },
9
- popover: {
10
- DEFAULT: 'hsl(var(--popover))',
11
- foreground: 'hsl(var(--popover-foreground))',
12
- },
13
- primary: {
14
- DEFAULT: 'hsl(var(--primary))',
15
- foreground: 'hsl(var(--primary-foreground))',
16
- },
17
- secondary: {
18
- DEFAULT: 'hsl(var(--secondary))',
19
- foreground: 'hsl(var(--secondary-foreground))',
20
- },
21
- muted: {
22
- DEFAULT: 'hsl(var(--muted))',
23
- foreground: 'hsl(var(--muted-foreground))',
24
- },
25
- accent: {
26
- DEFAULT: 'hsl(var(--accent))',
27
- foreground: 'hsl(var(--accent-foreground))',
28
- },
29
- destructive: {
30
- DEFAULT: 'hsl(var(--destructive))',
31
- foreground: 'hsl(var(--destructive-foreground))',
32
- },
33
- border: 'hsl(var(--border))',
34
- input: 'hsl(var(--input))',
35
- ring: 'hsl(var(--ring))',
36
- chart: {
37
- 1: 'hsl(var(--chart-1))',
38
- 2: 'hsl(var(--chart-2))',
39
- 3: 'hsl(var(--chart-3))',
40
- 4: 'hsl(var(--chart-4))',
41
- 5: 'hsl(var(--chart-5))',
42
- 6: 'hsl(var(--chart-6))',
43
- 7: 'hsl(var(--chart-7))',
44
- 8: 'hsl(var(--chart-8))',
45
- },
46
- sidebar: {
47
- DEFAULT: 'hsl(var(--sidebar-background))',
48
- foreground: 'hsl(var(--sidebar-foreground))',
49
- primary: 'hsl(var(--sidebar-primary))',
50
- 'primary-foreground': 'hsl(var(--sidebar-primary-foreground))',
51
- accent: 'hsl(var(--sidebar-accent))',
52
- 'accent-foreground': 'hsl(var(--sidebar-accent-foreground))',
53
- border: 'hsl(var(--sidebar-border))',
54
- ring: 'hsl(var(--sidebar-ring))',
55
- },
56
- },
57
- borderRadius: {
58
- lg: 'var(--radius)',
59
- md: 'calc(var(--radius) - 2px)',
60
- sm: 'calc(var(--radius) - 4px)',
61
- },
62
- keyframes: {
63
- 'accordion-down': {
64
- from: { height: '0' },
65
- to: { height: 'var(--radix-accordion-content-height)' },
66
- },
67
- 'accordion-up': {
68
- from: { height: 'var(--radix-accordion-content-height)' },
69
- to: { height: '0' },
70
- },
71
- },
72
- animation: {
73
- 'accordion-down': 'accordion-down 0.2s ease-out',
74
- 'accordion-up': 'accordion-up 0.2s ease-out',
75
- },
76
- };
77
-
78
- export { extend };
1
+ const extend = {
2
+ colors: {
3
+ background: 'hsl(var(--background))',
4
+ foreground: 'hsl(var(--foreground))',
5
+ card: {
6
+ DEFAULT: 'hsl(var(--card))',
7
+ foreground: 'hsl(var(--card-foreground))',
8
+ },
9
+ popover: {
10
+ DEFAULT: 'hsl(var(--popover))',
11
+ foreground: 'hsl(var(--popover-foreground))',
12
+ },
13
+ primary: {
14
+ DEFAULT: 'hsl(var(--primary))',
15
+ foreground: 'hsl(var(--primary-foreground))',
16
+ },
17
+ secondary: {
18
+ DEFAULT: 'hsl(var(--secondary))',
19
+ foreground: 'hsl(var(--secondary-foreground))',
20
+ },
21
+ muted: {
22
+ DEFAULT: 'hsl(var(--muted))',
23
+ foreground: 'hsl(var(--muted-foreground))',
24
+ },
25
+ accent: {
26
+ DEFAULT: 'hsl(var(--accent))',
27
+ foreground: 'hsl(var(--accent-foreground))',
28
+ },
29
+ destructive: {
30
+ DEFAULT: 'hsl(var(--destructive))',
31
+ foreground: 'hsl(var(--destructive-foreground))',
32
+ },
33
+ border: 'hsl(var(--border))',
34
+ input: 'hsl(var(--input))',
35
+ ring: 'hsl(var(--ring))',
36
+ chart: {
37
+ 1: 'hsl(var(--chart-1))',
38
+ 2: 'hsl(var(--chart-2))',
39
+ 3: 'hsl(var(--chart-3))',
40
+ 4: 'hsl(var(--chart-4))',
41
+ 5: 'hsl(var(--chart-5))',
42
+ 6: 'hsl(var(--chart-6))',
43
+ 7: 'hsl(var(--chart-7))',
44
+ 8: 'hsl(var(--chart-8))',
45
+ },
46
+ sidebar: {
47
+ DEFAULT: 'hsl(var(--sidebar-background))',
48
+ foreground: 'hsl(var(--sidebar-foreground))',
49
+ primary: 'hsl(var(--sidebar-primary))',
50
+ 'primary-foreground': 'hsl(var(--sidebar-primary-foreground))',
51
+ accent: 'hsl(var(--sidebar-accent))',
52
+ 'accent-foreground': 'hsl(var(--sidebar-accent-foreground))',
53
+ border: 'hsl(var(--sidebar-border))',
54
+ ring: 'hsl(var(--sidebar-ring))',
55
+ },
56
+ },
57
+ borderRadius: {
58
+ lg: 'var(--radius)',
59
+ md: 'calc(var(--radius) - 2px)',
60
+ sm: 'calc(var(--radius) - 4px)',
61
+ },
62
+ keyframes: {
63
+ 'accordion-down': {
64
+ from: { height: '0' },
65
+ to: { height: 'var(--radix-accordion-content-height)' },
66
+ },
67
+ 'accordion-up': {
68
+ from: { height: 'var(--radix-accordion-content-height)' },
69
+ to: { height: '0' },
70
+ },
71
+ },
72
+ animation: {
73
+ 'accordion-down': 'accordion-down 0.2s ease-out',
74
+ 'accordion-up': 'accordion-up 0.2s ease-out',
75
+ },
76
+ };
77
+
78
+ export { extend };