@motor-hero/ui-kit 0.34.1 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motor-hero/ui-kit",
3
- "version": "0.34.1",
3
+ "version": "0.35.0",
4
4
  "description": "Componentes React reutilizáveis para o ecossistema MotorHero — shadcn/ui + Tailwind CSS v4",
5
5
  "author": "MotorHero",
6
6
  "license": "UNLICENSED",
@@ -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"
@@ -100,7 +100,12 @@ const calendarClassNames = {
100
100
  months: "relative flex flex-col gap-4",
101
101
  month: "flex w-full flex-col gap-4",
102
102
  month_caption: "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)",
103
- caption_label: "text-sm font-medium select-none",
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",
104
109
  nav: "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
105
110
  button_previous: navButtonClass,
106
111
  button_next: navButtonClass,
@@ -118,14 +123,17 @@ const calendarClassNames = {
118
123
  }
119
124
 
120
125
  const calendarComponents = {
121
- Chevron: ({ orientation }: { orientation?: string }) =>
122
- orientation === "left" ? (
123
- <ChevronLeft className="size-4" />
124
- ) : (
125
- <ChevronRight className="size-4" />
126
- ),
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
+ },
127
131
  }
128
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
+
129
137
  /**
130
138
  * DatePicker / DateTimePicker — calendário + campo digitável com máscara
131
139
  * (nunca o `<input type="date"/time">` nativo). Desktop: Popover não-modal;
@@ -160,6 +168,12 @@ function DatePickerImpl({
160
168
  const committedDate = withTime ? dateTimeToDate(value) : dateOnlyToDate(value)
161
169
  const displayValue = displayFor(value, withTime)
162
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())
163
177
 
164
178
  const setOpen = (next: boolean) => {
165
179
  setOpenRaw(next)
@@ -261,6 +275,10 @@ function DatePickerImpl({
261
275
  <DayPicker
262
276
  mode="single"
263
277
  locale={ptBR}
278
+ captionLayout="dropdown"
279
+ formatters={{ formatMonthDropdown }}
280
+ startMonth={startMonth}
281
+ endMonth={endMonth}
264
282
  selected={withTime ? pendingDate : committedDate}
265
283
  defaultMonth={(withTime ? pendingDate : committedDate) ?? new Date()}
266
284
  onSelect={(date) => date && handleCalendarSelect(date)}