@catalystsoftware/ui 1.0.2 → 1.0.5

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.
Files changed (157) hide show
  1. package/data/tailwind.config.js +261 -3821
  2. package/dist/components/catalyst-ui/buttons/burger.tsx +207 -0
  3. package/dist/components/catalyst-ui/core/data-display/timeline.tsx +210 -0
  4. package/dist/components/catalyst-ui/core/feedback/alert.tsx +491 -0
  5. package/dist/components/catalyst-ui/core/feedback/spinner-1.tsx +65 -0
  6. package/dist/components/catalyst-ui/core/feedback/toast.tsx +1857 -0
  7. package/dist/components/catalyst-ui/core/navigation/menu.tsx +164 -0
  8. package/dist/components/catalyst-ui/forms/toggle-class.tsx +176 -0
  9. package/dist/components/catalyst-ui/hooks/use-copy-to-clipboard.tsx +419 -0
  10. package/dist/components/catalyst-ui/hooks/use-counter.tsx +13 -0
  11. package/dist/components/catalyst-ui/hooks/use-event-listener.tsx +23 -0
  12. package/dist/components/catalyst-ui/hooks/use-export-markdown.tsx +47 -0
  13. package/dist/components/catalyst-ui/hooks/use-focus.tsx +17 -0
  14. package/dist/components/catalyst-ui/hooks/use-interval.tsx +23 -0
  15. package/dist/components/catalyst-ui/hooks/use-is-client.tsx +16 -0
  16. package/dist/components/catalyst-ui/hooks/use-media-query.tsx +19 -0
  17. package/dist/components/catalyst-ui/hooks/use-mobile.tsx +19 -0
  18. package/dist/components/catalyst-ui/hooks/use-resize-observer.tsx +81 -0
  19. package/dist/components/catalyst-ui/hooks/use-timeout.tsx +21 -0
  20. package/dist/components/catalyst-ui/hooks/use-timer.tsx +209 -0
  21. package/dist/components/catalyst-ui/hooks/use-toggle.tsx +12 -0
  22. package/dist/components/catalyst-ui/media/image.tsx +13 -0
  23. package/dist/components/catalyst-ui/overlays/dual-sidebar.tsx +4142 -0
  24. package/dist/components/catalyst-ui/overlays/sidebar-original.tsx +726 -0
  25. package/dist/components/catalyst-ui/primitives/accordion.tsx +250 -0
  26. package/dist/components/catalyst-ui/primitives/alert-dialog.tsx +126 -0
  27. package/dist/components/catalyst-ui/primitives/aspect-ratio.tsx +9 -0
  28. package/dist/components/catalyst-ui/primitives/avatar.tsx +296 -0
  29. package/dist/components/catalyst-ui/primitives/badge.tsx +57 -0
  30. package/dist/components/catalyst-ui/primitives/breadcrumb.tsx +101 -0
  31. package/dist/components/catalyst-ui/primitives/button.tsx +265 -0
  32. package/dist/components/catalyst-ui/primitives/calendar-v4.tsx +208 -0
  33. package/dist/components/catalyst-ui/primitives/calendar.tsx +295 -0
  34. package/dist/components/catalyst-ui/primitives/card.tsx +618 -0
  35. package/dist/components/catalyst-ui/primitives/carousel.tsx +238 -0
  36. package/dist/components/catalyst-ui/primitives/chart.tsx +347 -0
  37. package/dist/components/catalyst-ui/primitives/checkbox.tsx +225 -0
  38. package/dist/components/catalyst-ui/primitives/collapsible.tsx +212 -0
  39. package/dist/components/catalyst-ui/primitives/command.tsx +393 -0
  40. package/dist/components/catalyst-ui/primitives/context-menu.tsx +236 -0
  41. package/dist/components/catalyst-ui/primitives/dialog.tsx +471 -0
  42. package/dist/components/catalyst-ui/primitives/drawer.tsx +761 -0
  43. package/dist/components/catalyst-ui/primitives/dropdown-menu.tsx +290 -0
  44. package/dist/components/catalyst-ui/primitives/empty.tsx +104 -0
  45. package/dist/components/catalyst-ui/primitives/field.tsx +244 -0
  46. package/dist/components/catalyst-ui/primitives/hover-card.tsx +124 -0
  47. package/dist/components/catalyst-ui/primitives/input-otp.tsx +76 -0
  48. package/dist/components/catalyst-ui/primitives/input.tsx +64 -0
  49. package/dist/components/catalyst-ui/primitives/item.tsx +196 -0
  50. package/dist/components/catalyst-ui/primitives/kbd.tsx +75 -0
  51. package/dist/components/catalyst-ui/primitives/label.tsx +24 -0
  52. package/dist/components/catalyst-ui/primitives/navigation-menu.tsx +150 -0
  53. package/dist/components/catalyst-ui/primitives/pagination.tsx +198 -0
  54. package/dist/components/catalyst-ui/primitives/popover.tsx +232 -0
  55. package/dist/components/catalyst-ui/primitives/progress.tsx +34 -0
  56. package/dist/components/catalyst-ui/primitives/radio-group.tsx +43 -0
  57. package/dist/components/catalyst-ui/primitives/resizable.tsx +56 -0
  58. package/dist/components/catalyst-ui/primitives/select.tsx +155 -0
  59. package/dist/components/catalyst-ui/primitives/separator.tsx +74 -0
  60. package/dist/components/catalyst-ui/primitives/sheet.tsx +126 -0
  61. package/dist/components/catalyst-ui/primitives/skeleton.tsx +15 -0
  62. package/dist/components/catalyst-ui/primitives/slider.tsx +27 -0
  63. package/dist/components/catalyst-ui/primitives/switch.tsx +187 -0
  64. package/dist/components/catalyst-ui/primitives/tabs.tsx +335 -0
  65. package/dist/components/catalyst-ui/primitives/textarea.tsx +24 -0
  66. package/dist/components/catalyst-ui/primitives/toggle-group.tsx +55 -0
  67. package/dist/components/catalyst-ui/primitives/toggle.tsx +42 -0
  68. package/dist/components/catalyst-ui/primitives/tooltip.tsx +116 -0
  69. package/dist/components/catalyst-ui/utils/basic-auth.tsx +40 -0
  70. package/dist/components/catalyst-ui/utils/context-storage.tsx +19 -0
  71. package/dist/components/catalyst-ui/utils/cors-middleware.tsx +71 -0
  72. package/dist/components/catalyst-ui/utils/deferred-content.tsx +595 -0
  73. package/dist/components/catalyst-ui/utils/honeypot-middleware.tsx +38 -0
  74. package/dist/components/catalyst-ui/utils/incId.tsx +75 -0
  75. package/dist/components/catalyst-ui/utils/jwk-auth.tsx +36 -0
  76. package/dist/components/catalyst-ui/utils/request-id.tsx +14 -0
  77. package/dist/components/catalyst-ui/utils/secure-headers.tsx +37 -0
  78. package/dist/components/catalyst-ui/utils/server-timing.tsx +23 -0
  79. package/dist/components/catalyst-ui/utils/utils.ts +43 -0
  80. package/dist/components/catalyst-ui/utils/with-cookie.tsx +43 -0
  81. package/dist/components/catalyst-ui/x/accordian-x.tsx +428 -0
  82. package/dist/components/catalyst-ui/x/alert-x.tsx +413 -0
  83. package/dist/components/catalyst-ui/x/animated-text-x.tsx +2242 -0
  84. package/dist/components/catalyst-ui/x/avatar-x.tsx +515 -0
  85. package/dist/components/catalyst-ui/x/badge-x.tsx +670 -0
  86. package/dist/components/catalyst-ui/x/button-X.tsx +2857 -0
  87. package/dist/components/catalyst-ui/x/button-group-x.tsx +847 -0
  88. package/dist/components/catalyst-ui/x/calendar-x.tsx +1910 -0
  89. package/dist/components/catalyst-ui/x/card-x.tsx +2597 -0
  90. package/dist/components/catalyst-ui/x/checkbox-x.tsx +656 -0
  91. package/dist/components/catalyst-ui/x/collapsible-x.tsx +1360 -0
  92. package/dist/components/catalyst-ui/x/combobox-x.tsx +911 -0
  93. package/dist/components/catalyst-ui/x/data-table-x.tsx +1753 -0
  94. package/dist/components/catalyst-ui/x/date-picker-x.tsx +648 -0
  95. package/dist/components/catalyst-ui/x/dialog-x.tsx +659 -0
  96. package/dist/components/catalyst-ui/x/dropdown-menu-x.tsx +612 -0
  97. package/dist/components/catalyst-ui/x/hover-card-x.tsx +375 -0
  98. package/dist/components/catalyst-ui/x/icon-x.tsx +840 -0
  99. package/dist/components/catalyst-ui/x/input-mask-x.tsx +981 -0
  100. package/dist/components/catalyst-ui/x/input-otp-x.tsx +659 -0
  101. package/dist/components/catalyst-ui/x/loader-x.tsx +1757 -0
  102. package/dist/components/catalyst-ui/x/pagination-x.tsx +622 -0
  103. package/dist/components/catalyst-ui/x/popover-x.tsx +744 -0
  104. package/dist/components/catalyst-ui/x/radio-group-x.tsx +499 -0
  105. package/dist/components/catalyst-ui/x/select-x.tsx +1127 -0
  106. package/dist/components/catalyst-ui/x/sheet-x.tsx +668 -0
  107. package/dist/components/catalyst-ui/x/switch-x.tsx +681 -0
  108. package/dist/components/catalyst-ui/x/table-x.tsx +574 -0
  109. package/dist/components/catalyst-ui/x/tabs-x.tsx +839 -0
  110. package/dist/components/catalyst-ui/x/textarea-x.tsx +1263 -0
  111. package/dist/components/catalyst-ui/x/tooltip-x.tsx +396 -0
  112. package/dist/components/catalyst-ui/x/tracker-x.tsx +560 -0
  113. package/dist/data/bg-data.tsx +901 -0
  114. package/dist/data/buttons-data.tsx +2327 -0
  115. package/dist/data/charts-data.tsx +102 -0
  116. package/dist/data/chat-data.tsx +83 -0
  117. package/dist/data/code-data.tsx +1040 -0
  118. package/dist/data/comboboxes-data.tsx +1843 -0
  119. package/dist/data/command-data.tsx +1381 -0
  120. package/dist/data/core-data.tsx +15953 -0
  121. package/dist/data/crm-data.tsx +47 -0
  122. package/dist/data/data.tsx +159 -0
  123. package/dist/data/date-and-time-data.tsx +554 -0
  124. package/dist/data/dependencies.tsx +7 -0
  125. package/dist/data/ecommerce-data.tsx +1387 -0
  126. package/dist/data/forms-data.tsx +7890 -0
  127. package/dist/data/hooks-data.tsx +5487 -0
  128. package/dist/data/index.ts +34 -0
  129. package/dist/data/inputs-data.tsx +557 -0
  130. package/dist/data/interactive-data.tsx +5394 -0
  131. package/dist/data/lofi-data.tsx +18295 -0
  132. package/dist/data/marketing-data.tsx +2546 -0
  133. package/dist/data/media-data.tsx +1510 -0
  134. package/dist/data/motion-data.tsx +5801 -0
  135. package/dist/data/overlay-data.tsx +4136 -0
  136. package/dist/data/pdf-data.tsx +124 -0
  137. package/dist/data/pos-data.tsx +213 -0
  138. package/dist/data/postcss.config.js +6 -0
  139. package/dist/data/primitive-data.tsx +5170 -0
  140. package/dist/data/prompt-data.tsx +1226 -0
  141. package/dist/data/requiredLibs.ts +4 -0
  142. package/dist/data/sandbox-data.tsx +1 -0
  143. package/dist/data/sidebars-data.tsx +5421 -0
  144. package/dist/data/stacks-data.tsx +32 -0
  145. package/dist/data/table-data.tsx +706 -0
  146. package/dist/data/tailwind.config.js +270 -0
  147. package/dist/data/tailwind.config.ngin.js +3830 -0
  148. package/dist/data/tailwind.css +431 -0
  149. package/dist/data/tools-data.tsx +6910 -0
  150. package/dist/data/typography-data.tsx +2050 -0
  151. package/dist/data/utils-data.tsx +6500 -0
  152. package/dist/data/x-data.tsx +1171 -0
  153. package/dist/data.tsx +159 -0
  154. package/package.json +1 -1
  155. package/dist/index.d.ts +0 -3
  156. package/dist/index.d.ts.map +0 -1
  157. package/dist/index.js.map +0 -362
