"use client"
import * as React from "react"
import type { DateRange } from "react-day-picker"
import { cn } from "../../lib/utils"
import { fieldControlInnerClass } from "../../lib/field-control"
import { formatDateFromDate } from "../../lib/date-filter"
import { Calendar } from "./calendar"
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
} from "./input-group"
import { MaskedInput, exxatMaskPatterns } from "./input-mask"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "./popover"
import { Tip } from "./tip"
export const DATE_PICKER_ICON_CLASS = "fa-light fa-calendar"
/** Matches Select trigger + InputGroup field chrome (value left, calendar icon right). */
const datePickerTriggerButtonClass = cn(
fieldControlInnerClass(),
"flex min-w-0 flex-1 items-center justify-between gap-2 px-2.5 text-start text-sm font-normal text-foreground outline-none",
"disabled:cursor-not-allowed disabled:opacity-50",
"[&_span]:truncate",
)
export interface DatePickerFieldProps {
value: Date | undefined
onChange: (d: Date | undefined) => void
id?: string
disabled?: boolean
/** Passed to the trigger row (e.g. `h-8 text-sm` in compact drawers). */
triggerClassName?: string
fromYear?: number
toYear?: number
popoverAlign?: "start" | "center" | "end"
popoverClassName?: string
}
/**
* Calendar + popover trigger — same pattern as New Placement schedule dates (WCAG: button exposes label, not raw text input).
*/
export function DatePickerField({
value,
onChange,
id,
disabled,
triggerClassName,
fromYear = 2020,
toYear = 2032,
popoverAlign = "start",
popoverClassName,
}: DatePickerFieldProps) {
return (
)
}
export function formatDateRangeForDisplay(range: DateRange | undefined): string {
if (!range?.from) return "Pick a date"
if (!range.to) return formatDateFromDate(range.from)
return `${formatDateFromDate(range.from)} – ${formatDateFromDate(range.to)}`
}
export interface DateRangePickerFieldProps {
value: DateRange | undefined
onChange: (range: DateRange | undefined) => void
id?: string
disabled?: boolean
placeholder?: string
/** Passed to the trigger row (e.g. `h-8 text-sm` in compact drawers). */
triggerClassName?: string
fromYear?: number
toYear?: number
popoverAlign?: "start" | "center" | "end"
popoverClassName?: string
/** Default 2 — matches shadcn range picker; use 1 in narrow surfaces. */
numberOfMonths?: number
}
/**
* Range calendar + popover trigger — shadcn DatePickerWithRange pattern (Field wrapper lives at call site).
*/
export function DateRangePickerField({
value,
onChange,
id,
disabled,
placeholder = "Pick a date",
triggerClassName,
fromYear = 2020,
toYear = 2032,
popoverAlign = "start",
popoverClassName,
numberOfMonths = 2,
}: DateRangePickerFieldProps) {
const label = value?.from ? formatDateRangeForDisplay(value) : placeholder
return (
)
}
export interface DateTextInputFieldProps {
value: string
onValueChange: (value: string) => void
"aria-label": string
id?: string
placeholder?: string
className?: string
inputClassName?: string
autoFocus?: boolean
disabled?: boolean
fromYear?: number
toYear?: number
iconButtonVariant?: "ghost" | "outline"
popoverAlign?: "start" | "center" | "end"
popoverClassName?: string
}
function parseMdyToLocalDate(raw: string): Date | undefined {
const match = raw.trim().match(/^(\d{2})\/(\d{2})\/(\d{4})$/)
if (!match) return undefined
const month = Number(match[1])
const day = Number(match[2])
const year = Number(match[3])
if (month < 1 || month > 12 || day < 1 || day > 31) return undefined
const date = new Date(year, month - 1, day, 12, 0, 0, 0)
if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) return undefined
return date
}
function formatLocalDateToMdy(date: Date): string {
const month = String(date.getMonth() + 1).padStart(2, "0")
const day = String(date.getDate()).padStart(2, "0")
const year = String(date.getFullYear())
return `${month}/${day}/${year}`
}
export function DateTextInputField({
value,
onValueChange,
"aria-label": ariaLabel,
id,
placeholder = "MM/DD/YYYY",
className,
inputClassName,
autoFocus,
disabled,
fromYear = 2020,
toYear = 2032,
iconButtonVariant = "ghost",
popoverAlign = "end",
popoverClassName,
}: DateTextInputFieldProps) {
return (
onValueChange(event.target.value)}
className={cn("flex-1 rounded-none", fieldControlInnerClass(), inputClassName)}
autoFocus={autoFocus}
disabled={disabled}
/>
onValueChange(next ? formatLocalDateToMdy(next) : "")}
initialFocus
fromYear={fromYear}
toYear={toYear}
captionLayout="dropdown"
/>
)
}