lecom-ui 5.2.88 → 5.2.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/components/Calendar/Calendar.js +380 -0
- package/dist/components/Collapse/Collapse.js +94 -0
- package/dist/components/Combobox/Combobox.js +128 -0
- package/dist/components/CustomDivider/CustomDivider.js +234 -0
- package/dist/components/DataTable/DataTable.utils.js +3 -10
- package/dist/components/DataTable/Table.js +2 -1
- package/dist/components/DatePicker/DatePicker.js +55 -0
- package/dist/components/Pagination/Pagination.js +3 -2
- package/dist/components/Sheet/Sheet.js +31 -1
- package/dist/components/Steps/Steps.js +102 -0
- package/dist/components/Switch/Switch.js +42 -6
- package/dist/components/TagInput/TagInput.js +106 -0
- package/dist/index.d.ts +152 -11
- package/dist/index.js +10 -0
- package/dist/plugin/extend.js +78 -78
- package/dist/plugin/fontFaces.js +172 -172
- package/dist/plugin/general.js +12 -12
- package/dist/plugin/pluginDev.cjs +5 -5
- package/dist/plugin/pluginNext.cjs +5 -5
- package/dist/plugin/pluginNextTurbo.cjs +5 -5
- package/dist/plugin/pluginVite.cjs +5 -5
- package/dist/plugin/template.js +31 -31
- package/dist/plugin/typographies.js +152 -152
- package/dist/plugin/varsTheme.js +79 -79
- package/dist/style.min.css +1 -1
- package/package.json +10 -5
package/README.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
lecom-ui
|
|
1
|
+
lecom-ui
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { DayPicker, useDayPicker, labelPrevious, labelNext } from 'react-day-picker';
|
|
3
|
+
import { buttonVariants, Button } from '../Button/Button.js';
|
|
4
|
+
import { cn } from '../../lib/utils.js';
|
|
5
|
+
import { differenceInCalendarDays } from 'date-fns';
|
|
6
|
+
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|
7
|
+
|
|
8
|
+
function Calendar({
|
|
9
|
+
className,
|
|
10
|
+
showOutsideDays = true,
|
|
11
|
+
showYearSwitcher = true,
|
|
12
|
+
yearRange = 12,
|
|
13
|
+
numberOfMonths,
|
|
14
|
+
components,
|
|
15
|
+
...props
|
|
16
|
+
}) {
|
|
17
|
+
const [navView, setNavView] = React.useState("days");
|
|
18
|
+
const [displayYears, setDisplayYears] = React.useState(
|
|
19
|
+
React.useMemo(() => {
|
|
20
|
+
const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
|
|
21
|
+
return {
|
|
22
|
+
from: currentYear - Math.floor(yearRange / 2 - 1),
|
|
23
|
+
to: currentYear + Math.ceil(yearRange / 2)
|
|
24
|
+
};
|
|
25
|
+
}, [yearRange])
|
|
26
|
+
);
|
|
27
|
+
const { onNextClick, onPrevClick, startMonth, endMonth } = props;
|
|
28
|
+
const columnsDisplayed = navView === "years" ? 1 : numberOfMonths;
|
|
29
|
+
const _monthsClassName = cn("relative flex", props.monthsClassName);
|
|
30
|
+
const _monthCaptionClassName = cn(
|
|
31
|
+
"relative mx-10 flex h-7 items-center justify-center",
|
|
32
|
+
props.monthCaptionClassName
|
|
33
|
+
);
|
|
34
|
+
const _weekdaysClassName = cn("flex flex-row", props.weekdaysClassName);
|
|
35
|
+
const _weekdayClassName = cn(
|
|
36
|
+
"w-8 text-sm font-normal text-muted-foreground",
|
|
37
|
+
props.weekdayClassName
|
|
38
|
+
);
|
|
39
|
+
const _monthClassName = cn("w-full", props.monthClassName);
|
|
40
|
+
const _captionClassName = cn(
|
|
41
|
+
"relative flex items-center justify-center pt-1",
|
|
42
|
+
props.captionClassName
|
|
43
|
+
);
|
|
44
|
+
const _captionLabelClassName = cn(
|
|
45
|
+
"truncate text-sm font-medium",
|
|
46
|
+
props.captionLabelClassName
|
|
47
|
+
);
|
|
48
|
+
const buttonNavClassName = buttonVariants({
|
|
49
|
+
variant: "outlined",
|
|
50
|
+
className: "absolute h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"
|
|
51
|
+
});
|
|
52
|
+
const _buttonNextClassName = cn(
|
|
53
|
+
buttonNavClassName,
|
|
54
|
+
"right-0",
|
|
55
|
+
props.buttonNextClassName
|
|
56
|
+
);
|
|
57
|
+
const _buttonPreviousClassName = cn(
|
|
58
|
+
buttonNavClassName,
|
|
59
|
+
"left-0",
|
|
60
|
+
props.buttonPreviousClassName
|
|
61
|
+
);
|
|
62
|
+
const _navClassName = cn("flex items-start", props.navClassName);
|
|
63
|
+
const _monthGridClassName = cn("mx-auto mt-4", props.monthGridClassName);
|
|
64
|
+
const _weekClassName = cn("mt-2 flex w-max items-start", props.weekClassName);
|
|
65
|
+
const _dayClassName = cn(
|
|
66
|
+
"flex size-8 flex-1 items-center justify-center p-0 text-sm",
|
|
67
|
+
props.dayClassName
|
|
68
|
+
);
|
|
69
|
+
const _dayButtonClassName = cn(
|
|
70
|
+
buttonVariants({ variant: "ghost" }),
|
|
71
|
+
"size-8 rounded-md p-0 font-normal transition-none aria-selected:opacity-100",
|
|
72
|
+
props.dayButtonClassName
|
|
73
|
+
);
|
|
74
|
+
const buttonRangeClassName = "bg-accent [&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground";
|
|
75
|
+
const _rangeStartClassName = cn(
|
|
76
|
+
buttonRangeClassName,
|
|
77
|
+
"day-range-start rounded-s-md",
|
|
78
|
+
props.rangeStartClassName
|
|
79
|
+
);
|
|
80
|
+
const _rangeEndClassName = cn(
|
|
81
|
+
buttonRangeClassName,
|
|
82
|
+
"day-range-end rounded-e-md",
|
|
83
|
+
props.rangeEndClassName
|
|
84
|
+
);
|
|
85
|
+
const _rangeMiddleClassName = cn(
|
|
86
|
+
"bg-accent !text-foreground [&>button]:bg-transparent [&>button]:!text-foreground [&>button]:hover:bg-transparent [&>button]:hover:!text-foreground",
|
|
87
|
+
props.rangeMiddleClassName
|
|
88
|
+
);
|
|
89
|
+
const _selectedClassName = cn(
|
|
90
|
+
"[&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground",
|
|
91
|
+
props.selectedClassName
|
|
92
|
+
);
|
|
93
|
+
const _todayClassName = cn(
|
|
94
|
+
"[&>button]:bg-accent [&>button]:text-accent-foreground",
|
|
95
|
+
props.todayClassName
|
|
96
|
+
);
|
|
97
|
+
const _outsideClassName = cn(
|
|
98
|
+
"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
|
|
99
|
+
props.outsideClassName
|
|
100
|
+
);
|
|
101
|
+
const _disabledClassName = cn(
|
|
102
|
+
"text-muted-foreground opacity-50",
|
|
103
|
+
props.disabledClassName
|
|
104
|
+
);
|
|
105
|
+
const _hiddenClassName = cn("invisible flex-1", props.hiddenClassName);
|
|
106
|
+
return /* @__PURE__ */ React.createElement(
|
|
107
|
+
DayPicker,
|
|
108
|
+
{
|
|
109
|
+
showOutsideDays,
|
|
110
|
+
className: cn("p-3", className),
|
|
111
|
+
style: {
|
|
112
|
+
width: 248.8 * (columnsDisplayed ?? 1) + "px"
|
|
113
|
+
},
|
|
114
|
+
classNames: {
|
|
115
|
+
months: _monthsClassName,
|
|
116
|
+
month_caption: _monthCaptionClassName,
|
|
117
|
+
weekdays: _weekdaysClassName,
|
|
118
|
+
weekday: _weekdayClassName,
|
|
119
|
+
month: _monthClassName,
|
|
120
|
+
caption: _captionClassName,
|
|
121
|
+
caption_label: _captionLabelClassName,
|
|
122
|
+
button_next: _buttonNextClassName,
|
|
123
|
+
button_previous: _buttonPreviousClassName,
|
|
124
|
+
nav: _navClassName,
|
|
125
|
+
month_grid: _monthGridClassName,
|
|
126
|
+
week: _weekClassName,
|
|
127
|
+
day: _dayClassName,
|
|
128
|
+
day_button: _dayButtonClassName,
|
|
129
|
+
range_start: _rangeStartClassName,
|
|
130
|
+
range_middle: _rangeMiddleClassName,
|
|
131
|
+
range_end: _rangeEndClassName,
|
|
132
|
+
selected: _selectedClassName,
|
|
133
|
+
today: _todayClassName,
|
|
134
|
+
outside: _outsideClassName,
|
|
135
|
+
disabled: _disabledClassName,
|
|
136
|
+
hidden: _hiddenClassName
|
|
137
|
+
},
|
|
138
|
+
components: {
|
|
139
|
+
Chevron: ({ orientation }) => {
|
|
140
|
+
const Icon = orientation === "left" ? ChevronLeft : ChevronRight;
|
|
141
|
+
return /* @__PURE__ */ React.createElement(Icon, { className: "h-4 w-4" });
|
|
142
|
+
},
|
|
143
|
+
Nav: ({ className: className2 }) => /* @__PURE__ */ React.createElement(
|
|
144
|
+
Nav,
|
|
145
|
+
{
|
|
146
|
+
className: className2,
|
|
147
|
+
displayYears,
|
|
148
|
+
navView,
|
|
149
|
+
setDisplayYears,
|
|
150
|
+
startMonth,
|
|
151
|
+
endMonth,
|
|
152
|
+
onPrevClick,
|
|
153
|
+
onNextClick
|
|
154
|
+
}
|
|
155
|
+
),
|
|
156
|
+
CaptionLabel: (props2) => /* @__PURE__ */ React.createElement(
|
|
157
|
+
CaptionLabel,
|
|
158
|
+
{
|
|
159
|
+
showYearSwitcher,
|
|
160
|
+
navView,
|
|
161
|
+
setNavView,
|
|
162
|
+
displayYears,
|
|
163
|
+
...props2
|
|
164
|
+
}
|
|
165
|
+
),
|
|
166
|
+
MonthGrid: ({ className: className2, children, ...props2 }) => /* @__PURE__ */ React.createElement(
|
|
167
|
+
MonthGrid,
|
|
168
|
+
{
|
|
169
|
+
className: className2,
|
|
170
|
+
displayYears,
|
|
171
|
+
startMonth,
|
|
172
|
+
endMonth,
|
|
173
|
+
navView,
|
|
174
|
+
setNavView,
|
|
175
|
+
...props2
|
|
176
|
+
},
|
|
177
|
+
children
|
|
178
|
+
),
|
|
179
|
+
...components
|
|
180
|
+
},
|
|
181
|
+
numberOfMonths: columnsDisplayed,
|
|
182
|
+
...props
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
Calendar.displayName = "Calendar";
|
|
187
|
+
function Nav({
|
|
188
|
+
className,
|
|
189
|
+
navView,
|
|
190
|
+
startMonth,
|
|
191
|
+
endMonth,
|
|
192
|
+
displayYears,
|
|
193
|
+
setDisplayYears,
|
|
194
|
+
onPrevClick,
|
|
195
|
+
onNextClick
|
|
196
|
+
}) {
|
|
197
|
+
const { nextMonth, previousMonth, goToMonth } = useDayPicker();
|
|
198
|
+
const isPreviousDisabled = (() => {
|
|
199
|
+
if (navView === "years") {
|
|
200
|
+
return startMonth && differenceInCalendarDays(
|
|
201
|
+
new Date(displayYears.from - 1, 0, 1),
|
|
202
|
+
startMonth
|
|
203
|
+
) < 0 || endMonth && differenceInCalendarDays(
|
|
204
|
+
new Date(displayYears.from - 1, 0, 1),
|
|
205
|
+
endMonth
|
|
206
|
+
) > 0;
|
|
207
|
+
}
|
|
208
|
+
return !previousMonth;
|
|
209
|
+
})();
|
|
210
|
+
const isNextDisabled = (() => {
|
|
211
|
+
if (navView === "years") {
|
|
212
|
+
return startMonth && differenceInCalendarDays(
|
|
213
|
+
new Date(displayYears.to + 1, 0, 1),
|
|
214
|
+
startMonth
|
|
215
|
+
) < 0 || endMonth && differenceInCalendarDays(
|
|
216
|
+
new Date(displayYears.to + 1, 0, 1),
|
|
217
|
+
endMonth
|
|
218
|
+
) > 0;
|
|
219
|
+
}
|
|
220
|
+
return !nextMonth;
|
|
221
|
+
})();
|
|
222
|
+
const handlePreviousClick = React.useCallback(() => {
|
|
223
|
+
if (!previousMonth) return;
|
|
224
|
+
if (navView === "years") {
|
|
225
|
+
setDisplayYears((prev) => ({
|
|
226
|
+
from: prev.from - (prev.to - prev.from + 1),
|
|
227
|
+
to: prev.to - (prev.to - prev.from + 1)
|
|
228
|
+
}));
|
|
229
|
+
onPrevClick?.(
|
|
230
|
+
new Date(
|
|
231
|
+
displayYears.from - (displayYears.to - displayYears.from),
|
|
232
|
+
0,
|
|
233
|
+
1
|
|
234
|
+
)
|
|
235
|
+
);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
goToMonth(previousMonth);
|
|
239
|
+
onPrevClick?.(previousMonth);
|
|
240
|
+
}, [previousMonth, goToMonth]);
|
|
241
|
+
const handleNextClick = React.useCallback(() => {
|
|
242
|
+
if (!nextMonth) return;
|
|
243
|
+
if (navView === "years") {
|
|
244
|
+
setDisplayYears((prev) => ({
|
|
245
|
+
from: prev.from + (prev.to - prev.from + 1),
|
|
246
|
+
to: prev.to + (prev.to - prev.from + 1)
|
|
247
|
+
}));
|
|
248
|
+
onNextClick?.(
|
|
249
|
+
new Date(
|
|
250
|
+
displayYears.from + (displayYears.to - displayYears.from),
|
|
251
|
+
0,
|
|
252
|
+
1
|
|
253
|
+
)
|
|
254
|
+
);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
goToMonth(nextMonth);
|
|
258
|
+
onNextClick?.(nextMonth);
|
|
259
|
+
}, [goToMonth, nextMonth]);
|
|
260
|
+
return /* @__PURE__ */ React.createElement("nav", { className: cn("flex items-center", className) }, /* @__PURE__ */ React.createElement(
|
|
261
|
+
Button,
|
|
262
|
+
{
|
|
263
|
+
variant: "outlined",
|
|
264
|
+
className: "absolute left-0 h-7 w-7 bg-transparent p-0 opacity-80 hover:opacity-100",
|
|
265
|
+
type: "button",
|
|
266
|
+
tabIndex: isPreviousDisabled ? void 0 : -1,
|
|
267
|
+
disabled: isPreviousDisabled,
|
|
268
|
+
"aria-label": navView === "years" ? `Go to the previous ${displayYears.to - displayYears.from + 1} years` : labelPrevious(previousMonth),
|
|
269
|
+
onClick: handlePreviousClick
|
|
270
|
+
},
|
|
271
|
+
/* @__PURE__ */ React.createElement(ChevronLeft, { className: "h-4 w-4" })
|
|
272
|
+
), /* @__PURE__ */ React.createElement(
|
|
273
|
+
Button,
|
|
274
|
+
{
|
|
275
|
+
variant: "outlined",
|
|
276
|
+
className: "absolute right-0 h-7 w-7 bg-transparent p-0 opacity-80 hover:opacity-100",
|
|
277
|
+
type: "button",
|
|
278
|
+
tabIndex: isNextDisabled ? void 0 : -1,
|
|
279
|
+
disabled: isNextDisabled,
|
|
280
|
+
"aria-label": navView === "years" ? `Go to the next ${displayYears.to - displayYears.from + 1} years` : labelNext(nextMonth),
|
|
281
|
+
onClick: handleNextClick
|
|
282
|
+
},
|
|
283
|
+
/* @__PURE__ */ React.createElement(ChevronRight, { className: "h-4 w-4" })
|
|
284
|
+
));
|
|
285
|
+
}
|
|
286
|
+
function CaptionLabel({
|
|
287
|
+
children,
|
|
288
|
+
showYearSwitcher,
|
|
289
|
+
navView,
|
|
290
|
+
setNavView,
|
|
291
|
+
displayYears,
|
|
292
|
+
...props
|
|
293
|
+
}) {
|
|
294
|
+
if (!showYearSwitcher) return /* @__PURE__ */ React.createElement("span", { ...props }, children);
|
|
295
|
+
return /* @__PURE__ */ React.createElement(
|
|
296
|
+
Button,
|
|
297
|
+
{
|
|
298
|
+
className: "h-7 w-full truncate text-sm font-medium",
|
|
299
|
+
variant: "ghost",
|
|
300
|
+
size: "small",
|
|
301
|
+
onClick: () => setNavView((prev) => prev === "days" ? "years" : "days")
|
|
302
|
+
},
|
|
303
|
+
navView === "days" ? children : displayYears.from + " - " + displayYears.to
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
function MonthGrid({
|
|
307
|
+
className,
|
|
308
|
+
children,
|
|
309
|
+
displayYears,
|
|
310
|
+
startMonth,
|
|
311
|
+
endMonth,
|
|
312
|
+
navView,
|
|
313
|
+
setNavView,
|
|
314
|
+
...props
|
|
315
|
+
}) {
|
|
316
|
+
if (navView === "years") {
|
|
317
|
+
return /* @__PURE__ */ React.createElement(
|
|
318
|
+
YearGrid,
|
|
319
|
+
{
|
|
320
|
+
displayYears,
|
|
321
|
+
startMonth,
|
|
322
|
+
endMonth,
|
|
323
|
+
setNavView,
|
|
324
|
+
navView,
|
|
325
|
+
className,
|
|
326
|
+
...props
|
|
327
|
+
}
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
return /* @__PURE__ */ React.createElement("table", { className, ...props }, children);
|
|
331
|
+
}
|
|
332
|
+
function YearGrid({
|
|
333
|
+
className,
|
|
334
|
+
displayYears,
|
|
335
|
+
startMonth,
|
|
336
|
+
endMonth,
|
|
337
|
+
setNavView,
|
|
338
|
+
navView,
|
|
339
|
+
...props
|
|
340
|
+
}) {
|
|
341
|
+
const { goToMonth, selected } = useDayPicker();
|
|
342
|
+
return /* @__PURE__ */ React.createElement("div", { className: cn("grid grid-cols-4 gap-y-2", className), ...props }, Array.from(
|
|
343
|
+
{ length: displayYears.to - displayYears.from + 1 },
|
|
344
|
+
(_, i) => {
|
|
345
|
+
const isBefore = differenceInCalendarDays(
|
|
346
|
+
new Date(displayYears.from + i, 11, 31),
|
|
347
|
+
startMonth
|
|
348
|
+
) < 0;
|
|
349
|
+
const isAfter = differenceInCalendarDays(
|
|
350
|
+
new Date(displayYears.from + i, 0, 0),
|
|
351
|
+
endMonth
|
|
352
|
+
) > 0;
|
|
353
|
+
const isDisabled = isBefore || isAfter;
|
|
354
|
+
return /* @__PURE__ */ React.createElement(
|
|
355
|
+
Button,
|
|
356
|
+
{
|
|
357
|
+
key: i,
|
|
358
|
+
className: cn(
|
|
359
|
+
"h-7 w-full text-sm font-normal text-foreground",
|
|
360
|
+
displayYears.from + i === (/* @__PURE__ */ new Date()).getFullYear() && "bg-accent font-medium text-accent-foreground"
|
|
361
|
+
),
|
|
362
|
+
variant: "ghost",
|
|
363
|
+
onClick: () => {
|
|
364
|
+
setNavView("days");
|
|
365
|
+
goToMonth(
|
|
366
|
+
new Date(
|
|
367
|
+
displayYears.from + i,
|
|
368
|
+
selected?.getMonth() ?? 0
|
|
369
|
+
)
|
|
370
|
+
);
|
|
371
|
+
},
|
|
372
|
+
disabled: navView === "years" ? isDisabled : void 0
|
|
373
|
+
},
|
|
374
|
+
displayYears.from + i
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
));
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export { Calendar };
|
|
@@ -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 };
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ChevronUpIcon, ChevronDownIcon } from 'lucide-react';
|
|
3
|
+
import { cn } from '../../lib/utils.js';
|
|
4
|
+
import { Button } from '../Button/Button.js';
|
|
5
|
+
import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../Command/Command.js';
|
|
6
|
+
import { Popover, PopoverTrigger, PopoverContent } from '../Popover/Popover.js';
|
|
7
|
+
import { Typography } from '../Typography/Typography.js';
|
|
8
|
+
|
|
9
|
+
function Combobox({
|
|
10
|
+
options,
|
|
11
|
+
value,
|
|
12
|
+
onChange,
|
|
13
|
+
placeholder = "Selecione...",
|
|
14
|
+
disabled = false,
|
|
15
|
+
notFoundContent = "Nenhuma op\xE7\xE3o encontrada.",
|
|
16
|
+
status = "default",
|
|
17
|
+
searchTerm = "Pesquisar...",
|
|
18
|
+
triggerClassName,
|
|
19
|
+
contentClassName
|
|
20
|
+
}) {
|
|
21
|
+
const [open, setOpen] = React.useState(false);
|
|
22
|
+
const [search, setSearch] = React.useState("");
|
|
23
|
+
const filterOptions = React.useCallback(
|
|
24
|
+
(opts) => {
|
|
25
|
+
const searchLower = search.toLowerCase();
|
|
26
|
+
return opts.map((item) => {
|
|
27
|
+
if ("options" in item) {
|
|
28
|
+
const filtered = item.options.filter(
|
|
29
|
+
(opt) => opt.label.toLowerCase().includes(searchLower) || opt.value.toLowerCase().includes(searchLower)
|
|
30
|
+
);
|
|
31
|
+
if (!filtered.length) return null;
|
|
32
|
+
return { ...item, options: filtered };
|
|
33
|
+
}
|
|
34
|
+
return item.label.toLowerCase().includes(searchLower) || item.value.toLowerCase().includes(searchLower) ? item : null;
|
|
35
|
+
}).filter(Boolean);
|
|
36
|
+
},
|
|
37
|
+
[search]
|
|
38
|
+
);
|
|
39
|
+
const filteredOptions = React.useMemo(
|
|
40
|
+
() => !search ? options : filterOptions(options),
|
|
41
|
+
[options, search, filterOptions]
|
|
42
|
+
);
|
|
43
|
+
const selectedLabel = options.flatMap((opt) => "options" in opt ? opt.options : [opt]).find((opt) => opt.value === value)?.label || placeholder;
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
if (!open) setSearch("");
|
|
46
|
+
}, [open]);
|
|
47
|
+
return /* @__PURE__ */ React.createElement(Popover, { open, onOpenChange: setOpen }, /* @__PURE__ */ React.createElement(PopoverTrigger, { asChild: true, className: cn(contentClassName) }, /* @__PURE__ */ React.createElement(
|
|
48
|
+
Button,
|
|
49
|
+
{
|
|
50
|
+
type: "button",
|
|
51
|
+
role: "combobox",
|
|
52
|
+
"aria-expanded": open,
|
|
53
|
+
className: cn(
|
|
54
|
+
triggerClassName,
|
|
55
|
+
"w-full h-10 bg-white rounded-md px-3 text-left shadow-sm flex items-center justify-between transition",
|
|
56
|
+
status === "error" ? "border border-red-500 hover:ring-1 hover:ring-red-500 focus:ring-1 focus:ring-red-500" : "border border-gray-300 hover:ring-1 hover:ring-blue-600 focus:ring-1 focus:ring-blue-600",
|
|
57
|
+
!value && "text-gray-400",
|
|
58
|
+
disabled && "opacity-50 pointer-events-none",
|
|
59
|
+
"hover:bg-white focus:!bg-white active:!bg-white"
|
|
60
|
+
),
|
|
61
|
+
disabled
|
|
62
|
+
},
|
|
63
|
+
/* @__PURE__ */ React.createElement(
|
|
64
|
+
"span",
|
|
65
|
+
{
|
|
66
|
+
className: cn(
|
|
67
|
+
value ? "text-black" : "text-gray-400",
|
|
68
|
+
"font-normal truncate max-w-[calc(100%-2.5rem)]"
|
|
69
|
+
)
|
|
70
|
+
},
|
|
71
|
+
/* @__PURE__ */ React.createElement(Typography, { variant: "body-medium-400" }, selectedLabel)
|
|
72
|
+
),
|
|
73
|
+
open ? /* @__PURE__ */ React.createElement(
|
|
74
|
+
ChevronUpIcon,
|
|
75
|
+
{
|
|
76
|
+
className: "ml-2 h-4 w-4 shrink-0 text-gray-400",
|
|
77
|
+
color: "black"
|
|
78
|
+
}
|
|
79
|
+
) : /* @__PURE__ */ React.createElement(
|
|
80
|
+
ChevronDownIcon,
|
|
81
|
+
{
|
|
82
|
+
className: "ml-2 h-4 w-4 shrink-0 text-gray-400",
|
|
83
|
+
color: "black"
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
)), /* @__PURE__ */ React.createElement(PopoverContent, { className: "w-[var(--radix-popover-trigger-width)] p-0" }, /* @__PURE__ */ React.createElement(Command, null, /* @__PURE__ */ React.createElement(
|
|
87
|
+
CommandInput,
|
|
88
|
+
{
|
|
89
|
+
placeholder: searchTerm,
|
|
90
|
+
value: search,
|
|
91
|
+
onValueChange: setSearch
|
|
92
|
+
}
|
|
93
|
+
), /* @__PURE__ */ React.createElement(CommandList, null, /* @__PURE__ */ React.createElement(CommandEmpty, null, notFoundContent), filteredOptions.map(
|
|
94
|
+
(item, idx) => "options" in item ? /* @__PURE__ */ React.createElement(CommandGroup, { key: `${item.label}-${idx}`, heading: item.label }, item.options.map((opt) => /* @__PURE__ */ React.createElement(
|
|
95
|
+
CommandItem,
|
|
96
|
+
{
|
|
97
|
+
key: opt.value,
|
|
98
|
+
onSelect: () => {
|
|
99
|
+
if (opt.disabled) return;
|
|
100
|
+
onChange(opt.value === value ? null : opt.value);
|
|
101
|
+
setOpen(false);
|
|
102
|
+
},
|
|
103
|
+
className: cn(
|
|
104
|
+
opt.value === value ? "bg-blue-100 font-semibold text-black" : "hover:bg-gray-100",
|
|
105
|
+
opt.disabled && "opacity-50 pointer-events-none"
|
|
106
|
+
)
|
|
107
|
+
},
|
|
108
|
+
opt.label
|
|
109
|
+
))) : /* @__PURE__ */ React.createElement(
|
|
110
|
+
CommandItem,
|
|
111
|
+
{
|
|
112
|
+
key: item.value,
|
|
113
|
+
onSelect: () => {
|
|
114
|
+
if (item.disabled) return;
|
|
115
|
+
onChange(item.value === value ? null : item.value);
|
|
116
|
+
setOpen(false);
|
|
117
|
+
},
|
|
118
|
+
className: cn(
|
|
119
|
+
item.value === value ? "bg-blue-100 font-semibold text-black" : "hover:bg-gray-100",
|
|
120
|
+
item.disabled && "opacity-50 pointer-events-none"
|
|
121
|
+
)
|
|
122
|
+
},
|
|
123
|
+
item.label
|
|
124
|
+
)
|
|
125
|
+
)))));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export { Combobox };
|