@@ -0,0 +1,648 @@
1
+ /**
2
+
3
+
4
+
5
+
6
+
7
+
8
+ export function DatePickerX({ datePicker = 'default', children, ...props }: any) {
9
+ switch (datePicker) {
10
+ case 'Closable':
11
+ break
12
+ default:
13
+ break;
14
+ }
15
+ }
16
+
17
+ const DatePickerDemo = () => {
18
+ const [open, setOpen] = useState(false)
19
+ const [date, setDate] = useState<Date | undefined>(undefined)
20
+
21
+ return (
22
+ <div className='w-full max-w-xs space-y-2'>
23
+ <Label htmlFor='date' className='px-1'>
24
+ Date picker
25
+ </Label>
26
+ <Popover open={open} onOpenChange={setOpen}>
27
+ <PopoverTrigger asChild>
28
+ <Button variant='outline' id='date' className='w-full justify-between font-normal'>
29
+ {date ? date.toLocaleDateString() : 'Pick a date'}
30
+ <ChevronDownIcon />
31
+ </Button>
32
+ </PopoverTrigger>
33
+ <PopoverContent className='w-auto overflow-hidden p-0' align='start'>
34
+ <Calendar
35
+ mode='single'
36
+ selected={date}
37
+ onSelect={date => {
38
+ setDate(date)
39
+ setOpen(false)
40
+ }}
41
+ />
42
+ </PopoverContent>
43
+ </Popover>
44
+ </div>
45
+ )
46
+ }
47
+
48
+ const DatePickerRangeDemo = () => {
49
+ const [range, setRange] = useState<DateRange | undefined>(undefined)
50
+
51
+ return (
52
+ <div className='w-full max-w-xs space-y-2'>
53
+ <Label htmlFor='dates' className='px-1'>
54
+ Range date picker
55
+ </Label>
56
+ <Popover>
57
+ <PopoverTrigger asChild>
58
+ <Button variant='outline' id='dates' className='w-full justify-between font-normal'>
59
+ {range?.from && range?.to
60
+ ? `${range.from.toLocaleDateString()} - ${range.to.toLocaleDateString()}`
61
+ : 'Pick a date'}
62
+ <ChevronDownIcon />
63
+ </Button>
64
+ </PopoverTrigger>
65
+ <PopoverContent className='w-auto overflow-hidden p-0' align='start'>
66
+ <Calendar
67
+ mode='range'
68
+ selected={range}
69
+ onSelect={range => {
70
+ setRange(range)
71
+ }}
72
+ />
73
+ </PopoverContent>
74
+ </Popover>
75
+ </div>
76
+ )
77
+ }
78
+
79
+ const DatePickerWithIconDemo = () => {
80
+ const [open, setOpen] = useState(false)
81
+ const [date, setDate] = useState<Date | undefined>(undefined)
82
+
83
+ return (
84
+ <div className='w-full max-w-xs space-y-2'>
85
+ <Label htmlFor='date' className='px-1'>
86
+ Date picker with icon
87
+ </Label>
88
+ <Popover open={open} onOpenChange={setOpen}>
89
+ <PopoverTrigger asChild>
90
+ <Button variant='outline' id='date' className='w-full justify-between font-normal'>
91
+ <span className='flex items-center'>
92
+ <CalendarIcon className='mr-2' />
93
+ {date ? date.toLocaleDateString() : 'Pick a date'}
94
+ </span>
95
+ <ChevronDownIcon />
96
+ </Button>
97
+ </PopoverTrigger>
98
+ <PopoverContent className='w-auto overflow-hidden p-0' align='start'>
99
+ <Calendar
100
+ mode='single'
101
+ selected={date}
102
+ onSelect={date => {
103
+ setDate(date)
104
+ setOpen(false)
105
+ }}
106
+ />
107
+ </PopoverContent>
108
+ </Popover>
109
+ </div>
110
+ )
111
+ }
112
+
113
+ const DatePickerWithinInputDemo = () => {
114
+ const [open, setOpen] = useState(false)
115
+ const [date, setDate] = useState<Date | undefined>(new Date())
116
+ const [month, setMonth] = useState<Date | undefined>(date)
117
+ const [value, setValue] = useState(formatDate(date))
118
+
119
+ return (
120
+ <div className='w-full max-w-xs space-y-2'>
121
+ <Label htmlFor='date' className='px-1'>
122
+ Date picker within input
123
+ </Label>
124
+ <div className='relative flex gap-2'>
125
+ <Input
126
+ id='date'
127
+ value={value}
128
+ placeholder='January 01, 2025'
129
+ className='bg-background pr-10'
130
+ onChange={e => {
131
+ const date = new Date(e.target.value)
132
+
133
+ setValue(e.target.value)
134
+
135
+ if (isValidDate(date)) {
136
+ setDate(date)
137
+ setMonth(date)
138
+ }
139
+ }}
140
+ onKeyDown={e => {
141
+ if (e.key === 'ArrowDown') {
142
+ e.preventDefault()
143
+ setOpen(true)
144
+ }
145
+ }}
146
+ />
147
+ <Popover open={open} onOpenChange={setOpen}>
148
+ <PopoverTrigger asChild>
149
+ <Button id='date-picker' variant='ghost' className='absolute top-1/2 right-2 size-6 -translate-y-1/2'>
150
+ <CalendarIcon className='size-3.5' />
151
+ <span className='sr-only'>Pick a date</span>
152
+ </Button>
153
+ </PopoverTrigger>
154
+ <PopoverContent className='w-auto overflow-hidden p-0' align='end' alignOffset={-8} sideOffset={10}>
155
+ <Calendar
156
+ mode='single'
157
+ selected={date}
158
+ month={month}
159
+ onMonthChange={setMonth}
160
+ onSelect={date => {
161
+ setDate(date)
162
+ setValue(formatDate(date))
163
+ setOpen(false)
164
+ }}
165
+ />
166
+ </PopoverContent>
167
+ </Popover>
168
+ </div>
169
+ </div>
170
+ )
171
+ }
172
+
173
+ const DatePickerWithNaturalLanguageDemo = () => {
174
+ const [open, setOpen] = useState(false)
175
+ const [value, setValue] = useState('In 2 days')
176
+ const [date, setDate] = useState<Date | undefined>(parseDate(value) || undefined)
177
+ const [month, setMonth] = useState<Date | undefined>(date)
178
+
179
+ return (
180
+ <div className='w-full max-w-xs space-y-2'>
181
+ <Label htmlFor='date' className='px-1'>
182
+ Date picker with natural language input
183
+ </Label>
184
+ <div className='relative flex gap-2'>
185
+ <Input
186
+ id='date'
187
+ value={value}
188
+ placeholder='Tomorrow or next week'
189
+ className='bg-background pr-10'
190
+ onChange={e => {
191
+ setValue(e.target.value)
192
+ const date = parseDate(e.target.value)
193
+
194
+ if (date) {
195
+ setDate(date)
196
+ setMonth(date)
197
+ }
198
+ }}
199
+ onKeyDown={e => {
200
+ if (e.key === 'ArrowDown') {
201
+ e.preventDefault()
202
+ setOpen(true)
203
+ }
204
+ }}
205
+ />
206
+ <Popover open={open} onOpenChange={setOpen}>
207
+ <PopoverTrigger asChild>
208
+ <Button id='date-picker' variant='ghost' className='absolute top-1/2 right-2 size-6 -translate-y-1/2'>
209
+ <CalendarIcon className='size-3.5' />
210
+ <span className='sr-only'>Pick a date</span>
211
+ </Button>
212
+ </PopoverTrigger>
213
+ <PopoverContent className='w-auto overflow-hidden p-0' align='end' alignOffset={-8} sideOffset={10}>
214
+ <Calendar
215
+ mode='single'
216
+ selected={date}
217
+ month={month}
218
+ onMonthChange={setMonth}
219
+ onSelect={date => {
220
+ setDate(date)
221
+ setValue(formatDate(date))
222
+ setOpen(false)
223
+ }}
224
+ />
225
+ </PopoverContent>
226
+ </Popover>
227
+ </div>
228
+ <div className='text-muted-foreground px-1 text-sm'>
229
+ Your post will be published on <span className='font-medium'>{formatDate(date)}</span>.
230
+ </div>
231
+ </div>
232
+ )
233
+ }
234
+
235
+ const DatePickerWithShortDateDisplayDemo = () => {
236
+ const [range, setRange] = useState<DateRange | undefined>({
237
+ from: new Date(2025, 10, 20),
238
+ to: new Date(2025, 10, 24)
239
+ })
240
+
241
+ return (
242
+ <div className='w-full max-w-xs space-y-2'>
243
+ <Label htmlFor='dates' className='px-1'>
244
+ Date picker with short date
245
+ </Label>
246
+ <Popover>
247
+ <PopoverTrigger asChild>
248
+ <Button variant='outline' id='dates' className='w-full justify-between font-normal'>
249
+ {range?.from && range?.to
250
+ ? formatDateRange(range.from, range.to, {
251
+ includeTime: false
252
+ })
253
+ : 'Pick a date'}
254
+ <ChevronDownIcon />
255
+ </Button>
256
+ </PopoverTrigger>
257
+ <PopoverContent className='w-auto overflow-hidden p-0' align='start'>
258
+ <Calendar
259
+ mode='range'
260
+ selected={range}
261
+ onSelect={range => {
262
+ setRange(range)
263
+ }}
264
+ />
265
+ </PopoverContent>
266
+ </Popover>
267
+ </div>
268
+ )
269
+ }
270
+
271
+ const DatePickerDisableOutsideDaysDemo = () => {
272
+ const [open, setOpen] = useState(false)
273
+ const [date, setDate] = useState<Date | undefined>(undefined)
274
+
275
+ return (
276
+ <div className='w-full max-w-xs space-y-2'>
277
+ <Label htmlFor='date' className='px-1'>
278
+ Disable outside days
279
+ </Label>
280
+ <Popover open={open} onOpenChange={setOpen}>
281
+ <PopoverTrigger asChild>
282
+ <Button variant='outline' id='date' className='w-full justify-between font-normal'>
283
+ {date ? date.toLocaleDateString() : 'Pick a date'}
284
+ <ChevronDownIcon />
285
+ </Button>
286
+ </PopoverTrigger>
287
+ <PopoverContent className='w-auto overflow-hidden p-0' align='start'>
288
+ <Calendar
289
+ mode='single'
290
+ selected={date}
291
+ showOutsideDays={false}
292
+ onSelect={date => {
293
+ setDate(date)
294
+ setOpen(false)
295
+ }}
296
+ />
297
+ </PopoverContent>
298
+ </Popover>
299
+ </div>
300
+ )
301
+ }
302
+
303
+ const DatePickerDemo = () => {
304
+ return (
305
+ <div className='w-full max-w-xs space-y-2'>
306
+ <Label htmlFor='time-picker' className='px-1'>
307
+ Time input
308
+ </Label>
309
+ <Input
310
+ type='time'
311
+ id='time-picker'
312
+ step='1'
313
+ defaultValue='08:30:00'
314
+ className='bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none'
315
+ />
316
+ </div>
317
+ )
318
+ }
319
+
320
+ const TimePickerWithIconDemo = () => {
321
+ return (
322
+ <div className='w-full max-w-xs space-y-2'>
323
+ <Label htmlFor='timepicker'>Time input with start icon</Label>
324
+ <div className='relative'>
325
+ <div className='text-muted-foreground pointer-events-none absolute inset-y-0 left-0 flex items-center justify-center pl-3 peer-disabled:opacity-50'>
326
+ <Clock8Icon className='size-4' />
327
+ <span className='sr-only'>User</span>
328
+ </div>
329
+ <Input
330
+ type='time'
331
+ id='time-picker'
332
+ step='1'
333
+ defaultValue='08:30:00'
334
+ className='peer bg-background appearance-none pl-9 [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none'
335
+ />
336
+ </div>
337
+ </div>
338
+ )
339
+ }
340
+
341
+ const DatePickerAndTimePickerDemo = () => {
342
+ const [open, setOpen] = useState(false)
343
+ const [date, setDate] = useState<Date | undefined>(undefined)
344
+
345
+ return (
346
+ <div className='flex gap-4'>
347
+ <div className='flex flex-col gap-3'>
348
+ <Label htmlFor='date-picker' className='px-1'>
349
+ Date picker
350
+ </Label>
351
+ <Popover open={open} onOpenChange={setOpen}>
352
+ <PopoverTrigger asChild>
353
+ <Button variant='outline' id='date-picker' className='justify-between font-normal'>
354
+ {date ? date.toLocaleDateString() : 'Pick a date'}
355
+ <ChevronDownIcon />
356
+ </Button>
357
+ </PopoverTrigger>
358
+ <PopoverContent className='w-auto overflow-hidden p-0' align='start'>
359
+ <Calendar
360
+ mode='single'
361
+ selected={date}
362
+ onSelect={date => {
363
+ setDate(date)
364
+ setOpen(false)
365
+ }}
366
+ />
367
+ </PopoverContent>
368
+ </Popover>
369
+ </div>
370
+ <div className='flex flex-col gap-3'>
371
+ <Label htmlFor='time-picker' className='px-1'>
372
+ Time input
373
+ </Label>
374
+ <Input
375
+ type='time'
376
+ id='time-picker'
377
+ step='1'
378
+ defaultValue='06:30:00'
379
+ className='bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none'
380
+ />
381
+ </div>
382
+ </div>
383
+ )
384
+ }
385
+
386
+ const DatePickerAndTimeRangePicker = () => {
387
+ const [open, setOpen] = useState(false)
388
+ const [date, setDate] = useState<Date | undefined>(undefined)
389
+
390
+ return (
391
+ <div className='flex flex-col gap-6'>
392
+ <div className='flex w-full max-w-xs flex-col gap-3'>
393
+ <Label htmlFor='date' className='px-1'>
394
+ Date
395
+ </Label>
396
+ <Popover open={open} onOpenChange={setOpen}>
397
+ <PopoverTrigger asChild>
398
+ <Button variant='outline' id='date' className='w-full justify-between font-normal'>
399
+ {date ? date.toLocaleDateString() : 'Pick a date'}
400
+ <ChevronDownIcon />
401
+ </Button>
402
+ </PopoverTrigger>
403
+ <PopoverContent className='w-auto overflow-hidden p-0' align='start'>
404
+ <Calendar
405
+ mode='single'
406
+ selected={date}
407
+ onSelect={date => {
408
+ setDate(date)
409
+ setOpen(false)
410
+ }}
411
+ />
412
+ </PopoverContent>
413
+ </Popover>
414
+ </div>
415
+ <div className='flex gap-4'>
416
+ <div className='flex flex-col gap-3'>
417
+ <Label htmlFor='time-from' className='px-1'>
418
+ From
419
+ </Label>
420
+ <Input
421
+ type='time'
422
+ id='time-from'
423
+ step='1'
424
+ defaultValue='01:30:00'
425
+ className='bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none'
426
+ />
427
+ </div>
428
+ <div className='flex flex-col gap-3'>
429
+ <Label htmlFor='time-to' className='px-1'>
430
+ To
431
+ </Label>
432
+ <Input
433
+ type='time'
434
+ id='time-to'
435
+ step='1'
436
+ defaultValue='02:30:00'
437
+ className='bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none'
438
+ />
439
+ </div>
440
+ </div>
441
+ </div>
442
+ )
443
+ }
444
+
445
+ const DatePickerRangeAndTimePickerDemo = () => {
446
+ const [openFrom, setOpenFrom] = useState(false)
447
+ const [openTo, setOpenTo] = useState(false)
448
+ const [dateFrom, setDateFrom] = useState<Date | undefined>(new Date('2025-06-18'))
449
+ const [dateTo, setDateTo] = useState<Date | undefined>(new Date('2025-06-25'))
450
+
451
+ return (
452
+ <div className='flex w-full max-w-64 min-w-0 flex-col gap-6'>
453
+ <div className='flex gap-4'>
454
+ <div className='flex flex-1 flex-col gap-3'>
455
+ <Label htmlFor='date-from' className='px-1'>
456
+ Departure date
457
+ </Label>
458
+ <Popover open={openFrom} onOpenChange={setOpenFrom}>
459
+ <PopoverTrigger asChild>
460
+ <Button variant='outline' id='date-from' className='w-full justify-between font-normal'>
461
+ {dateFrom
462
+ ? dateFrom.toLocaleDateString('en-US', {
463
+ day: '2-digit',
464
+ month: 'short',
465
+ year: 'numeric'
466
+ })
467
+ : 'Pick a date'}
468
+ <ChevronDownIcon />
469
+ </Button>
470
+ </PopoverTrigger>
471
+ <PopoverContent className='w-auto overflow-hidden p-0' align='start'>
472
+ <Calendar
473
+ mode='single'
474
+ selected={dateFrom}
475
+ onSelect={date => {
476
+ setDateFrom(date)
477
+ setOpenFrom(false)
478
+ }}
479
+ />
480
+ </PopoverContent>
481
+ </Popover>
482
+ </div>
483
+ <div className='flex flex-col gap-3'>
484
+ <Label htmlFor='time-from' className='invisible px-1'>
485
+ From
486
+ </Label>
487
+ <Input
488
+ type='time'
489
+ id='time-from'
490
+ step='1'
491
+ defaultValue='09:30:00'
492
+ className='bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none'
493
+ />
494
+ </div>
495
+ </div>
496
+ <div className='flex gap-4'>
497
+ <div className='flex flex-1 flex-col gap-3'>
498
+ <Label htmlFor='date-to' className='px-1'>
499
+ Return date
500
+ </Label>
501
+ <Popover open={openTo} onOpenChange={setOpenTo}>
502
+ <PopoverTrigger asChild>
503
+ <Button variant='outline' id='date-to' className='w-full justify-between font-normal'>
504
+ {dateTo
505
+ ? dateTo.toLocaleDateString('en-US', {
506
+ day: '2-digit',
507
+ month: 'short',
508
+ year: 'numeric'
509
+ })
510
+ : 'Pick a date'}
511
+ <ChevronDownIcon />
512
+ </Button>
513
+ </PopoverTrigger>
514
+ <PopoverContent className='w-auto overflow-hidden p-0' align='start'>
515
+ <Calendar
516
+ mode='single'
517
+ selected={dateTo}
518
+ captionLayout='dropdown'
519
+ onSelect={date => {
520
+ setDateTo(date)
521
+ setOpenTo(false)
522
+ }}
523
+ disabled={dateFrom && { before: dateFrom }}
524
+ />
525
+ </PopoverContent>
526
+ </Popover>
527
+ </div>
528
+ <div className='flex flex-col gap-3'>
529
+ <Label htmlFor='time-to' className='invisible px-1'>
530
+ To
531
+ </Label>
532
+ <Input
533
+ type='time'
534
+ id='time-to'
535
+ step='1'
536
+ defaultValue='18:30:00'
537
+ className='bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none'
538
+ />
539
+ </div>
540
+ </div>
541
+ </div>
542
+ )
543
+ }
544
+
545
+ const ChartFilterDemo = () => {
546
+ const [range, setRange] = useState<DateRange | undefined>({
547
+ from: new Date(2025, 0, 1),
548
+ to: new Date(2025, 0, 31)
549
+ })
550
+
551
+ const filteredData = useMemo(() => {
552
+ if (!range?.from && !range?.to) {
553
+ return chartData
554
+ }
555
+
556
+ return chartData.filter(item => {
557
+ const date = new Date(item.date)
558
+
559
+ return date >= range.from! && date <= range.to!
560
+ })
561
+ }, [range])
562
+
563
+ return (
564
+ <Card className='@container/card w-full max-w-xl'>
565
+ <CardHeader className='flex flex-col border-b @md/card:grid'>
566
+ <CardTitle>Web Analytics</CardTitle>
567
+ <CardDescription>Showing total visitors for this month.</CardDescription>
568
+ <CardAction className='mt-2 @md/card:mt-0'>
569
+ <Popover>
570
+ <PopoverTrigger asChild>
571
+ <Button variant='outline'>
572
+ <CalendarIcon />
573
+ {range?.from && range?.to
574
+ ? `${range.from.toLocaleDateString()} - ${range.to.toLocaleDateString()}`
575
+ : 'January 2025'}
576
+ </Button>
577
+ </PopoverTrigger>
578
+ <PopoverContent className='w-auto overflow-hidden p-0' align='end'>
579
+ <Calendar
580
+ className='w-full'
581
+ mode='range'
582
+ defaultMonth={range?.from}
583
+ selected={range}
584
+ onSelect={setRange}
585
+ startMonth={range?.from}
586
+ fixedWeeks
587
+ showOutsideDays
588
+ disabled={{
589
+ after: new Date(2025, 0, 31),
590
+ before: new Date(2025, 0, 1)
591
+ }}
592
+ />
593
+ </PopoverContent>
594
+ </Popover>
595
+ </CardAction>
596
+ </CardHeader>
597
+ <CardContent className='px-4'>
598
+ <ChartContainer config={chartConfig} className='aspect-auto h-62 w-full'>
599
+ <BarChart
600
+ accessibilityLayer
601
+ data={filteredData}
602
+ margin={{
603
+ left: 12,
604
+ right: 12
605
+ }}
606
+ >
607
+ <CartesianGrid vertical={false} />
608
+ <XAxis
609
+ dataKey='date'
610
+ tickLine={false}
611
+ axisLine={false}
612
+ tickMargin={8}
613
+ minTickGap={20}
614
+ tickFormatter={value => {
615
+ const date = new Date(value)
616
+
617
+ return date.toLocaleDateString('en-US', {
618
+ day: 'numeric'
619
+ })
620
+ }}
621
+ />
622
+ <ChartTooltip
623
+ content={
624
+ <ChartTooltipContent
625
+ className='w-[150px]'
626
+ nameKey='visitors'
627
+ labelFormatter={value => {
628
+ return new Date(value).toLocaleDateString('en-US', {
629
+ month: 'short',
630
+ day: 'numeric',
631
+ year: 'numeric'
632
+ })
633
+ }}
634
+ />
635
+ }
636
+ />
637
+ <Bar dataKey='visitors' fill={`var(--color-visitors)`} radius={4} />
638
+ </BarChart>
639
+ </ChartContainer>
640
+ </CardContent>
641
+ <CardFooter className='border-t'>
642
+ <div className='text-sm'>
643
+ You had <span className='font-semibold'>{total.toLocaleString()}</span> visitors for the month of January.
644
+ </div>
645
+ </CardFooter>
646
+ </Card>
647
+ )
648
+ } */