@algodomain/smart-forms 0.1.0

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.
@@ -0,0 +1,949 @@
1
+ import { useFormField, useFieldDetection, Label, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, cn, Input } from './chunk-IG4XDQMV.js';
2
+ import * as React4 from 'react';
3
+ import { useRef, useEffect, useMemo, useState } from 'react';
4
+ import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
5
+ import { InfoIcon, Calendar as Calendar$1, X, CheckIcon, CircleIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon } from 'lucide-react';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+ import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
8
+ import * as SelectPrimitive from '@radix-ui/react-select';
9
+ import { format } from 'date-fns';
10
+ import { Slot } from '@radix-ui/react-slot';
11
+ import { cva } from 'class-variance-authority';
12
+ import { getDefaultClassNames, DayPicker } from 'react-day-picker';
13
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
14
+
15
+ function Checkbox({
16
+ className,
17
+ ...props
18
+ }) {
19
+ return /* @__PURE__ */ jsx(
20
+ CheckboxPrimitive.Root,
21
+ {
22
+ "data-slot": "checkbox",
23
+ className: cn(
24
+ "peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
25
+ className
26
+ ),
27
+ ...props,
28
+ children: /* @__PURE__ */ jsx(
29
+ CheckboxPrimitive.Indicator,
30
+ {
31
+ "data-slot": "checkbox-indicator",
32
+ className: "flex items-center justify-center text-current transition-none",
33
+ children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-3.5" })
34
+ }
35
+ )
36
+ }
37
+ );
38
+ }
39
+ var SmartCheckbox = ({
40
+ field,
41
+ label,
42
+ className = "",
43
+ validation,
44
+ required = false,
45
+ defaultValue,
46
+ info,
47
+ subLabel
48
+ }) => {
49
+ const { value, error, onChange, fieldRef, registerValidation } = useFormField(field);
50
+ const fieldDetection = useFieldDetection();
51
+ const hasRegistered = useRef(false);
52
+ const hasSetDefault = useRef(false);
53
+ useEffect(() => {
54
+ if (validation && !hasRegistered.current) {
55
+ hasRegistered.current = true;
56
+ registerValidation(field, validation);
57
+ }
58
+ }, [validation, field, registerValidation]);
59
+ useEffect(() => {
60
+ if (fieldDetection?.registerField) {
61
+ fieldDetection.registerField(field);
62
+ }
63
+ }, [field, fieldDetection]);
64
+ useEffect(() => {
65
+ if (defaultValue !== void 0 && !hasSetDefault.current && (value === void 0 || value === null || value === "")) {
66
+ onChange(defaultValue);
67
+ hasSetDefault.current = true;
68
+ }
69
+ }, [defaultValue, value, onChange]);
70
+ return /* @__PURE__ */ jsxs("div", { className: `flex-1 min-w-0 ${className}`, children: [
71
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
72
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
73
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
74
+ /* @__PURE__ */ jsx(
75
+ Checkbox,
76
+ {
77
+ ref: fieldRef,
78
+ checked: value || false,
79
+ onCheckedChange: (checked) => onChange(!!checked),
80
+ className: error ? "border-destructive" : "",
81
+ "data-field": field,
82
+ id: `${field}-checkbox`
83
+ }
84
+ ),
85
+ /* @__PURE__ */ jsxs(Label, { htmlFor: `${field}-checkbox`, className: "text-sm font-normal cursor-pointer", children: [
86
+ label || field,
87
+ " ",
88
+ required && /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" })
89
+ ] })
90
+ ] }),
91
+ info && /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
92
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(InfoIcon, { className: "h-4 w-4 text-muted-foreground cursor-pointer mr-2" }) }),
93
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { className: "max-w-xs", children: info }) })
94
+ ] }) })
95
+ ] }),
96
+ subLabel && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground ml-6", children: subLabel })
97
+ ] }),
98
+ error && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm mt-1", children: error })
99
+ ] });
100
+ };
101
+ function RadioGroup({
102
+ className,
103
+ ...props
104
+ }) {
105
+ return /* @__PURE__ */ jsx(
106
+ RadioGroupPrimitive.Root,
107
+ {
108
+ "data-slot": "radio-group",
109
+ className: cn("grid gap-3", className),
110
+ ...props
111
+ }
112
+ );
113
+ }
114
+ function RadioGroupItem({
115
+ className,
116
+ ...props
117
+ }) {
118
+ return /* @__PURE__ */ jsx(
119
+ RadioGroupPrimitive.Item,
120
+ {
121
+ "data-slot": "radio-group-item",
122
+ className: cn(
123
+ "border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
124
+ className
125
+ ),
126
+ ...props,
127
+ children: /* @__PURE__ */ jsx(
128
+ RadioGroupPrimitive.Indicator,
129
+ {
130
+ "data-slot": "radio-group-indicator",
131
+ className: "relative flex items-center justify-center",
132
+ children: /* @__PURE__ */ jsx(CircleIcon, { className: "fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2" })
133
+ }
134
+ )
135
+ }
136
+ );
137
+ }
138
+ var SmartRadioGroup = ({
139
+ field,
140
+ label,
141
+ options,
142
+ name,
143
+ alignment = "vertical",
144
+ className = "",
145
+ validation,
146
+ required = false,
147
+ defaultValue,
148
+ info,
149
+ subLabel
150
+ }) => {
151
+ const { value, error, onChange, fieldRef, registerValidation } = useFormField(field);
152
+ const fieldDetection = useFieldDetection();
153
+ const hasRegistered = useRef(false);
154
+ const hasSetDefault = useRef(false);
155
+ useEffect(() => {
156
+ if (validation && !hasRegistered.current) {
157
+ hasRegistered.current = true;
158
+ registerValidation(field, validation);
159
+ }
160
+ }, [validation, field, registerValidation]);
161
+ useEffect(() => {
162
+ if (fieldDetection?.registerField) {
163
+ fieldDetection.registerField(field);
164
+ }
165
+ }, [field, fieldDetection]);
166
+ useEffect(() => {
167
+ if (defaultValue !== void 0 && !hasSetDefault.current && (value === void 0 || value === null || value === "")) {
168
+ onChange(defaultValue);
169
+ hasSetDefault.current = true;
170
+ }
171
+ }, [defaultValue, value, onChange]);
172
+ return /* @__PURE__ */ jsxs("div", { className: `flex-1 min-w-0 ${className}`, children: [
173
+ label && /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
174
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
175
+ /* @__PURE__ */ jsxs(Label, { className: "text-sm font-medium text-foreground", children: [
176
+ label,
177
+ " ",
178
+ required && /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" })
179
+ ] }),
180
+ info && /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
181
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(InfoIcon, { className: "h-4 w-4 text-muted-foreground cursor-pointer mr-2" }) }),
182
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { className: "max-w-xs", children: info }) })
183
+ ] }) })
184
+ ] }),
185
+ subLabel && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: subLabel })
186
+ ] }),
187
+ /* @__PURE__ */ jsx(
188
+ RadioGroup,
189
+ {
190
+ value: value || "",
191
+ onValueChange: (newValue) => onChange(newValue),
192
+ className: alignment === "horizontal" ? "flex flex-wrap gap-4" : "grid gap-3",
193
+ ref: fieldRef,
194
+ "data-field": field,
195
+ name: name || field,
196
+ children: options.map((option) => /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
197
+ /* @__PURE__ */ jsx(
198
+ RadioGroupItem,
199
+ {
200
+ value: option.value,
201
+ id: `${field}-${option.value}`
202
+ }
203
+ ),
204
+ /* @__PURE__ */ jsx(
205
+ Label,
206
+ {
207
+ htmlFor: `${field}-${option.value}`,
208
+ className: "text-sm font-normal cursor-pointer",
209
+ children: option.label
210
+ }
211
+ )
212
+ ] }, option.value))
213
+ }
214
+ ),
215
+ error && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm mt-1", children: error })
216
+ ] });
217
+ };
218
+ function Select({
219
+ ...props
220
+ }) {
221
+ return /* @__PURE__ */ jsx(SelectPrimitive.Root, { "data-slot": "select", ...props });
222
+ }
223
+ function SelectValue({
224
+ ...props
225
+ }) {
226
+ return /* @__PURE__ */ jsx(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
227
+ }
228
+ function SelectTrigger({
229
+ className,
230
+ size = "default",
231
+ children,
232
+ ...props
233
+ }) {
234
+ return /* @__PURE__ */ jsxs(
235
+ SelectPrimitive.Trigger,
236
+ {
237
+ "data-slot": "select-trigger",
238
+ "data-size": size,
239
+ className: cn(
240
+ "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
241
+ className
242
+ ),
243
+ ...props,
244
+ children: [
245
+ children,
246
+ /* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 opacity-50" }) })
247
+ ]
248
+ }
249
+ );
250
+ }
251
+ function SelectContent({
252
+ className,
253
+ children,
254
+ position = "popper",
255
+ ...props
256
+ }) {
257
+ return /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
258
+ SelectPrimitive.Content,
259
+ {
260
+ "data-slot": "select-content",
261
+ className: cn(
262
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
263
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
264
+ className
265
+ ),
266
+ position,
267
+ ...props,
268
+ children: [
269
+ /* @__PURE__ */ jsx(SelectScrollUpButton, {}),
270
+ /* @__PURE__ */ jsx(
271
+ SelectPrimitive.Viewport,
272
+ {
273
+ className: cn(
274
+ "p-1",
275
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
276
+ ),
277
+ children
278
+ }
279
+ ),
280
+ /* @__PURE__ */ jsx(SelectScrollDownButton, {})
281
+ ]
282
+ }
283
+ ) });
284
+ }
285
+ function SelectItem({
286
+ className,
287
+ children,
288
+ ...props
289
+ }) {
290
+ return /* @__PURE__ */ jsxs(
291
+ SelectPrimitive.Item,
292
+ {
293
+ "data-slot": "select-item",
294
+ className: cn(
295
+ "focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
296
+ className
297
+ ),
298
+ ...props,
299
+ children: [
300
+ /* @__PURE__ */ jsx("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }) }) }),
301
+ /* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children })
302
+ ]
303
+ }
304
+ );
305
+ }
306
+ function SelectScrollUpButton({
307
+ className,
308
+ ...props
309
+ }) {
310
+ return /* @__PURE__ */ jsx(
311
+ SelectPrimitive.ScrollUpButton,
312
+ {
313
+ "data-slot": "select-scroll-up-button",
314
+ className: cn(
315
+ "flex cursor-default items-center justify-center py-1",
316
+ className
317
+ ),
318
+ ...props,
319
+ children: /* @__PURE__ */ jsx(ChevronUpIcon, { className: "size-4" })
320
+ }
321
+ );
322
+ }
323
+ function SelectScrollDownButton({
324
+ className,
325
+ ...props
326
+ }) {
327
+ return /* @__PURE__ */ jsx(
328
+ SelectPrimitive.ScrollDownButton,
329
+ {
330
+ "data-slot": "select-scroll-down-button",
331
+ className: cn(
332
+ "flex cursor-default items-center justify-center py-1",
333
+ className
334
+ ),
335
+ ...props,
336
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4" })
337
+ }
338
+ );
339
+ }
340
+ var SmartSelect = ({
341
+ field,
342
+ label,
343
+ options,
344
+ className = "",
345
+ placeholder,
346
+ validation,
347
+ required = false,
348
+ defaultValue,
349
+ info,
350
+ subLabel
351
+ }) => {
352
+ const { value, error, onChange, fieldRef, registerValidation } = useFormField(field);
353
+ const fieldDetection = useFieldDetection();
354
+ const hasRegistered = useRef(false);
355
+ const hasSetDefault = useRef(false);
356
+ useEffect(() => {
357
+ if (validation && !hasRegistered.current) {
358
+ hasRegistered.current = true;
359
+ registerValidation(field, validation);
360
+ }
361
+ }, [validation, field, registerValidation]);
362
+ useEffect(() => {
363
+ if (fieldDetection?.registerField) {
364
+ fieldDetection.registerField(field);
365
+ }
366
+ }, [field, fieldDetection]);
367
+ useEffect(() => {
368
+ if (defaultValue !== void 0 && !hasSetDefault.current && (value === void 0 || value === null || value === "")) {
369
+ onChange(defaultValue);
370
+ hasSetDefault.current = true;
371
+ }
372
+ }, [defaultValue, value, onChange]);
373
+ return /* @__PURE__ */ jsxs("div", { className: `flex-1 min-w-0 ${className}`, children: [
374
+ label && /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
375
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
376
+ /* @__PURE__ */ jsxs(Label, { className: "text-sm font-medium text-foreground", children: [
377
+ label,
378
+ " ",
379
+ required && /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" })
380
+ ] }),
381
+ info && /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
382
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(InfoIcon, { className: "h-4 w-4 text-muted-foreground cursor-pointer mr-2" }) }),
383
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { className: "max-w-xs", children: info }) })
384
+ ] }) })
385
+ ] }),
386
+ subLabel && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: subLabel })
387
+ ] }),
388
+ /* @__PURE__ */ jsxs(
389
+ Select,
390
+ {
391
+ value: value || "",
392
+ onValueChange: (newValue) => onChange(newValue),
393
+ children: [
394
+ /* @__PURE__ */ jsx(
395
+ SelectTrigger,
396
+ {
397
+ ref: fieldRef,
398
+ className: `w-full ${error ? "border-destructive" : ""} ${className}`,
399
+ "data-field": field,
400
+ children: /* @__PURE__ */ jsx(SelectValue, { placeholder: placeholder || `Select ${label || field}` })
401
+ }
402
+ ),
403
+ /* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
404
+ ]
405
+ }
406
+ ),
407
+ error && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm mt-1", children: error })
408
+ ] });
409
+ };
410
+ var buttonVariants = cva(
411
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
412
+ {
413
+ variants: {
414
+ variant: {
415
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
416
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
417
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
418
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
419
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
420
+ link: "text-primary underline-offset-4 hover:underline"
421
+ },
422
+ size: {
423
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
424
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
425
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
426
+ icon: "size-9"
427
+ }
428
+ },
429
+ defaultVariants: {
430
+ variant: "default",
431
+ size: "default"
432
+ }
433
+ }
434
+ );
435
+ function Button({
436
+ className,
437
+ variant,
438
+ size,
439
+ asChild = false,
440
+ ...props
441
+ }) {
442
+ const Comp = asChild ? Slot : "button";
443
+ return /* @__PURE__ */ jsx(
444
+ Comp,
445
+ {
446
+ "data-slot": "button",
447
+ className: cn(buttonVariants({ variant, size, className })),
448
+ ...props
449
+ }
450
+ );
451
+ }
452
+ function Calendar({
453
+ className,
454
+ classNames,
455
+ showOutsideDays = true,
456
+ captionLayout = "label",
457
+ buttonVariant = "ghost",
458
+ formatters,
459
+ components,
460
+ ...props
461
+ }) {
462
+ const defaultClassNames = getDefaultClassNames();
463
+ return /* @__PURE__ */ jsx(
464
+ DayPicker,
465
+ {
466
+ showOutsideDays,
467
+ className: cn(
468
+ "bg-background group/calendar p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
469
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
470
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
471
+ className
472
+ ),
473
+ captionLayout,
474
+ formatters: {
475
+ formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
476
+ ...formatters
477
+ },
478
+ classNames: {
479
+ root: cn("w-fit", defaultClassNames.root),
480
+ months: cn(
481
+ "flex gap-4 flex-col md:flex-row relative",
482
+ defaultClassNames.months
483
+ ),
484
+ month: cn("flex flex-col w-full gap-4", defaultClassNames.month),
485
+ nav: cn(
486
+ "flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between",
487
+ defaultClassNames.nav
488
+ ),
489
+ button_previous: cn(
490
+ buttonVariants({ variant: buttonVariant }),
491
+ "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
492
+ defaultClassNames.button_previous
493
+ ),
494
+ button_next: cn(
495
+ buttonVariants({ variant: buttonVariant }),
496
+ "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
497
+ defaultClassNames.button_next
498
+ ),
499
+ month_caption: cn(
500
+ "flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)",
501
+ defaultClassNames.month_caption
502
+ ),
503
+ dropdowns: cn(
504
+ "w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5",
505
+ defaultClassNames.dropdowns
506
+ ),
507
+ dropdown_root: cn(
508
+ "relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md",
509
+ defaultClassNames.dropdown_root
510
+ ),
511
+ dropdown: cn(
512
+ "absolute bg-popover inset-0 opacity-0",
513
+ defaultClassNames.dropdown
514
+ ),
515
+ caption_label: cn(
516
+ "select-none font-medium",
517
+ captionLayout === "label" ? "text-sm" : "rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5",
518
+ defaultClassNames.caption_label
519
+ ),
520
+ table: "w-full border-collapse",
521
+ weekdays: cn("flex", defaultClassNames.weekdays),
522
+ weekday: cn(
523
+ "text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none",
524
+ defaultClassNames.weekday
525
+ ),
526
+ week: cn("flex w-full mt-2", defaultClassNames.week),
527
+ week_number_header: cn(
528
+ "select-none w-(--cell-size)",
529
+ defaultClassNames.week_number_header
530
+ ),
531
+ week_number: cn(
532
+ "text-[0.8rem] select-none text-muted-foreground",
533
+ defaultClassNames.week_number
534
+ ),
535
+ day: cn(
536
+ "relative w-full h-full p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none",
537
+ defaultClassNames.day
538
+ ),
539
+ range_start: cn(
540
+ "rounded-l-md bg-accent",
541
+ defaultClassNames.range_start
542
+ ),
543
+ range_middle: cn("rounded-none", defaultClassNames.range_middle),
544
+ range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
545
+ today: cn(
546
+ "bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none",
547
+ defaultClassNames.today
548
+ ),
549
+ outside: cn(
550
+ "text-muted-foreground aria-selected:text-muted-foreground",
551
+ defaultClassNames.outside
552
+ ),
553
+ disabled: cn(
554
+ "text-muted-foreground opacity-50",
555
+ defaultClassNames.disabled
556
+ ),
557
+ hidden: cn("invisible", defaultClassNames.hidden),
558
+ ...classNames
559
+ },
560
+ components: {
561
+ Root: ({ className: className2, rootRef, ...props2 }) => {
562
+ return /* @__PURE__ */ jsx(
563
+ "div",
564
+ {
565
+ "data-slot": "calendar",
566
+ ref: rootRef,
567
+ className: cn(className2),
568
+ ...props2
569
+ }
570
+ );
571
+ },
572
+ Chevron: ({ className: className2, orientation, ...props2 }) => {
573
+ if (orientation === "left") {
574
+ return /* @__PURE__ */ jsx(ChevronLeftIcon, { className: cn("size-4", className2), ...props2 });
575
+ }
576
+ if (orientation === "right") {
577
+ return /* @__PURE__ */ jsx(
578
+ ChevronRightIcon,
579
+ {
580
+ className: cn("size-4", className2),
581
+ ...props2
582
+ }
583
+ );
584
+ }
585
+ return /* @__PURE__ */ jsx(ChevronDownIcon, { className: cn("size-4", className2), ...props2 });
586
+ },
587
+ DayButton: CalendarDayButton,
588
+ WeekNumber: ({ children, ...props2 }) => {
589
+ return /* @__PURE__ */ jsx("td", { ...props2, children: /* @__PURE__ */ jsx("div", { className: "flex size-(--cell-size) items-center justify-center text-center", children }) });
590
+ },
591
+ ...components
592
+ },
593
+ ...props
594
+ }
595
+ );
596
+ }
597
+ function CalendarDayButton({
598
+ className,
599
+ day,
600
+ modifiers,
601
+ ...props
602
+ }) {
603
+ const defaultClassNames = getDefaultClassNames();
604
+ const ref = React4.useRef(null);
605
+ React4.useEffect(() => {
606
+ if (modifiers.focused) ref.current?.focus();
607
+ }, [modifiers.focused]);
608
+ return /* @__PURE__ */ jsx(
609
+ Button,
610
+ {
611
+ ref,
612
+ variant: "ghost",
613
+ size: "icon",
614
+ "data-day": day.date.toLocaleDateString(),
615
+ "data-selected-single": modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle,
616
+ "data-range-start": modifiers.range_start,
617
+ "data-range-end": modifiers.range_end,
618
+ "data-range-middle": modifiers.range_middle,
619
+ className: cn(
620
+ "data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 dark:hover:text-accent-foreground flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md [&>span]:text-xs [&>span]:opacity-70",
621
+ defaultClassNames.day,
622
+ className
623
+ ),
624
+ ...props
625
+ }
626
+ );
627
+ }
628
+ function Popover({
629
+ ...props
630
+ }) {
631
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
632
+ }
633
+ function PopoverTrigger({
634
+ ...props
635
+ }) {
636
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
637
+ }
638
+ function PopoverContent({
639
+ className,
640
+ align = "center",
641
+ sideOffset = 4,
642
+ ...props
643
+ }) {
644
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
645
+ PopoverPrimitive.Content,
646
+ {
647
+ "data-slot": "popover-content",
648
+ align,
649
+ sideOffset,
650
+ className: cn(
651
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
652
+ className
653
+ ),
654
+ ...props
655
+ }
656
+ ) });
657
+ }
658
+ var SmartDatePicker = ({
659
+ field,
660
+ label,
661
+ className = "",
662
+ placeholder,
663
+ validation,
664
+ required = false,
665
+ allowPast = true,
666
+ allowFuture = true,
667
+ valueAsString = true,
668
+ minDate,
669
+ maxDate,
670
+ defaultValue,
671
+ info,
672
+ subLabel
673
+ }) => {
674
+ const { value, error, onChange, fieldRef, registerValidation } = useFormField(field);
675
+ const fieldDetection = useFieldDetection();
676
+ const hasRegistered = useRef(false);
677
+ const hasSetDefault = useRef(false);
678
+ const parsedValue = useMemo(() => {
679
+ if (!value) return void 0;
680
+ if (value instanceof Date) return value;
681
+ const d = new Date(value);
682
+ return isNaN(d.getTime()) ? void 0 : d;
683
+ }, [value]);
684
+ const [open, setOpen] = useState(false);
685
+ useEffect(() => {
686
+ if (validation && !hasRegistered.current) {
687
+ hasRegistered.current = true;
688
+ registerValidation(field, validation);
689
+ }
690
+ }, [validation, field, registerValidation]);
691
+ useEffect(() => {
692
+ if (fieldDetection?.registerField) {
693
+ fieldDetection.registerField(field);
694
+ }
695
+ }, [field, fieldDetection]);
696
+ useEffect(() => {
697
+ if (defaultValue !== void 0 && !hasSetDefault.current && (value === void 0 || value === null || value === "")) {
698
+ onChange(defaultValue);
699
+ hasSetDefault.current = true;
700
+ }
701
+ }, [defaultValue, value, onChange]);
702
+ const today = useMemo(() => /* @__PURE__ */ new Date(), []);
703
+ const disabledMatcher = (date) => {
704
+ if (!allowPast) {
705
+ const startOfToday = new Date(today.getFullYear(), today.getMonth(), today.getDate());
706
+ if (date < startOfToday) return true;
707
+ }
708
+ if (!allowFuture) {
709
+ const startOfTomorrow = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1);
710
+ if (date >= startOfTomorrow) return true;
711
+ }
712
+ if (minDate && date < new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate())) return true;
713
+ if (maxDate && date > new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate())) return true;
714
+ return false;
715
+ };
716
+ const handleSelect = (selected) => {
717
+ if (!selected) {
718
+ onChange(void 0);
719
+ return;
720
+ }
721
+ if (valueAsString) {
722
+ const iso = format(selected, "yyyy-MM-dd");
723
+ onChange(iso);
724
+ } else {
725
+ onChange(selected);
726
+ }
727
+ setOpen(false);
728
+ };
729
+ const buttonText = useMemo(() => {
730
+ if (!parsedValue) return placeholder || `Select ${label || field}`;
731
+ return format(parsedValue, "dd/MM/yyyy");
732
+ }, [parsedValue, placeholder, label, field]);
733
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex-1 min-w-0", className), children: [
734
+ label && /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
735
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
736
+ /* @__PURE__ */ jsxs(Label, { className: "text-sm font-medium text-foreground", children: [
737
+ label,
738
+ " ",
739
+ required && /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" })
740
+ ] }),
741
+ info && /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
742
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(InfoIcon, { className: "h-4 w-4 text-muted-foreground cursor-pointer mr-2" }) }),
743
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { className: "max-w-xs", children: info }) })
744
+ ] }) })
745
+ ] }),
746
+ subLabel && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: subLabel })
747
+ ] }),
748
+ /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
749
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
750
+ Button,
751
+ {
752
+ ref: fieldRef,
753
+ variant: "outline",
754
+ className: cn(
755
+ "w-full justify-start text-left font-normal",
756
+ !parsedValue && "text-muted-foreground",
757
+ error && "border-destructive"
758
+ ),
759
+ "data-field": field,
760
+ children: [
761
+ /* @__PURE__ */ jsx(Calendar$1, { className: "mr-2 h-4 w-4" }),
762
+ buttonText
763
+ ]
764
+ }
765
+ ) }),
766
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: /* @__PURE__ */ jsx(
767
+ Calendar,
768
+ {
769
+ mode: "single",
770
+ selected: parsedValue,
771
+ onSelect: handleSelect,
772
+ disabled: disabledMatcher,
773
+ initialFocus: true
774
+ }
775
+ ) })
776
+ ] }),
777
+ error && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm mt-1", children: error })
778
+ ] });
779
+ };
780
+ var SmartTags = ({
781
+ field,
782
+ label,
783
+ className = "",
784
+ placeholder = "Type and press Enter...",
785
+ validation,
786
+ required = false,
787
+ maxTags,
788
+ defaultValue,
789
+ maxLength,
790
+ minLength,
791
+ allowDuplicates = false,
792
+ disabled = false,
793
+ onTagAdd,
794
+ onTagRemove,
795
+ info,
796
+ subLabel
797
+ }) => {
798
+ const { value, error, onChange, fieldRef, registerValidation } = useFormField(field);
799
+ const fieldDetection = useFieldDetection();
800
+ const hasRegistered = useRef(false);
801
+ const hasSetDefault = useRef(false);
802
+ const [tags, setTags] = useState([]);
803
+ const [inputValue, setInputValue] = useState("");
804
+ const inputRef = useRef(null);
805
+ useEffect(() => {
806
+ if (validation && !hasRegistered.current) {
807
+ hasRegistered.current = true;
808
+ registerValidation(field, validation);
809
+ }
810
+ }, [validation, field, registerValidation]);
811
+ useEffect(() => {
812
+ if (fieldDetection?.registerField) {
813
+ fieldDetection.registerField(field);
814
+ }
815
+ }, [field, fieldDetection]);
816
+ useEffect(() => {
817
+ if (defaultValue !== void 0 && !hasSetDefault.current && (!value || Array.isArray(value) && value.length === 0)) {
818
+ setTags(defaultValue);
819
+ onChange(defaultValue);
820
+ hasSetDefault.current = true;
821
+ }
822
+ }, [defaultValue, value, onChange]);
823
+ useEffect(() => {
824
+ if (Array.isArray(value)) {
825
+ setTags(value);
826
+ }
827
+ }, [value]);
828
+ const addTag = (text) => {
829
+ const trimmedText = text.trim();
830
+ if (!trimmedText) return;
831
+ if (minLength && trimmedText.length < minLength) return;
832
+ if (maxLength && trimmedText.length > maxLength) return;
833
+ if (maxTags && tags.length >= maxTags) return;
834
+ if (!allowDuplicates && tags.some((tag) => tag.toLowerCase() === trimmedText.toLowerCase())) {
835
+ return;
836
+ }
837
+ const newTags = [...tags, trimmedText];
838
+ setTags(newTags);
839
+ onChange(newTags);
840
+ if (onTagAdd) {
841
+ onTagAdd(trimmedText);
842
+ }
843
+ };
844
+ const removeTag = (tagText) => {
845
+ const newTags = tags.filter((tag) => tag !== tagText);
846
+ setTags(newTags);
847
+ onChange(newTags);
848
+ if (onTagRemove) {
849
+ onTagRemove(tagText);
850
+ }
851
+ };
852
+ const handleKeyDown = (e) => {
853
+ if (e.key === "Enter" || e.key === ",") {
854
+ e.preventDefault();
855
+ addTag(inputValue);
856
+ setInputValue("");
857
+ } else if (e.key === "Backspace" && !inputValue && tags.length > 0) {
858
+ removeTag(tags[tags.length - 1]);
859
+ }
860
+ };
861
+ const handleInputChange = (e) => {
862
+ const value2 = e.target.value;
863
+ setInputValue(value2);
864
+ };
865
+ return /* @__PURE__ */ jsxs("div", { className: `flex-1 min-w-0 ${className}`, children: [
866
+ label && /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
867
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
868
+ /* @__PURE__ */ jsxs(Label, { className: "text-sm font-medium text-foreground", children: [
869
+ label,
870
+ " ",
871
+ required && /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" }),
872
+ maxTags && /* @__PURE__ */ jsxs("span", { className: "ml-2 text-xs text-muted-foreground", children: [
873
+ "(",
874
+ tags.length,
875
+ "/",
876
+ maxTags,
877
+ ")"
878
+ ] })
879
+ ] }),
880
+ info && /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
881
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(InfoIcon, { className: "h-4 w-4 text-muted-foreground cursor-pointer mr-2" }) }),
882
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { className: "max-w-xs", children: info }) })
883
+ ] }) })
884
+ ] }),
885
+ subLabel && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: subLabel })
886
+ ] }),
887
+ /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsxs(
888
+ "div",
889
+ {
890
+ ref: fieldRef,
891
+ className: cn(
892
+ "min-h-[40px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background",
893
+ "focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
894
+ "flex flex-wrap items-center gap-2 cursor-text",
895
+ error && "border-destructive focus-within:ring-destructive",
896
+ disabled && "cursor-not-allowed opacity-50"
897
+ ),
898
+ "data-field": field,
899
+ onClick: () => inputRef.current?.focus(),
900
+ children: [
901
+ tags.map((tagText, index) => /* @__PURE__ */ jsxs(
902
+ "div",
903
+ {
904
+ className: "inline-flex items-center gap-1 px-2 py-1 bg-primary text-primary-foreground rounded-md text-sm",
905
+ children: [
906
+ /* @__PURE__ */ jsx("span", { children: tagText }),
907
+ /* @__PURE__ */ jsx(
908
+ Button,
909
+ {
910
+ type: "button",
911
+ variant: "ghost",
912
+ size: "sm",
913
+ className: "h-4 w-4 p-0 hover:bg-primary-foreground/20 text-primary-foreground",
914
+ onClick: (e) => {
915
+ e.stopPropagation();
916
+ removeTag(tagText);
917
+ },
918
+ disabled,
919
+ children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
920
+ }
921
+ )
922
+ ]
923
+ },
924
+ `${tagText}-${index}`
925
+ )),
926
+ /* @__PURE__ */ jsx(
927
+ Input,
928
+ {
929
+ ref: inputRef,
930
+ type: "text",
931
+ value: inputValue,
932
+ onChange: handleInputChange,
933
+ onKeyDown: handleKeyDown,
934
+ placeholder: tags.length === 0 ? placeholder : "",
935
+ className: "flex-1 min-w-[120px] border-0 shadow-none focus-visible:ring-0 focus-visible:ring-offset-0 p-0 h-auto",
936
+ disabled,
937
+ maxLength
938
+ }
939
+ )
940
+ ]
941
+ }
942
+ ) }),
943
+ error && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm mt-1", children: error })
944
+ ] });
945
+ };
946
+
947
+ export { Button, Popover, PopoverContent, PopoverTrigger, SmartCheckbox, SmartDatePicker, SmartRadioGroup, SmartSelect, SmartTags };
948
+ //# sourceMappingURL=chunk-6WAEAWTD.js.map
949
+ //# sourceMappingURL=chunk-6WAEAWTD.js.map