azamat-ui-kit-cli 0.2.2 → 0.3.4

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 (103) hide show
  1. package/README.md +11 -0
  2. package/dist/index.cjs +452 -0
  3. package/package.json +2 -2
  4. package/vendor/src/components/actions/action-menu.tsx +21 -18
  5. package/vendor/src/components/calendar/calendar.tsx +153 -102
  6. package/vendor/src/components/calendar/date-picker.tsx +24 -14
  7. package/vendor/src/components/calendar/date-range-picker.tsx +137 -58
  8. package/vendor/src/components/charts/charts.tsx +32 -21
  9. package/vendor/src/components/command/command-palette.tsx +68 -57
  10. package/vendor/src/components/data-table/data-table-bulk-actions.tsx +23 -20
  11. package/vendor/src/components/data-table/data-table-column-visibility-menu.tsx +21 -10
  12. package/vendor/src/components/data-table/data-table-pagination.tsx +6 -6
  13. package/vendor/src/components/data-table/data-table-toolbar.tsx +72 -44
  14. package/vendor/src/components/data-table/data-table.tsx +15 -11
  15. package/vendor/src/components/data-table/table-export-menu.tsx +1 -1
  16. package/vendor/src/components/data-table/table-import-button.tsx +1 -1
  17. package/vendor/src/components/display/data-state.tsx +20 -8
  18. package/vendor/src/components/display/index.ts +19 -15
  19. package/vendor/src/components/display/metric-card.tsx +35 -0
  20. package/vendor/src/components/display/progress-circle.tsx +24 -0
  21. package/vendor/src/components/display/smart-card.tsx +49 -27
  22. package/vendor/src/components/display/status-dot.tsx +45 -0
  23. package/vendor/src/components/display/user-card.tsx +30 -0
  24. package/vendor/src/components/feedback/alert.tsx +21 -11
  25. package/vendor/src/components/feedback/empty-state.tsx +2 -2
  26. package/vendor/src/components/feedback/loading-state.tsx +2 -2
  27. package/vendor/src/components/feedback/page-state.tsx +19 -15
  28. package/vendor/src/components/feedback/status-badge.tsx +43 -43
  29. package/vendor/src/components/form/form-app-input.tsx +147 -0
  30. package/vendor/src/components/form/form-date-input.tsx +16 -19
  31. package/vendor/src/components/form/form-field-shell.tsx +11 -8
  32. package/vendor/src/components/form/form-field-utils.ts +76 -0
  33. package/vendor/src/components/form/form-input.tsx +423 -44
  34. package/vendor/src/components/form/form-number-input.tsx +16 -15
  35. package/vendor/src/components/form/form-phone-input.tsx +15 -9
  36. package/vendor/src/components/form/form-search-input.tsx +16 -19
  37. package/vendor/src/components/form/form-select.tsx +4 -3
  38. package/vendor/src/components/form/public.ts +16 -14
  39. package/vendor/src/components/form/smart-form-shell.tsx +13 -12
  40. package/vendor/src/components/inputs/app-input.tsx +27 -0
  41. package/vendor/src/components/inputs/async-select.tsx +113 -84
  42. package/vendor/src/components/inputs/clearable-input.tsx +81 -61
  43. package/vendor/src/components/inputs/date-input.tsx +21 -17
  44. package/vendor/src/components/inputs/date-range-input.tsx +10 -10
  45. package/vendor/src/components/inputs/index.ts +1 -0
  46. package/vendor/src/components/inputs/input-decorator.tsx +101 -57
  47. package/vendor/src/components/inputs/masked-input.tsx +20 -20
  48. package/vendor/src/components/inputs/money-input.tsx +2 -2
  49. package/vendor/src/components/inputs/number-input.tsx +29 -19
  50. package/vendor/src/components/inputs/password-input.tsx +82 -45
  51. package/vendor/src/components/inputs/phone-input.tsx +24 -2
  52. package/vendor/src/components/inputs/quantity-input.tsx +2 -2
  53. package/vendor/src/components/inputs/search-input.tsx +54 -3
  54. package/vendor/src/components/inputs/simple-select.tsx +110 -22
  55. package/vendor/src/components/layout/app-shell.tsx +2 -2
  56. package/vendor/src/components/layout/index.ts +5 -4
  57. package/vendor/src/components/layout/page-header.tsx +79 -35
  58. package/vendor/src/components/layout/public.ts +12 -10
  59. package/vendor/src/components/layout/section-header.tsx +56 -0
  60. package/vendor/src/components/layout/stack.tsx +106 -0
  61. package/vendor/src/components/layout/stat-card.tsx +66 -29
  62. package/vendor/src/components/navigation/index.ts +1 -0
  63. package/vendor/src/components/navigation/nav-tabs.tsx +60 -0
  64. package/vendor/src/components/navigation/page-tabs.tsx +41 -26
  65. package/vendor/src/components/navigation/pagination.tsx +14 -10
  66. package/vendor/src/components/overlay/alert-dialog.tsx +65 -0
  67. package/vendor/src/components/overlay/drawer.tsx +71 -0
  68. package/vendor/src/components/overlay/index.ts +4 -2
  69. package/vendor/src/components/patterns/data-view.tsx +13 -8
  70. package/vendor/src/components/ui/badge.tsx +96 -52
  71. package/vendor/src/components/ui/button.tsx +99 -61
  72. package/vendor/src/components/ui/card.tsx +84 -25
  73. package/vendor/src/components/ui/checkbox.tsx +68 -68
  74. package/vendor/src/components/ui/command.tsx +32 -32
  75. package/vendor/src/components/ui/dialog.tsx +135 -138
  76. package/vendor/src/components/ui/dropdown-menu.tsx +21 -21
  77. package/vendor/src/components/ui/hover-card.tsx +49 -0
  78. package/vendor/src/components/ui/input-primitive.tsx +24 -0
  79. package/vendor/src/components/ui/input.tsx +191 -20
  80. package/vendor/src/components/ui/kbd.tsx +33 -0
  81. package/vendor/src/components/ui/popover.tsx +11 -11
  82. package/vendor/src/components/ui/radio-group.tsx +102 -0
  83. package/vendor/src/components/ui/right-click-menu.tsx +60 -0
  84. package/vendor/src/components/ui/scroll-box.tsx +27 -0
  85. package/vendor/src/components/ui/segmented-control.tsx +21 -17
  86. package/vendor/src/components/ui/select.tsx +187 -189
  87. package/vendor/src/components/ui/skeleton.tsx +2 -2
  88. package/vendor/src/components/ui/switch.tsx +60 -60
  89. package/vendor/src/components/ui/table.tsx +114 -114
  90. package/vendor/src/components/ui/tabs.tsx +2 -2
  91. package/vendor/src/components/ui/textarea.tsx +1 -1
  92. package/vendor/src/components/upload/file-dropzone.tsx +38 -0
  93. package/vendor/src/components/upload/file-upload.tsx +4 -4
  94. package/vendor/src/components/upload/image-upload.tsx +22 -19
  95. package/vendor/src/components/upload/index.ts +2 -0
  96. package/vendor/src/families/catalog.ts +1 -0
  97. package/vendor/src/families/docs-groups.ts +10 -1
  98. package/vendor/src/families/member-metadata.ts +24 -0
  99. package/vendor/src/families/member-snippets.ts +41 -2
  100. package/vendor/src/families/migration-map.ts +3 -0
  101. package/vendor/src/index.ts +23 -18
  102. package/vendor/templates/styles/globals.css +253 -0
  103. package/dist/index.js +0 -432
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "azamat-ui-kit-cli",
3
- "version": "0.2.2",
3
+ "version": "0.3.4",
4
4
  "description": "CLI for Azamat UI Kit source-copy, presets, and theme setup.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "bin": {
