laif-ds 0.2.69 → 0.2.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -212,6 +212,8 @@ Date picker component with optional range selection via `calendarRange`. Use `da
212
212
  - `firstDate`: First available date (disables dates before)
213
213
  - `lastDate`: Last available date (disables dates after)
214
214
  - `availableDates`: Array of specific dates that are selectable
215
+ - `showTime`: Show time picker columns (HH, MM)
216
+ - `withSeconds`: Show seconds column in the time picker (requires `showTime`)
215
217
  - And other DatePicker props
216
218
 
217
219
  **Example with English locale:**
@@ -227,7 +229,8 @@ const items: AppFormItem[] = [
227
229
  placeholder: "Pick a date",
228
230
  datePickerProps: {
229
231
  locale: enUS,
230
- dateFormat: "MM/dd/yyyy",
232
+ dateFormat: "MM/dd/yyyy HH:mm",
233
+ showTime: true,
231
234
  },
232
235
  },
233
236
  {
@@ -0,0 +1,304 @@
1
+ # AppTimePicker
2
+
3
+ ## Overview
4
+
5
+ Standalone time picker component for selecting hours, minutes, and optionally seconds. Displays a trigger with a clock icon and opens a popover with scrollable columns for each time unit. Supports controlled/uncontrolled usage, UTC mode, clearable selection, min/max time constraints, multiple sizes, and visual variants.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ | ---------------- | ----------------------------------------------------------------------------- | -------------------- | ------------------------------------------------------------------------ |
13
+ | `value` | `Date` | `undefined` | Controlled selected time as a Date object. |
14
+ | `onChange` | `(date: Date \| undefined) => void` | `undefined` | Callback fired when the selected time changes. |
15
+ | `onClear` | `() => void` | `undefined` | Callback fired when the value is cleared. |
16
+ | `label` | `string \| React.ReactNode` | `undefined` | Label displayed above the trigger. |
17
+ | `placeholder` | `string` | `"Seleziona orario"` | Placeholder text shown when no time is selected. |
18
+ | `disabled` | `boolean` | `false` | Disables the time picker. |
19
+ | `clearable` | `boolean` | `false` | Show a clear (X) button in the trigger to reset the selection. |
20
+ | `className` | `string` | `""` | Additional CSS classes applied to the trigger element. |
21
+ | `labelClassName` | `string` | `""` | CSS classes for the label element. |
22
+ | `wrpClassName` | `string` | `""` | CSS classes for the outer wrapper `<div>`. |
23
+ | `size` | `"sm" \| "default" \| "lg"` | `"default"` | Size variant of the trigger. |
24
+ | `variant` | `"default" \| "destructive" \| "outline" \| "secondary" \| "ghost" \| "link"` | `"default"` | Visual variant of the trigger. |
25
+ | `useUtc` | `boolean` | `false` | Use UTC time instead of local time. Shows a "UTC" badge. |
26
+ | `withSeconds` | `boolean` | `false` | Show a seconds column in the time picker. |
27
+ | `minTime` | `Date` | `undefined` | Minimum selectable time. Hours/minutes/seconds before this are disabled. |
28
+ | `maxTime` | `Date` | `undefined` | Maximum selectable time. Hours/minutes/seconds after this are disabled. |
29
+ | `id` | `string` | `undefined` | HTML `id` for the trigger element. |
30
+ | `data-testid` | `string` | `undefined` | `data-testid` attribute for E2E testing (e.g. Playwright). |
31
+
32
+ ---
33
+
34
+ ## Behavior
35
+
36
+ ### Time Selection
37
+
38
+ - **Columns**: The popover displays scrollable columns for hours (00–23) and minutes (00–59). An optional seconds column (00–59) is shown when `withSeconds` is `true`.
39
+ - **Scroll-to-selected**: When the popover opens, the selected value is automatically scrolled into view.
40
+ - **Display format**: The trigger shows time in `HH:MM` format (or `HH:MM:SS` with `withSeconds`).
41
+
42
+ ### Controlled vs Uncontrolled
43
+
44
+ - **Controlled**: Pass `value` and `onChange` to manage state externally. The component detects controlled mode by checking if the `value` prop is provided (even if `undefined`).
45
+ - **Uncontrolled**: Omit the `value` prop entirely. The component manages its own internal state.
46
+
47
+ ### Clearable
48
+
49
+ - **Trigger clear button**: When `clearable` is `true` and a value is selected, an X button appears in the trigger.
50
+ - **Popover clear button**: A "Clear" button always appears at the bottom of the popover when a value is selected.
51
+ - **Callbacks**: Both `onChange(undefined)` and `onClear()` are called when clearing.
52
+
53
+ ### Min/Max Time Constraints
54
+
55
+ - **Disabled options**: When `minTime` or `maxTime` is set, out-of-range hours are visually disabled and not selectable.
56
+ - **Cascading constraints**: Minutes are constrained only when the selected hour matches the boundary hour. Seconds are constrained only when both hour and minute match.
57
+ - **UTC-aware**: Constraints respect the `useUtc` setting.
58
+
59
+ ### UTC Mode
60
+
61
+ - When `useUtc` is `true`, all time reading/writing uses UTC methods (`getUTCHours`, `setUTCHours`, etc.).
62
+ - A small "UTC" badge is displayed in the trigger.
63
+
64
+ ---
65
+
66
+ ## Exported Types
67
+
68
+ ```ts
69
+ type AppTimePickerSize = "sm" | "default" | "lg";
70
+
71
+ type AppTimePickerVariant =
72
+ | "default"
73
+ | "destructive"
74
+ | "outline"
75
+ | "secondary"
76
+ | "ghost"
77
+ | "link";
78
+
79
+ interface AppTimePickerProps {
80
+ /* see Props table above */
81
+ }
82
+ ```
83
+
84
+ ---
85
+
86
+ ## Examples
87
+
88
+ ### Basic
89
+
90
+ ```tsx
91
+ import { AppTimePicker } from "laif-ds";
92
+ import { useState } from "react";
93
+
94
+ export function BasicTimePicker() {
95
+ const [time, setTime] = useState<Date | undefined>();
96
+
97
+ return (
98
+ <AppTimePicker
99
+ value={time}
100
+ onChange={setTime}
101
+ label="Select Time"
102
+ placeholder="Pick a time"
103
+ />
104
+ );
105
+ }
106
+ ```
107
+
108
+ ### With Seconds
109
+
110
+ ```tsx
111
+ import { AppTimePicker } from "laif-ds";
112
+ import { useState } from "react";
113
+
114
+ export function TimePickerWithSeconds() {
115
+ const [time, setTime] = useState<Date | undefined>();
116
+
117
+ return (
118
+ <AppTimePicker
119
+ value={time}
120
+ onChange={setTime}
121
+ withSeconds
122
+ label="Time with Seconds"
123
+ />
124
+ );
125
+ }
126
+ ```
127
+
128
+ ### Clearable
129
+
130
+ ```tsx
131
+ import { AppTimePicker } from "laif-ds";
132
+ import { useState } from "react";
133
+
134
+ export function ClearableTimePicker() {
135
+ const [time, setTime] = useState<Date | undefined>(new Date());
136
+
137
+ return (
138
+ <AppTimePicker
139
+ value={time}
140
+ onChange={setTime}
141
+ clearable
142
+ label="Clearable Picker"
143
+ />
144
+ );
145
+ }
146
+ ```
147
+
148
+ ### UTC Mode
149
+
150
+ ```tsx
151
+ import { AppTimePicker } from "laif-ds";
152
+ import { useState } from "react";
153
+
154
+ export function UtcTimePicker() {
155
+ const [time, setTime] = useState<Date | undefined>(new Date());
156
+
157
+ return (
158
+ <AppTimePicker
159
+ value={time}
160
+ onChange={setTime}
161
+ useUtc
162
+ label="UTC Time Picker"
163
+ />
164
+ );
165
+ }
166
+ ```
167
+
168
+ ### Min/Max Time Constraints
169
+
170
+ ```tsx
171
+ import { AppTimePicker } from "laif-ds";
172
+ import { useState } from "react";
173
+
174
+ export function BusinessHoursTimePicker() {
175
+ const [time, setTime] = useState<Date | undefined>();
176
+
177
+ const minTime = new Date();
178
+ minTime.setHours(9, 0, 0, 0);
179
+
180
+ const maxTime = new Date();
181
+ maxTime.setHours(17, 30, 0, 0);
182
+
183
+ return (
184
+ <AppTimePicker
185
+ value={time}
186
+ onChange={setTime}
187
+ minTime={minTime}
188
+ maxTime={maxTime}
189
+ label="Business Hours Only"
190
+ />
191
+ );
192
+ }
193
+ ```
194
+
195
+ ### Sizes and Variants
196
+
197
+ ```tsx
198
+ import { AppTimePicker } from "laif-ds";
199
+
200
+ export function TimePickerVariants() {
201
+ return (
202
+ <div className="flex flex-col gap-4">
203
+ <AppTimePicker size="sm" label="Small" />
204
+ <AppTimePicker size="default" label="Default" />
205
+ <AppTimePicker size="lg" label="Large" />
206
+ <AppTimePicker variant="outline" label="Outline Variant" />
207
+ <AppTimePicker variant="ghost" label="Ghost Variant" />
208
+ </div>
209
+ );
210
+ }
211
+ ```
212
+
213
+ ### Disabled
214
+
215
+ ```tsx
216
+ import { AppTimePicker } from "laif-ds";
217
+
218
+ export function DisabledTimePicker() {
219
+ return <AppTimePicker value={new Date()} disabled label="Disabled Picker" />;
220
+ }
221
+ ```
222
+
223
+ ### In Dialog
224
+
225
+ ```tsx
226
+ import { AppTimePicker } from "laif-ds";
227
+ import { AppDialog } from "laif-ds";
228
+ import { Button } from "laif-ds";
229
+ import { useState } from "react";
230
+
231
+ export function TimePickerInDialog() {
232
+ const [time, setTime] = useState<Date | undefined>();
233
+ const [open, setOpen] = useState(false);
234
+
235
+ return (
236
+ <AppDialog
237
+ open={open}
238
+ onOpenChange={setOpen}
239
+ title="Seleziona Orario"
240
+ description="Scegli l'orario per la tua prenotazione."
241
+ trigger={<Button>Apri Time Picker Dialog</Button>}
242
+ footer={
243
+ <>
244
+ <Button variant="outline" onClick={() => setOpen(false)}>
245
+ Annulla
246
+ </Button>
247
+ <Button onClick={() => setOpen(false)}>Conferma</Button>
248
+ </>
249
+ }
250
+ asChild
251
+ >
252
+ <div className="space-y-4">
253
+ <AppTimePicker
254
+ value={time}
255
+ onChange={setTime}
256
+ label="Orario di inizio"
257
+ placeholder="Seleziona un'orario"
258
+ clearable
259
+ />
260
+ {time && (
261
+ <div className="bg-d-muted/50 flex items-center gap-2 rounded border p-3 text-sm">
262
+ <span className="text-d-muted-foreground">Orario selezionato:</span>
263
+ <span className="font-medium tabular-nums">
264
+ {time.toLocaleTimeString("it-IT", {
265
+ hour: "2-digit",
266
+ minute: "2-digit",
267
+ })}
268
+ </span>
269
+ </div>
270
+ )}
271
+ </div>
272
+ </AppDialog>
273
+ );
274
+ }
275
+ ```
276
+
277
+ ---
278
+
279
+ ## Helper Component: TimePickerColumn
280
+
281
+ The `TimePickerColumn` component is exported and can be used independently (e.g., inside the `DatePicker` component for datetime selection).
282
+
283
+ ### TimePickerColumn Props
284
+
285
+ | Prop | Type | Default | Description |
286
+ | ---------------- | -------------------------------- | ----------- | ------------------------------------------------------- |
287
+ | `options` | `number[]` | — | Array of numeric options to display. |
288
+ | `value` | `number \| undefined` | `undefined` | Currently selected value. |
289
+ | `onChange` | `(value: number) => void` | — | Callback fired when an option is selected. |
290
+ | `type` | `"hour" \| "minute" \| "second"` | — | Column type — determines the header label (HH, MM, SS). |
291
+ | `className` | `string` | `""` | Additional CSS classes for the column wrapper. |
292
+ | `disabledValues` | `Set<number>` | `undefined` | Set of values that should be disabled (not selectable). |
293
+
294
+ ---
295
+
296
+ ## Notes
297
+
298
+ - **Sizing**: Use `size` to control the trigger height (sm: h-8, default: h-9, lg: h-10).
299
+ - **Variants**: Use `variant` to change the trigger's visual style (background, border, text color).
300
+ - **UTC badge**: When `useUtc` is `true`, a small "UTC" label appears in the trigger for clarity.
301
+ - **Controlled detection**: The component uses `props.hasOwnProperty("value")` to detect controlled mode, so passing `value={undefined}` keeps it controlled.
302
+ - **Performance**: Option arrays (0–23 for hours, 0–59 for minutes/seconds) are memoized to avoid re-creation on every render.
303
+ - **Accessibility**: The trigger has proper ARIA attributes. Disabled options in the columns are not focusable.
304
+ - **Integration with DatePicker**: The `TimePickerColumn` sub-component is reused by `DatePicker` when `showTime` is enabled.
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Overview
4
4
 
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.
5
+ Date picker component that supports both **single date** and **date range** selection, with optional **time picker** columns. 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, clearable selection, and initial calendar month.
6
6
 
7
7
  ---
8
8
 
@@ -10,34 +10,45 @@ Date picker component that supports both **single date** and **date range** sele
10
10
 
11
11
  ### Common Props
12
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). |
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. Auto-adjusts with `showTime`. |
18
+ | `className` | `string` | `""` | Additional classes for the trigger element. |
19
+ | `wrpClassName` | `string` | `""` | Additional classes for the outer wrapper `<div>`. |
20
+ | `labelClassName` | `string` | `""` | Additional classes for the label element. |
21
+ | `label` | `string \| React.ReactNode` | `undefined` | Label displayed above the date picker. |
22
+ | `disabled` | `boolean` | `false` | Disables interactions and the popover. |
23
+ | `size` | `"sm" \| "default" \| "lg"` | `"default"` | Trigger size affecting height and icon size. |
24
+ | `clearable` | `boolean` | `false` | Show a clear (X) button to reset the selection. |
25
+ | `onClear` | `() => void` | `undefined` | Callback fired when the value is cleared via the clear button. |
26
+ | `minDate` | `Date` | `undefined` | Minimum selectable date. Dates before this are disabled. |
27
+ | `maxDate` | `Date` | `undefined` | Maximum selectable date. Dates after this are disabled. |
28
+ | `availableDates` | `Date[]` | `undefined` | Only these dates are selectable; all others are disabled. |
29
+ | `locale` | `Partial<Locale>` | `it` (Italian) | Locale for date formatting (from date-fns). |
30
+ | `initialCalendarMonth` | `Date` | `undefined` | Initial month to display in calendar (overridden by value). |
31
+ | `numberOfMonths` | `number` | `1` | Number of months to display side-by-side (useful for range mode). |
32
+ | `customCalendarProps` | `React.ComponentProps<typeof Calendar>` | `undefined` | Custom props forwarded to the underlying Calendar component. |
33
+ | `id` | `string` | auto-generated | HTML id attribute for the trigger element. |
34
+ | `data-testid` | `string` | `undefined` | Test identifier attribute for E2E testing (e.g. Playwright). |
35
+
36
+ #### Deprecated Common Props
37
+
38
+ | Prop | Type | Replacement | Description |
39
+ | --------------- | -------- | ----------- | ---------------------------------------------------------- |
40
+ | `firstDate` | `Date` | `minDate` | ⚠️ Deprecated. Use `minDate` instead. |
41
+ | `lastDate` | `Date` | `maxDate` | ⚠️ Deprecated. Use `maxDate` instead. |
42
+ | `buttonVariant` | `string` | `className` | ⚠️ Deprecated. This prop is unused. Style via `className`. |
34
43
 
35
44
  ### Single Mode Props (mode="single" or undefined)
36
45
 
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. |
46
+ | Prop | Type | Default | Description |
47
+ | ------------- | ----------------------------------- | ----------- | ------------------------------------------------------------- |
48
+ | `value` | `Date` | `undefined` | Controlled selected date. |
49
+ | `onChange` | `(date: Date \| undefined) => void` | `undefined` | Called when the date changes. |
50
+ | `showTime` | `boolean` | `false` | Show time picker columns (HH, MM) alongside the calendar. |
51
+ | `withSeconds` | `boolean` | `false` | Show seconds column in the time picker (requires `showTime`). |
41
52
 
42
53
  ### Range Mode Props (mode="range")
43
54
 
@@ -61,9 +72,23 @@ Date picker component that supports both **single date** and **date range** sele
61
72
  - **Display**: Shows "from - to" format in the trigger (e.g., "13/01/2025 - 20/01/2025").
62
73
  - **Multiple months**: Use `numberOfMonths={2}` to show two months side by side for easier range selection.
63
74
 
75
+ ### Time Picker (Single Mode Only)
76
+
77
+ - **Activation**: Set `showTime` to display hour and minute columns next to the calendar.
78
+ - **Seconds**: Set `withSeconds` alongside `showTime` to add a seconds column.
79
+ - **Auto-close**: When `showTime` is enabled, the popover stays open after selecting a date so the user can adjust the time. Without `showTime`, the popover closes on date selection.
80
+ - **Format auto-detection**: If no `dateFormat` is provided, the component automatically uses `"dd/MM/yyyy HH:mm"` (or `"dd/MM/yyyy HH:mm:ss"` with `withSeconds`).
81
+ - **Time preservation**: When changing the date, the previously selected time is preserved.
82
+
83
+ ### Clearable
84
+
85
+ - **Clear button**: When `clearable` is `true` and a value is selected, an X button appears in the trigger.
86
+ - **Callback**: The `onClear` callback fires when the clear button is clicked.
87
+ - **Works in both modes**: Clearing resets the value to `undefined` in both single and range modes.
88
+
64
89
  ### Common Behavior
65
90
 
66
- - **Disabled dates**: `firstDate`, `lastDate`, `minDate`, `maxDate`, and `availableDates` are combined into the `Calendar`'s `disabled` matcher array.
91
+ - **Disabled dates**: `minDate`, `maxDate`, and `availableDates` are combined into the `Calendar`'s `disabled` matcher array. Legacy `firstDate`/`lastDate` are also supported.
67
92
  - **Disabled state**: When `disabled` is true, the popover will not open and the trigger is non-interactive with reduced opacity.
68
93
  - **Formatting**: `dateFormat` is applied via `date-fns/format` to the selected date(s) in the trigger.
69
94
  - **Calendar month**: The calendar displays the month of the selected date (or `from` date in range mode), or `initialCalendarMonth` if no date is selected.
@@ -180,19 +205,65 @@ export function RangeWithConstraints() {
180
205
  }
181
206
  ```
