laif-ds 0.2.66 → 0.2.68
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.
|
@@ -26,13 +26,13 @@ export interface AppFormItem {
|
|
|
26
26
|
| "async"
|
|
27
27
|
| "async-multiple"; // Field type
|
|
28
28
|
name: string; // Field name (used for form state and validation)
|
|
29
|
-
inputType?:
|
|
29
|
+
inputType?: ComponentProps<"input">["type"]; // HTML input type for "input" component (e.g. "text", "email", "password", "number", "url", "search", "tel")
|
|
30
30
|
defaultValue?: string | boolean | number | string[] | Date | number[]; // Initial value
|
|
31
31
|
options?: AppSelectOption[]; // Options for select/multiselect/radio
|
|
32
32
|
disabled?: boolean; // Disables the field
|
|
33
33
|
placeholder?: string; // Placeholder text
|
|
34
34
|
caption?: string; // Helper text below the field
|
|
35
|
-
calendarRange?: [Date, Date]; // Date range for datepicker
|
|
35
|
+
calendarRange?: [Date, Date]; // Date range for datepicker (enables range mode)
|
|
36
36
|
min?: number; // Minimum value for slider
|
|
37
37
|
max?: number; // Maximum value for slider
|
|
38
38
|
step?: number; // Step value for slider
|
|
@@ -41,10 +41,11 @@ export interface AppFormItem {
|
|
|
41
41
|
resolveOptionValue?: (option: any) => string; // Value extractor for async option
|
|
42
42
|
renderSelectedValue?: (option: any) => React.ReactNode; // Customize render of selected async option
|
|
43
43
|
initialOptions?: any[]; // Optional cache for async select hydration
|
|
44
|
-
notFound?: React.ReactNode;
|
|
45
|
-
noResultsMessage?: string;
|
|
46
|
-
debounce?: number;
|
|
47
|
-
clearable?: boolean;
|
|
44
|
+
notFound?: React.ReactNode; // Custom not found message for async select
|
|
45
|
+
noResultsMessage?: string; // No results message for async select
|
|
46
|
+
debounce?: number; // Debounce time for async select search
|
|
47
|
+
clearable?: boolean; // Allow clearing async select value
|
|
48
|
+
datePickerProps?: Partial<ComponentProps<typeof DatePicker>>; // Additional DatePicker props (locale, dateFormat, numberOfMonths, minDate, maxDate, etc.)
|
|
48
49
|
}
|
|
49
50
|
```
|
|
50
51
|
|
|
@@ -199,7 +200,50 @@ Ricorda che il fetch parte solo quando il menu è aperto; eventuali valori inizi
|
|
|
199
200
|
|
|
200
201
|
### datepicker
|
|
201
202
|
|
|
202
|
-
Date picker component with optional range selection via `calendarRange`
|
|
203
|
+
Date picker component with optional range selection via `calendarRange`. Use `datePickerProps` to customize the DatePicker behavior such as locale, date format, number of months displayed, min/max dates, etc.
|
|
204
|
+
|
|
205
|
+
**Available datePickerProps options:**
|
|
206
|
+
|
|
207
|
+
- `locale`: Locale object from `date-fns/locale` (e.g., `enUS`, `it`, `fr`)
|
|
208
|
+
- `dateFormat`: Date format string (e.g., `"MM/dd/yyyy"`, `"dd/MM/yyyy"`)
|
|
209
|
+
- `numberOfMonths`: Number of months to display in the calendar
|
|
210
|
+
- `minDate`: Minimum selectable date
|
|
211
|
+
- `maxDate`: Maximum selectable date
|
|
212
|
+
- `firstDate`: First available date (disables dates before)
|
|
213
|
+
- `lastDate`: Last available date (disables dates after)
|
|
214
|
+
- `availableDates`: Array of specific dates that are selectable
|
|
215
|
+
- And other DatePicker props
|
|
216
|
+
|
|
217
|
+
**Example with English locale:**
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
import { enUS } from "date-fns/locale";
|
|
221
|
+
|
|
222
|
+
const items: AppFormItem[] = [
|
|
223
|
+
{
|
|
224
|
+
label: "Appointment Date",
|
|
225
|
+
component: "datepicker",
|
|
226
|
+
name: "appointmentDate",
|
|
227
|
+
placeholder: "Pick a date",
|
|
228
|
+
datePickerProps: {
|
|
229
|
+
locale: enUS,
|
|
230
|
+
dateFormat: "MM/dd/yyyy",
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
label: "Event Date Range",
|
|
235
|
+
component: "datepicker",
|
|
236
|
+
name: "eventRange",
|
|
237
|
+
placeholder: "Select date range",
|
|
238
|
+
calendarRange: [new Date(), new Date()],
|
|
239
|
+
datePickerProps: {
|
|
240
|
+
locale: enUS,
|
|
241
|
+
dateFormat: "MM/dd/yyyy",
|
|
242
|
+
numberOfMonths: 2,
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
];
|
|
246
|
+
```
|
|
203
247
|
|
|
204
248
|
### radio
|
|
205
249
|
|
|
@@ -358,6 +402,84 @@ export function DateRangeForm() {
|
|
|
358
402
|
}
|
|
359
403
|
```
|
|
360
404
|
|
|
405
|
+
### External Form Control
|
|
406
|
+
|
|
407
|
+
You can access the form instance to programmatically control values, watch changes, and reset the form:
|
|
408
|
+
|
|
409
|
+
```tsx
|
|
410
|
+
import { AppForm, Button } from "laif-ds";
|
|
411
|
+
import { useForm } from "react-hook-form";
|
|
412
|
+
import { useState, useEffect } from "react";
|
|
413
|
+
|
|
414
|
+
export function ExternalControlForm() {
|
|
415
|
+
const [formValues, setFormValues] = useState({});
|
|
416
|
+
const [watchedValues, setWatchedValues] = useState({});
|
|
417
|
+
|
|
418
|
+
const form = useForm({
|
|
419
|
+
defaultValues: {
|
|
420
|
+
name: "",
|
|
421
|
+
email: "",
|
|
422
|
+
},
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
const { watch, setValue, reset } = form;
|
|
426
|
+
|
|
427
|
+
// Watch specific fields
|
|
428
|
+
const nameValue = watch("name");
|
|
429
|
+
const emailValue = watch("email");
|
|
430
|
+
|
|
431
|
+
// Auto-fill handler
|
|
432
|
+
const handleAutoFill = () => {
|
|
433
|
+
setValue("name", "Mario Rossi");
|
|
434
|
+
setValue("email", "mario@example.com");
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
// Reset handler
|
|
438
|
+
const handleReset = () => {
|
|
439
|
+
reset();
|
|
440
|
+
setFormValues({});
|
|
441
|
+
setWatchedValues({});
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
// Watch all form values
|
|
445
|
+
useEffect(() => {
|
|
446
|
+
const subscription = watch((values) => {
|
|
447
|
+
setWatchedValues(values);
|
|
448
|
+
});
|
|
449
|
+
return () => subscription.unsubscribe();
|
|
450
|
+
}, [watch]);
|
|
451
|
+
|
|
452
|
+
return (
|
|
453
|
+
<div>
|
|
454
|
+
<div className="mb-4 flex gap-2">
|
|
455
|
+
<Button type="button" variant="outline" onClick={handleAutoFill}>
|
|
456
|
+
Auto-fill
|
|
457
|
+
</Button>
|
|
458
|
+
<Button type="button" variant="outline" onClick={handleReset}>
|
|
459
|
+
Reset
|
|
460
|
+
</Button>
|
|
461
|
+
</div>
|
|
462
|
+
|
|
463
|
+
<AppForm
|
|
464
|
+
form={form}
|
|
465
|
+
items={[
|
|
466
|
+
{ label: "Name", component: "input", name: "name" },
|
|
467
|
+
{ label: "Email", component: "input", name: "email" },
|
|
468
|
+
]}
|
|
469
|
+
onSubmit={(data) => setFormValues(data)}
|
|
470
|
+
showSubmitButton
|
|
471
|
+
/>
|
|
472
|
+
|
|
473
|
+
<div className="mt-4">
|
|
474
|
+
<p>Name: {nameValue || "(empty)"}</p>
|
|
475
|
+
<p>Email: {emailValue || "(empty)"}</p>
|
|
476
|
+
<pre>{JSON.stringify(watchedValues, null, 2)}</pre>
|
|
477
|
+
</div>
|
|
478
|
+
</div>
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
361
483
|
---
|
|
362
484
|
|
|
363
485
|
## Notes
|
|
@@ -2,45 +2,72 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Date picker component that supports both **single date** and **date range** selection. Composed of a trigger with calendar icon and a `Calendar` component in a popover. Supports min/max date constraints, allowed dates, custom display format, sizes, localization, and initial calendar month.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## Props
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
| `
|
|
16
|
-
| `
|
|
17
|
-
| `
|
|
18
|
-
| `
|
|
19
|
-
| `
|
|
20
|
-
| `
|
|
21
|
-
| `disabled` | `boolean`
|
|
22
|
-
| `size` | `"sm" \| "default" \| "lg"`
|
|
23
|
-
| `firstDate` | `Date`
|
|
24
|
-
| `lastDate` | `Date`
|
|
25
|
-
| `minDate` | `Date`
|
|
26
|
-
| `maxDate` | `Date`
|
|
27
|
-
| `availableDates` | `Date[]`
|
|
28
|
-
| `locale` | `Partial<Locale>`
|
|
29
|
-
| `initialCalendarMonth` | `Date`
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
32
|
-
| `
|
|
11
|
+
### Common Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
| ---------------------- | --------------------------------------- | ------------------ | ------------------------------------------------------------ |
|
|
15
|
+
| `mode` | `"single" \| "range"` | `"single"` | Selection mode: single date or date range. |
|
|
16
|
+
| `placeholder` | `string` | `"Seleziona data"` | Text when no date is selected. |
|
|
17
|
+
| `dateFormat` | `string` | `"dd/MM/yyyy"` | `date-fns` format string for the trigger text. |
|
|
18
|
+
| `className` | `string` | `""` | Additional classes for the trigger. |
|
|
19
|
+
| `wrpClassName` | `string` | `""` | Additional classes for the wrapper container. |
|
|
20
|
+
| `label` | `string \| React.ReactNode` | `undefined` | Label displayed above the date picker. |
|
|
21
|
+
| `disabled` | `boolean` | `false` | Disables interactions and the popover. |
|
|
22
|
+
| `size` | `"sm" \| "default" \| "lg"` | `"default"` | Trigger size affecting height and icon size. |
|
|
23
|
+
| `firstDate` | `Date` | `undefined` | Minimum selectable date (legacy prop, use `minDate`). |
|
|
24
|
+
| `lastDate` | `Date` | `undefined` | Maximum selectable date (legacy prop, use `maxDate`). |
|
|
25
|
+
| `minDate` | `Date` | `undefined` | Minimum selectable date. |
|
|
26
|
+
| `maxDate` | `Date` | `undefined` | Maximum selectable date. |
|
|
27
|
+
| `availableDates` | `Date[]` | `undefined` | Only these dates are selectable. |
|
|
28
|
+
| `locale` | `Partial<Locale>` | `it` (Italian) | Locale for date formatting (from date-fns). |
|
|
29
|
+
| `initialCalendarMonth` | `Date` | `undefined` | Initial month to display in calendar (overridden by value). |
|
|
30
|
+
| `numberOfMonths` | `number` | `1` | Number of months to display (useful for range mode). |
|
|
31
|
+
| `customCalendarProps` | `React.ComponentProps<typeof Calendar>` | `undefined` | Custom props to pass to the Calendar component. |
|
|
32
|
+
| `id` | `string` | `undefined` | HTML id attribute for the trigger (useful for testing). |
|
|
33
|
+
| `data-testid` | `string` | `undefined` | Test identifier attribute for E2E testing (e.g. Playwright). |
|
|
34
|
+
|
|
35
|
+
### Single Mode Props (mode="single" or undefined)
|
|
36
|
+
|
|
37
|
+
| Prop | Type | Default | Description |
|
|
38
|
+
| ---------- | ----------------------------------- | ----------- | ----------------------------- |
|
|
39
|
+
| `value` | `Date` | `undefined` | Controlled selected date. |
|
|
40
|
+
| `onChange` | `(date: Date \| undefined) => void` | `undefined` | Called when the date changes. |
|
|
41
|
+
|
|
42
|
+
### Range Mode Props (mode="range")
|
|
43
|
+
|
|
44
|
+
| Prop | Type | Default | Description |
|
|
45
|
+
| ---------- | ------------------------------------------ | ----------- | ----------------------------------- |
|
|
46
|
+
| `value` | `DateRange` (`{ from?: Date, to?: Date }`) | `undefined` | Controlled selected date range. |
|
|
47
|
+
| `onChange` | `(range: DateRange \| undefined) => void` | `undefined` | Called when the date range changes. |
|
|
33
48
|
|
|
34
49
|
---
|
|
35
50
|
|
|
36
51
|
## Behavior
|
|
37
52
|
|
|
53
|
+
### Single Mode
|
|
54
|
+
|
|
55
|
+
- **Selection**: Click a date to select it. The selected date is highlighted.
|
|
56
|
+
- **Display**: Shows the formatted date in the trigger (e.g., "13/01/2025").
|
|
57
|
+
|
|
58
|
+
### Range Mode
|
|
59
|
+
|
|
60
|
+
- **Selection**: Click to set the start date, click again to set the end date. The range is highlighted.
|
|
61
|
+
- **Display**: Shows "from - to" format in the trigger (e.g., "13/01/2025 - 20/01/2025").
|
|
62
|
+
- **Multiple months**: Use `numberOfMonths={2}` to show two months side by side for easier range selection.
|
|
63
|
+
|
|
64
|
+
### Common Behavior
|
|
65
|
+
|
|
38
66
|
- **Disabled dates**: `firstDate`, `lastDate`, `minDate`, `maxDate`, and `availableDates` are combined into the `Calendar`'s `disabled` matcher array.
|
|
39
67
|
- **Disabled state**: When `disabled` is true, the popover will not open and the trigger is non-interactive with reduced opacity.
|
|
40
|
-
- **Formatting**: `dateFormat` is applied via `date-fns/format` to the selected date in the trigger.
|
|
41
|
-
- **Calendar month**: The calendar displays the month of the selected date, or `initialCalendarMonth` if no date is selected.
|
|
68
|
+
- **Formatting**: `dateFormat` is applied via `date-fns/format` to the selected date(s) in the trigger.
|
|
69
|
+
- **Calendar month**: The calendar displays the month of the selected date (or `from` date in range mode), or `initialCalendarMonth` if no date is selected.
|
|
42
70
|
- **State synchronization**: The component syncs internal state with the `value` prop via useEffect.
|
|
43
|
-
- **Custom calendar**: Use `customCalendarProps` to override default Calendar props (mode, selected, onSelect).
|
|
44
71
|
- **Localization**: The `locale` prop affects both the calendar display and the formatted date in the trigger.
|
|
45
72
|
|
|
46
73
|
---
|
|
@@ -79,6 +106,80 @@ export function ControlledDatePicker() {
|
|
|
79
106
|
}
|
|
80
107
|
```
|
|
81
108
|
|
|
109
|
+
### Range Mode - Basic
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
import { DatePicker } from "laif-ds";
|
|
113
|
+
import { useState } from "react";
|
|
114
|
+
import { DateRange } from "react-day-picker";
|
|
115
|
+
|
|
116
|
+
export function RangeDatePicker() {
|
|
117
|
+
const [range, setRange] = useState<DateRange | undefined>();
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<DatePicker
|
|
121
|
+
mode="range"
|
|
122
|
+
value={range}
|
|
123
|
+
onChange={setRange}
|
|
124
|
+
placeholder="Seleziona intervallo"
|
|
125
|
+
/>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Range Mode - With Two Months
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
import { DatePicker } from "laif-ds";
|
|
134
|
+
import { addDays } from "date-fns";
|
|
135
|
+
import { useState } from "react";
|
|
136
|
+
import { DateRange } from "react-day-picker";
|
|
137
|
+
|
|
138
|
+
export function RangeWithTwoMonths() {
|
|
139
|
+
const [range, setRange] = useState<DateRange | undefined>({
|
|
140
|
+
from: new Date(),
|
|
141
|
+
to: addDays(new Date(), 7),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<DatePicker
|
|
146
|
+
mode="range"
|
|
147
|
+
value={range}
|
|
148
|
+
onChange={setRange}
|
|
149
|
+
placeholder="Seleziona intervallo"
|
|
150
|
+
numberOfMonths={2}
|
|
151
|
+
label="Periodo di prenotazione"
|
|
152
|
+
/>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Range Mode - With Constraints
|
|
158
|
+
|
|
159
|
+
```tsx
|
|
160
|
+
import { DatePicker } from "laif-ds";
|
|
161
|
+
import { addDays } from "date-fns";
|
|
162
|
+
import { useState } from "react";
|
|
163
|
+
import { DateRange } from "react-day-picker";
|
|
164
|
+
|
|
165
|
+
export function RangeWithConstraints() {
|
|
166
|
+
const today = new Date();
|
|
167
|
+
const [range, setRange] = useState<DateRange | undefined>();
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<DatePicker
|
|
171
|
+
mode="range"
|
|
172
|
+
value={range}
|
|
173
|
+
onChange={setRange}
|
|
174
|
+
placeholder="Seleziona (prossimi 30 giorni)"
|
|
175
|
+
firstDate={today}
|
|
176
|
+
lastDate={addDays(today, 30)}
|
|
177
|
+
numberOfMonths={2}
|
|
178
|
+
/>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
82
183
|
### Configurable
|
|
83
184
|
|
|
84
185
|
```tsx
|
|
@@ -245,3 +346,6 @@ export function DatePickerInDialog() {
|
|
|
245
346
|
- **Button variant**: The `buttonVariant` prop is deprecated and not used in the current implementation.
|
|
246
347
|
- **Accessibility**: The trigger has proper ARIA attributes and keyboard navigation support.
|
|
247
348
|
- **State management**: Component maintains internal state but syncs with external `value` prop.
|
|
349
|
+
- **Range mode**: Use `mode="range"` for date range selection. The `value` and `onChange` types change accordingly.
|
|
350
|
+
- **Multiple months**: In range mode, use `numberOfMonths={2}` to display two months side by side for better UX.
|
|
351
|
+
- **DateRange type**: Import `DateRange` from `react-day-picker` when using range mode: `{ from?: Date, to?: Date }`.
|
|
@@ -1,55 +1,55 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs as l, jsx as a } from "react/jsx-runtime";
|
|
3
|
-
import { cn as
|
|
4
|
-
import { Controller as
|
|
5
|
-
import { AppSelect as
|
|
6
|
-
import { AsyncSelect as
|
|
7
|
-
import { Button as
|
|
8
|
-
import { Checkbox as
|
|
9
|
-
import { DatePicker as
|
|
10
|
-
import { Input as
|
|
3
|
+
import { cn as d } from "../../lib/utils.js";
|
|
4
|
+
import { Controller as I } from "../../node_modules/react-hook-form/dist/index.esm.js";
|
|
5
|
+
import { AppSelect as b } from "./app-select.js";
|
|
6
|
+
import { AsyncSelect as A } from "./async-select.js";
|
|
7
|
+
import { Button as F } from "./button.js";
|
|
8
|
+
import { Checkbox as R } from "./checkbox.js";
|
|
9
|
+
import { DatePicker as j } from "./date-picker.js";
|
|
10
|
+
import { Input as M } from "./input.js";
|
|
11
11
|
import { Label as t } from "./label.js";
|
|
12
|
-
import { RadioGroup as
|
|
13
|
-
import { Slider as
|
|
14
|
-
import { Switch as
|
|
15
|
-
import { Textarea as
|
|
12
|
+
import { RadioGroup as B, RadioGroupItem as D } from "./radio-group.js";
|
|
13
|
+
import { Slider as T } from "./slider.js";
|
|
14
|
+
import { Switch as $ } from "./switch.js";
|
|
15
|
+
import { Textarea as G } from "./textarea.js";
|
|
16
16
|
import { Typo as i } from "./typo.js";
|
|
17
|
-
const
|
|
18
|
-
items:
|
|
19
|
-
cols:
|
|
20
|
-
form:
|
|
21
|
-
submitText:
|
|
22
|
-
onSubmit:
|
|
23
|
-
isSubmitting:
|
|
24
|
-
showSubmitButton:
|
|
17
|
+
const ne = ({
|
|
18
|
+
items: h,
|
|
19
|
+
cols: m = "2",
|
|
20
|
+
form: g,
|
|
21
|
+
submitText: x = "Invia",
|
|
22
|
+
onSubmit: C,
|
|
23
|
+
isSubmitting: v = !1,
|
|
24
|
+
showSubmitButton: N = !1
|
|
25
25
|
}) => {
|
|
26
26
|
const {
|
|
27
|
-
control:
|
|
28
|
-
handleSubmit:
|
|
29
|
-
formState: { errors:
|
|
30
|
-
} =
|
|
31
|
-
const c =
|
|
27
|
+
control: y,
|
|
28
|
+
handleSubmit: f,
|
|
29
|
+
formState: { errors: S, isValid: V, isDirty: k }
|
|
30
|
+
} = g, w = (e) => {
|
|
31
|
+
const c = S[e.name]?.message, s = c ? String(c) : void 0;
|
|
32
32
|
return /* @__PURE__ */ a("div", { children: /* @__PURE__ */ a(
|
|
33
|
-
|
|
33
|
+
I,
|
|
34
34
|
{
|
|
35
35
|
name: e.name,
|
|
36
|
-
control:
|
|
36
|
+
control: y,
|
|
37
37
|
render: ({ field: r }) => {
|
|
38
38
|
const o = /* @__PURE__ */ l("div", { className: "mb-2 flex items-center justify-between", children: [
|
|
39
39
|
/* @__PURE__ */ a(t, { children: e.label }),
|
|
40
|
-
|
|
40
|
+
s && /* @__PURE__ */ a("span", { className: "text-d-destructive text-xs", children: s })
|
|
41
41
|
] });
|
|
42
42
|
switch (e.component) {
|
|
43
43
|
case "input":
|
|
44
44
|
return /* @__PURE__ */ l("div", { children: [
|
|
45
45
|
o,
|
|
46
46
|
/* @__PURE__ */ a(
|
|
47
|
-
|
|
47
|
+
M,
|
|
48
48
|
{
|
|
49
49
|
...r,
|
|
50
50
|
type: e.inputType,
|
|
51
51
|
placeholder: e.placeholder,
|
|
52
|
-
className: s
|
|
52
|
+
className: d(s && "border-d-destructive"),
|
|
53
53
|
disabled: e.disabled
|
|
54
54
|
}
|
|
55
55
|
)
|
|
@@ -65,7 +65,7 @@ const Z = ({
|
|
|
65
65
|
return /* @__PURE__ */ l("div", { children: [
|
|
66
66
|
o,
|
|
67
67
|
/* @__PURE__ */ a(
|
|
68
|
-
|
|
68
|
+
A,
|
|
69
69
|
{
|
|
70
70
|
multiple: n,
|
|
71
71
|
fetcher: e.fetcher,
|
|
@@ -89,11 +89,11 @@ const Z = ({
|
|
|
89
89
|
return /* @__PURE__ */ l("div", { children: [
|
|
90
90
|
o,
|
|
91
91
|
/* @__PURE__ */ a(
|
|
92
|
-
|
|
92
|
+
G,
|
|
93
93
|
{
|
|
94
94
|
...r,
|
|
95
95
|
placeholder: e.placeholder,
|
|
96
|
-
className: s
|
|
96
|
+
className: d(s && "border-d-destructive"),
|
|
97
97
|
disabled: e.disabled
|
|
98
98
|
}
|
|
99
99
|
)
|
|
@@ -102,23 +102,23 @@ const Z = ({
|
|
|
102
102
|
return /* @__PURE__ */ l("div", { children: [
|
|
103
103
|
o,
|
|
104
104
|
/* @__PURE__ */ a(
|
|
105
|
-
|
|
105
|
+
B,
|
|
106
106
|
{
|
|
107
107
|
value: r.value != null ? String(r.value) : "",
|
|
108
108
|
onValueChange: (n) => r.onChange(n),
|
|
109
109
|
className: "space-y-2",
|
|
110
110
|
disabled: e.disabled,
|
|
111
111
|
children: (e.options ?? []).map((n) => {
|
|
112
|
-
const
|
|
112
|
+
const p = `${e.name}-${n.value}`;
|
|
113
113
|
return /* @__PURE__ */ l(
|
|
114
114
|
"div",
|
|
115
115
|
{
|
|
116
116
|
className: "flex items-center gap-2",
|
|
117
117
|
children: [
|
|
118
118
|
/* @__PURE__ */ a(
|
|
119
|
-
|
|
119
|
+
D,
|
|
120
120
|
{
|
|
121
|
-
id:
|
|
121
|
+
id: p,
|
|
122
122
|
value: String(n.value),
|
|
123
123
|
disabled: e.disabled
|
|
124
124
|
}
|
|
@@ -126,8 +126,8 @@ const Z = ({
|
|
|
126
126
|
/* @__PURE__ */ a(
|
|
127
127
|
t,
|
|
128
128
|
{
|
|
129
|
-
htmlFor:
|
|
130
|
-
className:
|
|
129
|
+
htmlFor: p,
|
|
130
|
+
className: d(
|
|
131
131
|
"cursor-pointer",
|
|
132
132
|
e.disabled && "cursor-not-allowed opacity-60"
|
|
133
133
|
),
|
|
@@ -146,7 +146,7 @@ const Z = ({
|
|
|
146
146
|
return /* @__PURE__ */ l("div", { children: [
|
|
147
147
|
o,
|
|
148
148
|
/* @__PURE__ */ a(
|
|
149
|
-
|
|
149
|
+
b,
|
|
150
150
|
{
|
|
151
151
|
...r,
|
|
152
152
|
onValueChange: (n) => r.onChange(n),
|
|
@@ -160,7 +160,7 @@ const Z = ({
|
|
|
160
160
|
return /* @__PURE__ */ l("div", { children: [
|
|
161
161
|
o,
|
|
162
162
|
/* @__PURE__ */ a(
|
|
163
|
-
|
|
163
|
+
b,
|
|
164
164
|
{
|
|
165
165
|
...r,
|
|
166
166
|
multiple: !0,
|
|
@@ -171,32 +171,38 @@ const Z = ({
|
|
|
171
171
|
}
|
|
172
172
|
)
|
|
173
173
|
] });
|
|
174
|
-
case "datepicker":
|
|
174
|
+
case "datepicker": {
|
|
175
|
+
const {
|
|
176
|
+
mode: n,
|
|
177
|
+
value: p,
|
|
178
|
+
onChange: L,
|
|
179
|
+
customCalendarProps: E,
|
|
180
|
+
...O
|
|
181
|
+
} = e.datePickerProps || {}, P = {
|
|
182
|
+
value: r.value,
|
|
183
|
+
onChange: e.disabled || e.calendarRange ? void 0 : (u) => r.onChange(u),
|
|
184
|
+
placeholder: e.placeholder,
|
|
185
|
+
disabled: e.disabled,
|
|
186
|
+
customCalendarProps: e.disabled ? {
|
|
187
|
+
disabled: !0,
|
|
188
|
+
mode: "single"
|
|
189
|
+
} : e.calendarRange ? {
|
|
190
|
+
mode: "range",
|
|
191
|
+
selected: r.value,
|
|
192
|
+
onSelect: (u) => r.onChange(u)
|
|
193
|
+
} : void 0,
|
|
194
|
+
...O
|
|
195
|
+
};
|
|
175
196
|
return /* @__PURE__ */ l("div", { className: "relative", children: [
|
|
176
197
|
o,
|
|
177
|
-
/* @__PURE__ */ a(
|
|
178
|
-
F,
|
|
179
|
-
{
|
|
180
|
-
value: r.value,
|
|
181
|
-
onChange: e.disabled || e.calendarRange ? void 0 : (n) => r.onChange(n),
|
|
182
|
-
placeholder: e.placeholder,
|
|
183
|
-
disabled: e.disabled,
|
|
184
|
-
customCalendarProps: e.disabled ? {
|
|
185
|
-
disabled: !0,
|
|
186
|
-
mode: "single"
|
|
187
|
-
} : e.calendarRange ? {
|
|
188
|
-
mode: "range",
|
|
189
|
-
selected: r.value,
|
|
190
|
-
onSelect: (n) => r.onChange(n)
|
|
191
|
-
} : void 0
|
|
192
|
-
}
|
|
193
|
-
)
|
|
198
|
+
/* @__PURE__ */ a(j, { ...P })
|
|
194
199
|
] });
|
|
200
|
+
}
|
|
195
201
|
case "checkbox":
|
|
196
202
|
return /* @__PURE__ */ l("div", { className: "space-y-1.5", children: [
|
|
197
203
|
/* @__PURE__ */ l("div", { className: "flex items-center gap-2", children: [
|
|
198
204
|
/* @__PURE__ */ a(
|
|
199
|
-
|
|
205
|
+
R,
|
|
200
206
|
{
|
|
201
207
|
...r,
|
|
202
208
|
id: e.name,
|
|
@@ -209,14 +215,14 @@ const Z = ({
|
|
|
209
215
|
t,
|
|
210
216
|
{
|
|
211
217
|
htmlFor: e.name,
|
|
212
|
-
className:
|
|
218
|
+
className: d(
|
|
213
219
|
"cursor-pointer",
|
|
214
220
|
e.disabled && "cursor-not-allowed opacity-60"
|
|
215
221
|
),
|
|
216
222
|
children: e.label
|
|
217
223
|
}
|
|
218
224
|
),
|
|
219
|
-
|
|
225
|
+
s && /* @__PURE__ */ a("span", { className: "text-d-destructive text-xs", children: s })
|
|
220
226
|
] }),
|
|
221
227
|
e.caption && /* @__PURE__ */ a(
|
|
222
228
|
i,
|
|
@@ -242,7 +248,7 @@ const Z = ({
|
|
|
242
248
|
)
|
|
243
249
|
] }),
|
|
244
250
|
/* @__PURE__ */ a(
|
|
245
|
-
|
|
251
|
+
$,
|
|
246
252
|
{
|
|
247
253
|
id: e.name,
|
|
248
254
|
checked: !!r.value,
|
|
@@ -251,13 +257,13 @@ const Z = ({
|
|
|
251
257
|
}
|
|
252
258
|
)
|
|
253
259
|
] }),
|
|
254
|
-
|
|
260
|
+
s && /* @__PURE__ */ a("span", { className: "text-d-destructive text-xs", children: s })
|
|
255
261
|
] });
|
|
256
262
|
case "slider":
|
|
257
263
|
return /* @__PURE__ */ l("div", { children: [
|
|
258
264
|
o,
|
|
259
265
|
/* @__PURE__ */ a(
|
|
260
|
-
|
|
266
|
+
T,
|
|
261
267
|
{
|
|
262
268
|
value: Array.isArray(r.value) ? r.value : [r.value || e.min || 0],
|
|
263
269
|
onValueChange: (n) => r.onChange(n[0]),
|
|
@@ -282,26 +288,26 @@ const Z = ({
|
|
|
282
288
|
}
|
|
283
289
|
) });
|
|
284
290
|
};
|
|
285
|
-
return /* @__PURE__ */ l("form", { onSubmit:
|
|
286
|
-
/* @__PURE__ */ a("div", { className:
|
|
291
|
+
return /* @__PURE__ */ l("form", { onSubmit: f((e) => C?.(e)), children: [
|
|
292
|
+
/* @__PURE__ */ a("div", { className: d("grid gap-4", `grid-cols-${m}`), children: h.map((e, c) => /* @__PURE__ */ a(
|
|
287
293
|
"div",
|
|
288
294
|
{
|
|
289
|
-
className:
|
|
290
|
-
children:
|
|
295
|
+
className: d(c === h.length - 1 && "col-span-full"),
|
|
296
|
+
children: w(e)
|
|
291
297
|
},
|
|
292
298
|
e.name
|
|
293
299
|
)) }),
|
|
294
|
-
|
|
295
|
-
|
|
300
|
+
N && /* @__PURE__ */ a("div", { className: "mt-4 flex justify-end", children: /* @__PURE__ */ a(
|
|
301
|
+
F,
|
|
296
302
|
{
|
|
297
303
|
type: "submit",
|
|
298
|
-
disabled: !
|
|
299
|
-
isLoading:
|
|
300
|
-
children:
|
|
304
|
+
disabled: !V || !k || v,
|
|
305
|
+
isLoading: v,
|
|
306
|
+
children: x
|
|
301
307
|
}
|
|
302
308
|
) })
|
|
303
309
|
] });
|
|
304
310
|
};
|
|
305
311
|
export {
|
|
306
|
-
|
|
312
|
+
ne as AppForm
|
|
307
313
|
};
|
|
@@ -1,109 +1,135 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsxs as
|
|
3
|
-
import { designTokens as
|
|
4
|
-
import { Calendar as
|
|
5
|
-
import { Icon as
|
|
6
|
-
import { Label as
|
|
7
|
-
import { Popover as
|
|
8
|
-
import { cn as
|
|
2
|
+
import { jsxs as h, jsx as n } from "react/jsx-runtime";
|
|
3
|
+
import { designTokens as r } from "../design-tokens.js";
|
|
4
|
+
import { Calendar as O } from "./calendar.js";
|
|
5
|
+
import { Icon as J } from "./icon.js";
|
|
6
|
+
import { Label as K } from "./label.js";
|
|
7
|
+
import { Popover as Q, PopoverTrigger as U, PopoverContent as W } from "./popover.js";
|
|
8
|
+
import { cn as k } from "../../lib/utils.js";
|
|
9
9
|
import * as d from "react";
|
|
10
|
-
import { useEffect as
|
|
11
|
-
import { it as
|
|
12
|
-
import { formatDate as
|
|
13
|
-
import { isSameDay as
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
10
|
+
import { useEffect as X } from "react";
|
|
11
|
+
import { it as Y } from "../../node_modules/date-fns/locale/it.js";
|
|
12
|
+
import { formatDate as v } from "../../node_modules/date-fns/format.js";
|
|
13
|
+
import { isSameDay as Z } from "../../node_modules/date-fns/isSameDay.js";
|
|
14
|
+
function de(e) {
|
|
15
|
+
const {
|
|
16
|
+
placeholder: F = "Seleziona data",
|
|
17
|
+
dateFormat: g = "dd/MM/yyyy",
|
|
18
|
+
className: R,
|
|
19
|
+
disabled: s = !1,
|
|
20
|
+
size: m = "default",
|
|
21
|
+
firstDate: p,
|
|
22
|
+
lastDate: b,
|
|
23
|
+
availableDates: C,
|
|
24
|
+
locale: l = Y,
|
|
25
|
+
initialCalendarMonth: c,
|
|
26
|
+
customCalendarProps: x,
|
|
27
|
+
label: D,
|
|
28
|
+
wrpClassName: T,
|
|
29
|
+
id: j,
|
|
30
|
+
"data-testid": V,
|
|
31
|
+
minDate: M,
|
|
32
|
+
maxDate: S,
|
|
33
|
+
numberOfMonths: q
|
|
34
|
+
} = e, a = e.mode === "range", [f, y] = d.useState(
|
|
35
|
+
a ? void 0 : e.value
|
|
36
|
+
), [o, I] = d.useState(
|
|
37
|
+
a ? e.value : void 0
|
|
38
|
+
), [z, u] = d.useState(
|
|
39
|
+
c
|
|
40
|
+
), [N, E] = d.useState(!1), L = (t) => {
|
|
41
|
+
y(t), t && u(t), !a && e.onChange && e.onChange(t);
|
|
42
|
+
}, w = (t) => {
|
|
43
|
+
I(t), t?.from && u(t.from), a && e.onChange && e.onChange(t);
|
|
39
44
|
};
|
|
40
|
-
let
|
|
41
|
-
|
|
42
|
-
(
|
|
43
|
-
(
|
|
45
|
+
let i = [];
|
|
46
|
+
p && i.push({ before: p }), b && i.push({ after: b }), C?.length && i.push(
|
|
47
|
+
(t) => !C.some(
|
|
48
|
+
(H) => Z(H, t)
|
|
44
49
|
)
|
|
45
|
-
),
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
), s && (i = [!0]), X(() => {
|
|
51
|
+
if (a) {
|
|
52
|
+
I(e.value);
|
|
53
|
+
const t = e.value?.from;
|
|
54
|
+
u(t ?? c);
|
|
55
|
+
} else
|
|
56
|
+
y(e.value), u(
|
|
57
|
+
e.value ?? c
|
|
58
|
+
);
|
|
59
|
+
}, [e.value, a, c]);
|
|
60
|
+
const A = d.useId(), P = j ?? A, B = a ? !!o?.from : !!f, G = () => a && o ? /* @__PURE__ */ h("span", { children: [
|
|
61
|
+
o.from && v(o.from, g, { locale: l }),
|
|
62
|
+
o.from && o.to && " - ",
|
|
63
|
+
o.to && v(o.to, g, { locale: l })
|
|
64
|
+
] }) : !a && f ? /* @__PURE__ */ n("span", { children: v(f, g, { locale: l }) }) : /* @__PURE__ */ n("span", { className: "text-d-muted-foreground", children: F });
|
|
65
|
+
return /* @__PURE__ */ h("div", { className: k("flex flex-col gap-1.5", T), children: [
|
|
66
|
+
D && /* @__PURE__ */ n(K, { htmlFor: P, children: D }),
|
|
67
|
+
/* @__PURE__ */ h(Q, { open: s ? !1 : N, onOpenChange: E, children: [
|
|
68
|
+
/* @__PURE__ */ n(U, { asChild: !0, children: /* @__PURE__ */ h(
|
|
53
69
|
"div",
|
|
54
70
|
{
|
|
55
|
-
id:
|
|
56
|
-
"data-testid":
|
|
57
|
-
className:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
71
|
+
id: P,
|
|
72
|
+
"data-testid": V,
|
|
73
|
+
className: k(
|
|
74
|
+
r.input.base,
|
|
75
|
+
r.radius.default,
|
|
76
|
+
r.text.base,
|
|
77
|
+
r.interaction.disabled,
|
|
62
78
|
"flex items-center gap-2 font-normal whitespace-nowrap [&>span]:line-clamp-1",
|
|
63
|
-
|
|
64
|
-
|
|
79
|
+
r.focusRing,
|
|
80
|
+
N && r.activeRing,
|
|
65
81
|
"hover:border-d-ring cursor-pointer transition-colors",
|
|
66
|
-
!
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
82
|
+
!B && "text-d-muted-foreground",
|
|
83
|
+
s && "cursor-not-allowed opacity-50",
|
|
84
|
+
m === "default" && r.sizes.default,
|
|
85
|
+
m === "sm" && r.sizes.sm,
|
|
86
|
+
m === "lg" && r.sizes.lg,
|
|
87
|
+
R
|
|
72
88
|
),
|
|
73
|
-
"aria-disabled":
|
|
89
|
+
"aria-disabled": s,
|
|
74
90
|
role: "button",
|
|
75
|
-
tabIndex:
|
|
76
|
-
onClick:
|
|
91
|
+
tabIndex: s ? -1 : 0,
|
|
92
|
+
onClick: s ? void 0 : () => {
|
|
77
93
|
},
|
|
78
94
|
children: [
|
|
79
|
-
/* @__PURE__ */
|
|
80
|
-
/* @__PURE__ */
|
|
81
|
-
e.from && a(e.from, f),
|
|
82
|
-
e.from && e.to && " - ",
|
|
83
|
-
e.to && a(e.to, f)
|
|
84
|
-
] }) : c ? /* @__PURE__ */ t("span", { children: a(c, f) }) : /* @__PURE__ */ t("span", { className: "text-d-muted-foreground", children: P }) })
|
|
95
|
+
/* @__PURE__ */ n(J, { name: "Calendar", size: m === "lg" ? "sm" : "xs" }),
|
|
96
|
+
/* @__PURE__ */ n("div", { children: G() })
|
|
85
97
|
]
|
|
86
98
|
}
|
|
87
99
|
) }),
|
|
88
|
-
/* @__PURE__ */
|
|
89
|
-
|
|
100
|
+
/* @__PURE__ */ n(W, { className: "w-auto p-0 shadow", children: a ? /* @__PURE__ */ n(
|
|
101
|
+
O,
|
|
90
102
|
{
|
|
91
|
-
...
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
103
|
+
...x || {},
|
|
104
|
+
mode: "range",
|
|
105
|
+
selected: o,
|
|
106
|
+
onSelect: w,
|
|
107
|
+
autoFocus: !0,
|
|
108
|
+
disabled: i,
|
|
109
|
+
locale: l,
|
|
110
|
+
defaultMonth: z,
|
|
111
|
+
numberOfMonths: q ?? 1,
|
|
112
|
+
minDate: M,
|
|
113
|
+
maxDate: S
|
|
114
|
+
}
|
|
115
|
+
) : /* @__PURE__ */ n(
|
|
116
|
+
O,
|
|
117
|
+
{
|
|
118
|
+
...x || {},
|
|
119
|
+
mode: "single",
|
|
120
|
+
selected: f,
|
|
121
|
+
onSelect: L,
|
|
96
122
|
autoFocus: !0,
|
|
97
|
-
disabled:
|
|
98
|
-
locale:
|
|
99
|
-
defaultMonth:
|
|
100
|
-
minDate:
|
|
101
|
-
maxDate:
|
|
123
|
+
disabled: i,
|
|
124
|
+
locale: l,
|
|
125
|
+
defaultMonth: z,
|
|
126
|
+
minDate: M,
|
|
127
|
+
maxDate: S
|
|
102
128
|
}
|
|
103
129
|
) })
|
|
104
130
|
] })
|
|
105
131
|
] });
|
|
106
132
|
}
|
|
107
133
|
export {
|
|
108
|
-
|
|
134
|
+
de as DatePicker
|
|
109
135
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { Command as Command_2 } from 'cmdk';
|
|
|
11
11
|
import { ComponentProps } from 'react';
|
|
12
12
|
import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
|
|
13
13
|
import { ControllerProps } from 'react-hook-form';
|
|
14
|
+
import { DateRange } from 'react-day-picker';
|
|
14
15
|
import { DayPicker } from 'react-day-picker';
|
|
15
16
|
import { default as default_2 } from 'react';
|
|
16
17
|
import { default as default_3 } from 'embla-carousel-react';
|
|
@@ -244,6 +245,7 @@ export declare interface AppFormItem {
|
|
|
244
245
|
noResultsMessage?: string;
|
|
245
246
|
debounce?: number;
|
|
246
247
|
clearable?: boolean;
|
|
248
|
+
datePickerProps?: Partial<ComponentProps<typeof DatePicker>>;
|
|
247
249
|
}
|
|
248
250
|
|
|
249
251
|
declare interface AppFormProps {
|
|
@@ -1548,11 +1550,9 @@ export declare interface DataTableState<TData = Record<string, unknown>> {
|
|
|
1548
1550
|
columnVisibility?: Partial<Record<keyof TData, boolean>>;
|
|
1549
1551
|
}
|
|
1550
1552
|
|
|
1551
|
-
export declare function DatePicker(
|
|
1553
|
+
export declare function DatePicker(props: DatePickerProps): JSX.Element;
|
|
1552
1554
|
|
|
1553
|
-
|
|
1554
|
-
value?: Date;
|
|
1555
|
-
onChange?: (date: Date | undefined) => void;
|
|
1555
|
+
declare interface DatePickerBaseProps {
|
|
1556
1556
|
placeholder?: string;
|
|
1557
1557
|
dateFormat?: string;
|
|
1558
1558
|
className?: string;
|
|
@@ -1571,6 +1571,21 @@ export declare interface DatePickerProps {
|
|
|
1571
1571
|
"data-testid"?: string;
|
|
1572
1572
|
minDate?: Date;
|
|
1573
1573
|
maxDate?: Date;
|
|
1574
|
+
numberOfMonths?: number;
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
export declare type DatePickerProps = DatePickerSingleProps | DatePickerRangeProps;
|
|
1578
|
+
|
|
1579
|
+
declare interface DatePickerRangeProps extends DatePickerBaseProps {
|
|
1580
|
+
mode: "range";
|
|
1581
|
+
value?: DateRange;
|
|
1582
|
+
onChange?: (range: DateRange | undefined) => void;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
declare interface DatePickerSingleProps extends DatePickerBaseProps {
|
|
1586
|
+
mode?: "single";
|
|
1587
|
+
value?: Date;
|
|
1588
|
+
onChange?: (date: Date | undefined) => void;
|
|
1574
1589
|
}
|
|
1575
1590
|
|
|
1576
1591
|
/**
|