@motor-hero/ui-kit 0.34.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/date-picker.d.ts.map +1 -1
- package/dist/index.cjs +29 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +31 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/date-picker.tsx +44 -25
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
|
2
2
|
import { InputMask } from "@react-input/mask"
|
|
3
|
-
import { format, isValid, parse } from "date-fns"
|
|
3
|
+
import { endOfYear, format, isValid, parse, subYears } from "date-fns"
|
|
4
4
|
import { ptBR } from "date-fns/locale"
|
|
5
|
-
import { CalendarIcon, ChevronLeft, ChevronRight, Clock } from "lucide-react"
|
|
5
|
+
import { CalendarIcon, ChevronDown, ChevronLeft, ChevronRight, Clock } from "lucide-react"
|
|
6
6
|
import * as React from "react"
|
|
7
7
|
import { DayPicker, type Matcher } from "react-day-picker"
|
|
8
8
|
import { Drawer as DrawerPrimitive } from "vaul"
|
|
@@ -91,25 +91,31 @@ const triggerInputClass =
|
|
|
91
91
|
const fieldInputClass =
|
|
92
92
|
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
93
93
|
|
|
94
|
+
/** Botão "ghost" (sem borda, hover:bg-accent) — mesma variante que o shadcn usa nas
|
|
95
|
+
* setas de navegação do calendário; inline porque o ui-kit não tem um Button próprio. */
|
|
96
|
+
const navButtonClass =
|
|
97
|
+
"inline-flex size-(--cell-size) shrink-0 select-none items-center justify-center rounded-md p-0 transition-colors hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:opacity-50"
|
|
98
|
+
|
|
94
99
|
const calendarClassNames = {
|
|
95
|
-
months: "flex flex-col",
|
|
96
|
-
month: "flex flex-col gap-4",
|
|
97
|
-
month_caption: "flex
|
|
98
|
-
caption_label:
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
months: "relative flex flex-col gap-4",
|
|
101
|
+
month: "flex w-full flex-col gap-4",
|
|
102
|
+
month_caption: "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)",
|
|
103
|
+
caption_label:
|
|
104
|
+
"flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm font-medium select-none [&>svg]:size-3.5 [&>svg]:text-muted-foreground",
|
|
105
|
+
dropdowns: "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium",
|
|
106
|
+
dropdown_root:
|
|
107
|
+
"relative rounded-md border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50",
|
|
108
|
+
dropdown: "absolute inset-0 bg-popover opacity-0",
|
|
109
|
+
nav: "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
|
|
110
|
+
button_previous: navButtonClass,
|
|
111
|
+
button_next: navButtonClass,
|
|
112
|
+
month_grid: "w-full border-collapse",
|
|
105
113
|
weekdays: "flex",
|
|
106
|
-
weekday: "
|
|
107
|
-
week: "flex w-full
|
|
108
|
-
day: "relative p-0 text-center
|
|
114
|
+
weekday: "flex-1 select-none rounded-md text-[0.8rem] font-normal text-muted-foreground",
|
|
115
|
+
week: "mt-2 flex w-full",
|
|
116
|
+
day: "relative aspect-square h-full w-full select-none p-0 text-center aria-selected:[&>button]:bg-primary aria-selected:[&>button]:text-primary-foreground aria-selected:[&>button]:hover:bg-primary",
|
|
109
117
|
day_button:
|
|
110
|
-
"inline-flex size-
|
|
111
|
-
selected:
|
|
112
|
-
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground rounded-md [&>button]:bg-primary [&>button]:text-primary-foreground",
|
|
118
|
+
"inline-flex aspect-square size-auto w-full min-w-(--cell-size) items-center justify-center rounded-md p-0 font-normal transition-colors hover:bg-accent hover:text-accent-foreground",
|
|
113
119
|
today: "bg-accent text-accent-foreground rounded-md",
|
|
114
120
|
outside: "text-muted-foreground opacity-50",
|
|
115
121
|
disabled: "text-muted-foreground opacity-50 pointer-events-none",
|
|
@@ -117,14 +123,17 @@ const calendarClassNames = {
|
|
|
117
123
|
}
|
|
118
124
|
|
|
119
125
|
const calendarComponents = {
|
|
120
|
-
Chevron: ({ orientation }: { orientation?: string }) =>
|
|
121
|
-
orientation === "left"
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
),
|
|
126
|
+
Chevron: ({ orientation }: { orientation?: string }) => {
|
|
127
|
+
if (orientation === "left") return <ChevronLeft className="size-4" />
|
|
128
|
+
if (orientation === "right") return <ChevronRight className="size-4" />
|
|
129
|
+
return <ChevronDown className="size-4" />
|
|
130
|
+
},
|
|
126
131
|
}
|
|
127
132
|
|
|
133
|
+
/** Nome curto do mês em pt-BR pro rótulo do dropdown (ex. "jul") — explícito porque
|
|
134
|
+
* `toLocaleString("default", ...)` seguiria o locale do navegador, não o do app. */
|
|
135
|
+
const formatMonthDropdown = (date: Date) => date.toLocaleString("pt-BR", { month: "short" })
|
|
136
|
+
|
|
128
137
|
/**
|
|
129
138
|
* DatePicker / DateTimePicker — calendário + campo digitável com máscara
|
|
130
139
|
* (nunca o `<input type="date"/time">` nativo). Desktop: Popover não-modal;
|
|
@@ -159,6 +168,12 @@ function DatePickerImpl({
|
|
|
159
168
|
const committedDate = withTime ? dateTimeToDate(value) : dateOnlyToDate(value)
|
|
160
169
|
const displayValue = displayFor(value, withTime)
|
|
161
170
|
const matchers = toMatchers(minDate, maxDate, disabledDates)
|
|
171
|
+
// Alcance do dropdown de ano: minDate/maxDate quando informados, senão o mesmo
|
|
172
|
+
// padrão da lib (100 anos atrás -> fim do ano atual) — calculado explícito nos dois
|
|
173
|
+
// lados porque passar só um dos dois via prop faz a lib truncar o outro (visto na
|
|
174
|
+
// prática: só uma opção de ano no lado sem prop), em vez de cair no padrão dela.
|
|
175
|
+
const startMonth = dateOnlyToDate(minDate) ?? subYears(new Date(), 100)
|
|
176
|
+
const endMonth = dateOnlyToDate(maxDate) ?? endOfYear(new Date())
|
|
162
177
|
|
|
163
178
|
const setOpen = (next: boolean) => {
|
|
164
179
|
setOpenRaw(next)
|
|
@@ -260,11 +275,15 @@ function DatePickerImpl({
|
|
|
260
275
|
<DayPicker
|
|
261
276
|
mode="single"
|
|
262
277
|
locale={ptBR}
|
|
278
|
+
captionLayout="dropdown"
|
|
279
|
+
formatters={{ formatMonthDropdown }}
|
|
280
|
+
startMonth={startMonth}
|
|
281
|
+
endMonth={endMonth}
|
|
263
282
|
selected={withTime ? pendingDate : committedDate}
|
|
264
283
|
defaultMonth={(withTime ? pendingDate : committedDate) ?? new Date()}
|
|
265
284
|
onSelect={(date) => date && handleCalendarSelect(date)}
|
|
266
285
|
disabled={matchers}
|
|
267
|
-
className={withTime ? "p-0" : "p-3"}
|
|
286
|
+
className={cn(withTime ? "p-0" : "p-3", "[--cell-size:2rem]")}
|
|
268
287
|
classNames={calendarClassNames}
|
|
269
288
|
components={calendarComponents}
|
|
270
289
|
/>
|