182
207
 
183
- ### Configurable
208
+ ### Clearable
184
209
 
185
210
  ```tsx
186
211
  import { DatePicker } from "laif-ds";
212
+ import { useState } from "react";
213
+
214
+ export function ClearableDatePicker() {
215
+ const [date, setDate] = useState<Date | undefined>(new Date());
187
216
 
188
- export function ConfigurableDatePicker() {
189
217
  return (
190
218
  <DatePicker
191
- value={new Date()}
192
- placeholder="Seleziona una data"
193
- dateFormat="PPP"
194
- className="w-[300px]"
195
- buttonVariant="outline"
219
+ value={date}
220
+ onChange={setDate}
221
+ placeholder="Seleziona data"
222
+ clearable
223
+ onClear={() => console.log("cleared!")}
224
+ label="Data cancellabile"
225
+ />
226
+ );
227
+ }
228
+ ```
229
+
230
+ ### With Time Picker
231
+
232
+ ```tsx
233
+ import { DatePicker } from "laif-ds";
234
+ import { useState } from "react";
235
+
236
+ export function DateTimePicker() {
237
+ const [date, setDate] = useState<Date | undefined>();
238
+
239
+ return (
240
+ <DatePicker
241
+ value={date}
242
+ onChange={setDate}
243
+ showTime
244
+ label="Data e ora"
245
+ placeholder="Seleziona data e ora"
246
+ />
247
+ );
248
+ }
249
+ ```
250
+
251
+ ### With Time Picker and Seconds
252
+
253
+ ```tsx
254
+ import { DatePicker } from "laif-ds";
255
+ import { useState } from "react";
256
+
257
+ export function DateTimeWithSeconds() {
258
+ const [date, setDate] = useState<Date | undefined>(new Date());
259
+
260
+ return (
261
+ <DatePicker
262
+ value={date}
263
+ onChange={setDate}
264
+ showTime
265
+ withSeconds
266
+ label="Data e ora con secondi"
196
267
  />
197
268
  );
198
269
  }
@@ -202,14 +273,18 @@ export function ConfigurableDatePicker() {
202
273
 
203
274
  ```tsx