8
- "azamat-ui-kit": "dist/index.js"
8
+ "azamat-ui-kit": "dist/index.cjs"
9
9
  },
10
10
  "files": [
11
11
  "dist",
@@ -66,17 +66,20 @@ function ActionMenu({
66
66
  return (
67
67
  <DropdownMenu>
68
68
  <DropdownMenuTrigger
69
- render={
70
- trigger ?? (
71
- <Button
72
- type="button"
73
- variant="ghost"
74
- size="icon-sm"
75
- disabled={disabled}
76
- className={triggerClassName}
77
- />
78
- )
79
- }
69
+ render={
70
+ trigger ?? (
71
+ <Button
72
+ type="button"
73
+ variant="ghost"
74
+ size="icon-sm"
75
+ disabled={disabled}
76
+ className={cn(
77
+ "rounded-full border border-transparent text-muted-foreground hover:border-border/70 hover:bg-muted/50 hover:text-foreground",
78
+ triggerClassName
79
+ )}
80
+ />
81
+ )
82
+ }
80
83
  >
81
84
  {!trigger && <MoreHorizontalIcon />}
82
85
  <span className="sr-only">Open actions</span>
@@ -104,13 +107,13 @@ function ActionMenu({
104
107
  variant={action.destructive ? "destructive" : "default"}
105
108
  onClick={() => void handleSelect(action)}
106
109
  >
107
- {isLoading ? <Loader2Icon className="animate-spin" /> : action.icon}
108
- <span className="min-w-0 flex-1 truncate">{action.label}</span>
109
- {action.shortcut && (
110
- <span className="ml-auto text-xs text-muted-foreground">{action.shortcut}</span>
111
- )}
112
- </DropdownMenuItem>
113
- )
110
+ {isLoading ? <Loader2Icon className="animate-spin" /> : action.icon}
111
+ <span className="min-w-0 flex-1 truncate">{action.label}</span>
112
+ {action.shortcut && (
113
+ <span className="ml-auto text-[11px] tracking-[0.14em] text-muted-foreground">{action.shortcut}</span>
114
+ )}
115
+ </DropdownMenuItem>
116
+ )
114
117
  })}
115
118
  </DropdownMenuContent>
116
119
  </DropdownMenu>
@@ -31,10 +31,10 @@ export type CalendarLabels = {
31
31
  disabledDate?: (date: string, reason: CalendarDisabledReason) => string
32
32
  }
33
33
 
34
- export type CalendarProps = React.ComponentProps<"div"> & {
35
- value?: string | null
36
- range?: CalendarDateRange
37
- onValueChange?: (value: string) => void
34
+ export type CalendarProps = React.ComponentProps<"div"> & {
35
+ value?: string | null
36
+ range?: CalendarDateRange
37
+ onValueChange?: (value: string) => void
38
38
  onRangeChange?: (range: CalendarDateRange) => void
39
39
  mode?: "single" | "range"
40
40
  month?: Date
@@ -42,11 +42,14 @@ export type CalendarProps = React.ComponentProps<"div"> & {
42
42
  onMonthChange?: (month: Date) => void
43
43
  min?: string
44
44
  max?: string
45
- disabledDates?: string[]
46
- locale?: string
47
- weekStartsOn?: 0 | 1
48
- labels?: CalendarLabels
49
- }
45
+ disabledDates?: string[]
46
+ locale?: string
47
+ weekStartsOn?: 0 | 1
48
+ numberOfMonths?: number
49
+ showMonthHeaders?: boolean
50
+ pagedNavigation?: boolean
51
+ labels?: CalendarLabels
52
+ }
50
53
 
51
54
  function getInitialMonth(defaultMonth?: Date | string | null, value?: string | null, range?: CalendarDateRange) {
52
55
  if (defaultMonth instanceof Date) return startOfMonth(defaultMonth)
@@ -103,20 +106,41 @@ function Calendar({
103
106
  onMonthChange,
104
107
  min,
105
108
  max,
106
- disabledDates,
107
- locale = "en-US",
108
- weekStartsOn = 1,
109
- labels,
110
- ...props
111
- }: CalendarProps) {
112
- const [internalMonth, setInternalMonth] = React.useState(() => getInitialMonth(defaultMonth, value, range))
113
- const currentMonth = month ?? internalMonth
114
- const todayKey = toDateKey(new Date())
115
- const disabledSet = React.useMemo(() => new Set(disabledDates ?? []), [disabledDates])
116
- const monthDays = React.useMemo(() => getMonthDays(currentMonth, weekStartsOn), [currentMonth, weekStartsOn])
117
- const weekdayLabels = React.useMemo(() => getWeekdayLabels(locale, weekStartsOn), [locale, weekStartsOn])
118
- const buttonRefs = React.useRef(new Map<string, HTMLButtonElement>())
119
- const [focusedDateKey, setFocusedDateKey] = React.useState(() => value ?? range?.from ?? todayKey)
109
+ disabledDates,
110
+ locale = "en-US",
111
+ weekStartsOn = 1,
112
+ numberOfMonths = 1,
113
+ showMonthHeaders,
114
+ pagedNavigation = false,
115
+ labels,
116
+ ...props
117
+ }: CalendarProps) {
118
+ const [internalMonth, setInternalMonth] = React.useState(() => getInitialMonth(defaultMonth, value, range))
119
+ const currentMonth = month ?? internalMonth
120
+ const resolvedNumberOfMonths = Math.max(numberOfMonths, 1)
121
+ const shouldShowMonthHeaders = showMonthHeaders ?? resolvedNumberOfMonths > 1
122
+ const navigationStep = pagedNavigation ? resolvedNumberOfMonths : 1
123
+ const todayKey = toDateKey(new Date())
124
+ const disabledSet = React.useMemo(() => new Set(disabledDates ?? []), [disabledDates])
125
+ const weekdayLabels = React.useMemo(() => getWeekdayLabels(locale, weekStartsOn), [locale, weekStartsOn])
126
+ const buttonRefs = React.useRef(new Map<string, HTMLButtonElement>())
127
+ const [focusedDateKey, setFocusedDateKey] = React.useState(() => value ?? range?.from ?? todayKey)
128
+ const visibleMonths = React.useMemo(
129
+ () => Array.from({ length: resolvedNumberOfMonths }, (_, index) => addMonths(currentMonth, index)),
130
+ [currentMonth, resolvedNumberOfMonths]
131
+ )
132
+ const monthDaysByMonth = React.useMemo(
133
+ () =>
134
+ visibleMonths.map((visibleMonth) => ({
135
+ month: visibleMonth,
136
+ days: getMonthDays(visibleMonth, weekStartsOn),
137
+ })),
138
+ [visibleMonths, weekStartsOn]
139
+ )
140
+ const allMonthDays = React.useMemo(
141
+ () => monthDaysByMonth.flatMap((entry) => entry.days),
142
+ [monthDaysByMonth]
143
+ )
120
144
 
121
145
  const getDisabledReason = React.useCallback(
122
146
  (dateKey: string): CalendarDisabledReason | undefined => {
@@ -128,12 +152,12 @@ function Calendar({
128
152
  [disabledSet, max, min]
129
153
  )
130
154
 
131
- const isDateDisabled = React.useCallback((dateKey: string) => Boolean(getDisabledReason(dateKey)), [getDisabledReason])
132
-
133
- const visibleEnabledKeys = React.useMemo(
134
- () => monthDays.map(toDateKey).filter((dateKey) => !isDateDisabled(dateKey)),
135
- [isDateDisabled, monthDays]
136
- )
155
+ const isDateDisabled = React.useCallback((dateKey: string) => Boolean(getDisabledReason(dateKey)), [getDisabledReason])
156
+
157
+ const visibleEnabledKeys = React.useMemo(
158
+ () => allMonthDays.map(toDateKey).filter((dateKey) => !isDateDisabled(dateKey)),
159
+ [allMonthDays, isDateDisabled]
160
+ )
137
161
 
138
162
  const tabbableDateKey = React.useMemo(() => {
139
163
  const preferred = value ?? range?.from ?? todayKey
@@ -153,9 +177,9 @@ function Calendar({
153
177
  onMonthChange?.(next)
154
178
  }
155
179
 
156
- const moveFocus = (date: Date) => {
157
- let nextDate = date
158
- let nextKey = toDateKey(nextDate)
180
+ const moveFocus = (date: Date) => {
181
+ let nextDate = date
182
+ let nextKey = toDateKey(nextDate)
159
183
  let guard = 0
160
184
 
161
185
  while (isDateDisabled(nextKey) && guard < 370) {
@@ -163,13 +187,15 @@ function Calendar({
163
187
  nextKey = toDateKey(nextDate)
164
188
  guard += 1
165
189
  }
166
-
167
- setFocusedDateKey(nextKey)
168
-
169
- if (!isSameMonth(nextDate, currentMonth)) {
170
- setMonth(startOfMonth(nextDate))
171
- }
172
- }
190
+
191
+ setFocusedDateKey(nextKey)
192
+
193
+ const isVisibleInCurrentViewport = visibleMonths.some((visibleMonth) => isSameMonth(nextDate, visibleMonth))
194
+
195
+ if (!isVisibleInCurrentViewport) {
196
+ setMonth(startOfMonth(nextDate))
197
+ }
198
+ }
173
199
 
174
200
  const handleDateSelect = (dateKey: string) => {
175
201
  if (isDateDisabled(dateKey)) return
@@ -197,10 +223,12 @@ function Calendar({
197
223
  onRangeChange?.({ from, to: dateKey })
198
224
  }
199
225
 
200
- const handleDateKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>, date: Date) => {
201
- const columnIndex = monthDays.findIndex((item) => toDateKey(item) === toDateKey(date)) % 7
202
-
203
- switch (event.key) {
226
+ const handleDateKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>, date: Date) => {
227
+ const visibleMonthEntry = monthDaysByMonth.find((entry) => isSameMonth(date, entry.month))
228
+ const columnIndex =
229
+ ((visibleMonthEntry?.days.findIndex((item) => toDateKey(item) === toDateKey(date)) ?? 0) + 7) % 7
230
+
231
+ switch (event.key) {
204
232
  case "ArrowRight":
205
233
  event.preventDefault()
206
234
  moveFocus(addDays(date, 1))
@@ -239,90 +267,113 @@ function Calendar({
239
267
  return (
240
268
  <div
241
269
  data-slot="calendar"
270
+ data-months={resolvedNumberOfMonths}
242
271
  className={cn(
243
- "w-72 rounded-[calc(var(--radius-2xl)+2px)] border border-border/75 bg-popover/98 p-3 text-popover-foreground shadow-[0_24px_70px_rgba(15,23,42,0.14)] backdrop-blur",
272
+ "w-fit rounded-[calc(var(--radius-2xl)+4px)] border border-border/80 bg-popover/98 p-3.5 text-popover-foreground shadow-[0_24px_70px_rgba(15,23,42,0.16)] ring-1 ring-foreground/6 backdrop-blur",
244
273
  className
245
274
  )}
246
275
  {...props}
247
276
  >
248
- <div className="mb-3 flex items-center justify-between gap-2">
277
+ <div className="mb-4 flex items-center justify-between gap-3">
249
278
  <Button
250
279
  type="button"
251
280
  variant="outline"
252
281
  size="icon-sm"
253
- className="rounded-full border-border/80 bg-background/70 text-foreground shadow-none hover:bg-accent hover:text-accent-foreground"
282
+ className="rounded-full border-border/90 bg-background/88 text-foreground shadow-[0_1px_0_rgba(255,255,255,0.08)] hover:border-ring/30 hover:bg-accent hover:text-accent-foreground"
254
283
  aria-label={labels?.previousMonth ?? "Previous month"}
255
- onClick={() => setMonth(addMonths(currentMonth, -1))}
284
+ onClick={() => setMonth(addMonths(currentMonth, -navigationStep))}
256
285
  >
257
286
  <ChevronLeftIcon />
258
287
  </Button>
259
- <div className="text-base font-semibold capitalize tracking-tight text-foreground">{getMonthLabel(currentMonth, locale)}</div>
288
+ <div className="flex flex-1 flex-col items-center text-center">
289
+ <span className="text-[11px] font-semibold uppercase tracking-[0.24em] text-muted-foreground">Calendar</span>
290
+ <div className="text-base font-semibold capitalize tracking-tight text-foreground">{getMonthLabel(currentMonth, locale)}</div>
291
+ </div>
260
292
  <Button
261
293
  type="button"
262
294
  variant="outline"
263
295
  size="icon-sm"
264
- className="rounded-full border-border/80 bg-background/70 text-foreground shadow-none hover:bg-accent hover:text-accent-foreground"
296
+ className="rounded-full border-border/90 bg-background/88 text-foreground shadow-[0_1px_0_rgba(255,255,255,0.08)] hover:border-ring/30 hover:bg-accent hover:text-accent-foreground"
265
297
  aria-label={labels?.nextMonth ?? "Next month"}
266
- onClick={() => setMonth(addMonths(currentMonth, 1))}
298
+ onClick={() => setMonth(addMonths(currentMonth, navigationStep))}
267
299
  >
268
300
  <ChevronRightIcon />
269
301
  </Button>
270
302
  </div>
271
303
 
272
- <div className="grid grid-cols-7 gap-1 text-center text-[0.72rem] font-medium uppercase tracking-[0.18em] text-muted-foreground">
273
- {weekdayLabels.map((weekday) => (
274
- <div key={weekday} className="py-1.5">
275
- {weekday}
304
+ <div
305
+ className={cn("grid gap-3.5", resolvedNumberOfMonths > 1 && "sm:grid-cols-2")}
306
+ style={
307
+ resolvedNumberOfMonths > 2
308
+ ? { gridTemplateColumns: `repeat(${resolvedNumberOfMonths}, minmax(0, 1fr))` }
309
+ : undefined
310
+ }
311
+ >
312
+ {monthDaysByMonth.map(({ month: visibleMonth, days }) => (
313
+ <div key={toDateKey(visibleMonth)} className="min-w-[17rem] rounded-[var(--radius-2xl)] border border-border/60 bg-background/58 p-2.5 shadow-[inset_0_1px_0_rgba(255,255,255,0.05)]">
314
+ {shouldShowMonthHeaders && (
315
+ <div className="mb-3 text-center text-sm font-semibold capitalize tracking-tight text-foreground">
316
+ {getMonthLabel(visibleMonth, locale)}
317
+ </div>
318
+ )}
319
+
320
+ <div className="grid grid-cols-7 gap-1 text-center text-[0.68rem] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
321
+ {weekdayLabels.map((weekday) => (
322
+ <div key={`${toDateKey(visibleMonth)}-${weekday}`} className="py-1.5">
323
+ {weekday}
324
+ </div>
325
+ ))}
326
+ </div>
327
+
328
+ <div className="mt-2 grid grid-cols-7 gap-1.5">
329
+ {days.map((date) => {
330
+ const dateKey = toDateKey(date)
331
+ const outside = !isSameMonth(date, visibleMonth)
332
+ const selected = mode === "single" ? value === dateKey : dateKey === range?.from || dateKey === range?.to
333
+ const inRange = mode === "range" && isWithinRange(dateKey, range?.from, range?.to)
334
+ const disabledReason = getDisabledReason(dateKey)
335
+ const disabled = Boolean(disabledReason)
336
+ const disabledLabel = disabledReason ? labels?.disabledDate?.(dateKey, disabledReason) : undefined
337
+
338
+ return (
339
+ <button
340
+ key={dateKey}
341
+ ref={(node) => {
342
+ if (node) buttonRefs.current.set(dateKey, node)
343
+ else buttonRefs.current.delete(dateKey)
344
+ }}
345
+ type="button"
346
+ disabled={disabled}
347
+ aria-label={disabledLabel ?? labels?.selectDate?.(dateKey) ?? dateKey}
348
+ aria-current={dateKey === todayKey ? "date" : undefined}
349
+ tabIndex={dateKey === tabbableDateKey ? 0 : -1}
350
+ title={disabledLabel}
351
+ data-selected={selected || undefined}
352
+ data-today={dateKey === todayKey || undefined}
353
+ data-outside={outside || undefined}
354
+ data-in-range={inRange || undefined}
355
+ data-disabled-reason={disabledReason}
356
+ className={cn(
357
+ "flex h-10 items-center justify-center rounded-[min(var(--radius-xl),16px)] border border-transparent text-sm font-medium outline-none transition-[background-color,color,border-color,box-shadow,transform] hover:border-border/70 hover:bg-accent hover:text-accent-foreground focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-35",
358
+ outside && "text-muted-foreground/42",
359
+ dateKey === todayKey && "border-primary/25 bg-accent/42 text-foreground",
360
+ inRange && "border-primary/12 bg-primary/10 text-foreground",
361
+ selected && "border-primary/85 bg-primary text-primary-foreground shadow-[0_10px_24px_color-mix(in_oklch,var(--primary),transparent_76%)] hover:bg-primary/92 hover:text-primary-foreground"
362
+ )}
363
+ onFocus={() => setFocusedDateKey(dateKey)}
364
+ onKeyDown={(event) => handleDateKeyDown(event, date)}
365
+ onClick={() => handleDateSelect(dateKey)}
366
+ >
367
+ {date.getDate()}
368
+ </button>
369
+ )
370
+ })}
371
+ </div>
276
372
  </div>
277
373
  ))}
278
374
  </div>
279
-
280
- <div className="mt-2 grid grid-cols-7 gap-1.5">
281
- {monthDays.map((date) => {
282
- const dateKey = toDateKey(date)
283
- const outside = !isSameMonth(date, currentMonth)
284
- const selected = mode === "single" ? value === dateKey : dateKey === range?.from || dateKey === range?.to
285
- const inRange = mode === "range" && isWithinRange(dateKey, range?.from, range?.to)
286
- const disabledReason = getDisabledReason(dateKey)
287
- const disabled = Boolean(disabledReason)
288
- const disabledLabel = disabledReason ? labels?.disabledDate?.(dateKey, disabledReason) : undefined
289
-
290
- return (
291
- <button
292
- key={dateKey}
293
- ref={(node) => {
294
- if (node) buttonRefs.current.set(dateKey, node)
295
- else buttonRefs.current.delete(dateKey)
296
- }}
297
- type="button"
298
- disabled={disabled}
299
- aria-label={disabledLabel ?? labels?.selectDate?.(dateKey) ?? dateKey}
300
- aria-current={dateKey === todayKey ? "date" : undefined}
301
- tabIndex={dateKey === tabbableDateKey ? 0 : -1}
302
- title={disabledLabel}
303
- data-selected={selected || undefined}
304
- data-today={dateKey === todayKey || undefined}
305
- data-outside={outside || undefined}
306
- data-in-range={inRange || undefined}
307
- data-disabled-reason={disabledReason}
308
- className={cn(
309
- "flex h-9 items-center justify-center rounded-xl border border-transparent text-sm font-medium outline-none transition-[background-color,color,border-color,box-shadow] hover:bg-accent hover:text-accent-foreground focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-35",
310
- outside && "text-muted-foreground/45",
311
- dateKey === todayKey && "border-primary/30 bg-accent/25 text-foreground",
312
- inRange && "border-accent/60 bg-accent/75 text-accent-foreground",
313
- selected && "border-primary/80 bg-primary text-primary-foreground shadow-[0_10px_24px_color-mix(in_oklch,var(--primary),transparent_76%)] hover:bg-primary/92 hover:text-primary-foreground"
314
- )}
315
- onFocus={() => setFocusedDateKey(dateKey)}
316
- onKeyDown={(event) => handleDateKeyDown(event, date)}
317
- onClick={() => handleDateSelect(dateKey)}
318
- >
319
- {date.getDate()}
320
- </button>
321
- )
322
- })}
323
- </div>
324
- </div>
325
- )
326
- }
375
+ </div>
376
+ )
377
+ }
327
378
 
328
379
  export { Calendar }
@@ -52,25 +52,35 @@ function DatePicker({
52
52
  return (
53
53
  <div data-slot="date-picker" className={cn("w-full", className)}>
54
54
  <Popover open={open} onOpenChange={setOpen}>
55
- <PopoverTrigger
56
- render={
57
- <Button
58
- type="button"
59
- variant="outline"
60
- disabled={disabled}
61
- className={cn("w-full justify-start text-left font-normal", !hasValue && "text-muted-foreground", triggerClassName)}
62
- />
63
- }
64
- >
55
+ <PopoverTrigger
56
+ render={
57
+ <Button
58
+ type="button"
59
+ variant="outline"
60
+ disabled={disabled}
61
+ className={cn(
62
+ "min-h-11 w-full justify-start rounded-[min(var(--radius-xl),16px)] border-border/80 bg-background/96 text-left font-normal shadow-[0_1px_0_rgba(255,255,255,0.06)]",
63
+ !hasValue && "text-muted-foreground",
64
+ triggerClassName
65
+ )}
66
+ />
67
+ }
68
+ >
65
69
  <CalendarIcon data-icon="inline-start" />
66
70
  <span className="min-w-0 flex-1 truncate">
67
71
  {hasValue ? formatValue(String(value)) : placeholder ?? labels?.placeholder ?? "Select date"}
68
72
  </span>
69
73
  </PopoverTrigger>
70
- <PopoverContent align="start" className={cn("w-auto p-0", contentClassName)}>
71
- <Calendar value={value} onValueChange={handleSelect} labels={labels} {...calendarProps} />
72
- </PopoverContent>
73
- </Popover>
74
+ <PopoverContent
75
+ align="start"
76
+ className={cn(
77
+ "w-auto rounded-[var(--radius-2xl)] border-border/80 bg-popover/98 p-0 shadow-[0_24px_80px_rgba(15,23,42,0.18)] backdrop-blur",
78
+ contentClassName
79
+ )}
80
+ >
81
+ <Calendar value={value} onValueChange={handleSelect} labels={labels} {...calendarProps} />
82
+ </PopoverContent>
83
+ </Popover>
74
84
  </div>
75
85
  )
76
86
  }