204
275
  import { DatePicker } from "laif-ds";
276
+ import { useState } from "react";
205
277
 
206
278
  export function WithMinMaxDates() {
279
+ const [date, setDate] = useState<Date | undefined>();
280
+
207
281
  return (
208
282
  <DatePicker
209
- placeholder="Seleziona una data tra le date minima e massima"
210
- firstDate={new Date("2025-09-20")}
211
- lastDate={new Date("2025-09-28")}
212
- buttonVariant="outline"
283
+ value={date}
284
+ onChange={setDate}
285
+ placeholder="Seleziona una data nel range"
286
+ minDate={new Date("2025-09-20")}
287
+ maxDate={new Date("2025-09-28")}
213
288
  />
214
289
  );
215
290
  }
@@ -219,17 +294,21 @@ export function WithMinMaxDates() {
219
294
 
220
295
  ```tsx
221
296
  import { DatePicker } from "laif-ds";
297
+ import { useState } from "react";
222
298
 
223
299
  export function WithAvailableDates() {
300
+ const [date, setDate] = useState<Date | undefined>();
301
+
224
302
  return (
225
303
  <DatePicker
304
+ value={date}
305
+ onChange={setDate}
226
306
  placeholder="Scegli una delle date disponibili"
227
307
  availableDates={[
228
308
  new Date("2025-09-22"),
229
309
  new Date("2025-09-25"),
230
310
  new Date("2025-09-27"),
231
311
  ]}
232
- buttonVariant="outline"
233
312
  />
234
313
  );
235
314
  }
@@ -335,17 +414,73 @@ export function DatePickerInDialog() {
335
414
  }
336
415
  ```
337
416
 
417
+ ### In Drawer
418
+
419
+ ```tsx
420
+ import { DatePicker } from "laif-ds";
421
+ import {
422
+ Drawer,
423
+ DrawerContent,
424
+ DrawerTrigger,
425
+ DrawerHeader,
426
+ DrawerTitle,
427
+ DrawerDescription,
428
+ DrawerFooter,
429
+ DrawerClose,
430
+ } from "laif-ds";
431
+ import { Button } from "laif-ds";
432
+ import { useState } from "react";
433
+
434
+ export function DatePickerInDrawer() {
435
+ const [date, setDate] = useState<Date | undefined>(new Date("2023-08-12"));
436
+
437
+ return (
438
+ <Drawer>
439
+ <DrawerTrigger asChild>
440
+ <Button variant="outline">Apri Drawer con DatePicker</Button>
441
+ </DrawerTrigger>
442
+ <DrawerContent>
443
+ <DrawerHeader>
444
+ <DrawerTitle>Seleziona una data</DrawerTitle>
445
+ <DrawerDescription>
446
+ Scegli una data dal calendario qui sotto.
447
+ </DrawerDescription>
448
+ </DrawerHeader>
449
+ <div className="px-4 py-4">
450
+ <DatePicker
451
+ placeholder="Seleziona una data"
452
+ value={date}
453
+ onChange={setDate}
454
+ />
455
+ </div>
456
+ {date && (
457
+ <div className="text-d-secondary-foreground px-4 text-sm">
458
+ Data selezionata: {date.toLocaleDateString("it-IT")}
459
+ </div>
460
+ )}
461
+ <DrawerFooter>
462
+ <DrawerClose asChild>
463
+ <Button variant="outline">Chiudi</Button>
464
+ </DrawerClose>
465
+ </DrawerFooter>
466
+ </DrawerContent>
467
+ </Drawer>
468
+ );
469
+ }
470
+ ```
471
+
338
472
  ---
339
473
 
340
474
  ## Notes
341
475
 
342
476
  - **Sizing**: Use `size` to control the trigger height and icon size (sm: h-8, default: h-9, lg: h-10).
343
- - **Popover width**: The popover content automatically sizes to fit the Calendar component.
477
+ - **Popover width**: The popover content automatically sizes to fit the Calendar (and time columns when `showTime` is enabled).
344
478
  - **Internationalization**: Use `locale` prop for calendar localization and `dateFormat` for display formatting.
345
- - **Legacy props**: `firstDate` and `lastDate` are legacy props; prefer `minDate` and `maxDate`.
346
- - **Button variant**: The `buttonVariant` prop is deprecated and not used in the current implementation.
479
+ - **Deprecated props**: `firstDate`/`lastDate` use `minDate`/`maxDate`. `buttonVariant` use `className`.
347
480
  - **Accessibility**: The trigger has proper ARIA attributes and keyboard navigation support.
348
481
  - **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.
482
+ - **Range mode**: Use `mode="range"` for date range selection. The `value` and `onChange` types change accordingly. `showTime` is not available in range mode.
350
483
  - **Multiple months**: In range mode, use `numberOfMonths={2}` to display two months side by side for better UX.
351
484
  - **DateRange type**: Import `DateRange` from `react-day-picker` when using range mode: `{ from?: Date, to?: Date }`.
485
+ - **Clearable**: Use `clearable` to allow users to reset the selection. Works in both single and range modes.
486
+ - **Label styling**: Use `labelClassName` to apply custom styles to the label element.
@@ -30,7 +30,8 @@ This document provides a complete mapping of all components available in the lai
30
30
  - **AsyncSelect** - Select component with asynchronous data loading capabilities
31
31
  - **AppSelect** - Enhanced select dropdown with search and multi-select capabilities
32
32
  - **Checkbox** - Binary selection input for forms
33
- - **DatePicker** - Calendar-based date selection input
33
+ - **AppTimePicker** - Standalone time picker with hours, minutes, seconds columns, min/max constraints, UTC mode, and clearable selection
34
+ - **DatePicker** - Calendar-based date and datetime selection input with single/range modes, time picker, and clearable support
34
35
  - **Form** - Form wrapper component with validation support
35
36
  - **Input** - Text input field with multiple variants and features
36
37
  - **InputOtp** - One-time password input component