'use client' import { forwardRef, useState } from 'react' import * as PopoverPrimitive from '@radix-ui/react-popover' import { ChevronDown } from '../../icons' import { cn } from '../../lib/cn' import { Calendar, formatDateLabel, formatDateRangeLabel } from '../calendar/calendar' import { chipVariants, TRIGGER_BORDER_CLASS } from '../chip/chip' import { chipContentLabelClass } from '../chip/chip-chrome' import { POPOVER_ANIMATION_CLASSES } from '../popover/popover-animation' interface ChipDatePickerBaseProps { /** * Trigger chrome. `filled` (default) is the bordered field chip with the owned * chevron; `ghost` is the bare toolbar pill — no border, no chevron — for * visual parity with neighboring `Chip` buttons. */ variant?: 'filled' | 'ghost' /** * Overrides the trigger text, e.g. a calendar period label ("June 2026") whose * granularity differs from the selected value. */ label?: string /** Shown in the trigger when nothing is selected. */ placeholder?: string /** Aligns the calendar popover relative to the trigger. */ align?: 'start' | 'center' | 'end' /** Disables the trigger. */ disabled?: boolean /** Stretch the trigger to fill its container (mirrors `Chip`'s `fullWidth`). */ fullWidth?: boolean /** Removes the default `mx-0.5` cluster margin (mirrors `Chip`'s `flush`). */ flush?: boolean /** Forwarded class for the trigger button. */ className?: string } interface ChipDatePickerSingleProps extends ChipDatePickerBaseProps { mode?: 'single' /** Selected date as a `YYYY-MM-DD` string. */ value?: string /** Called with the picked date in `YYYY-MM-DD` format. */ onChange?: (value: string) => void /** * Today's calendar day (`YYYY-MM-DD`) in the caller's effective timezone; * defaults to the runtime's local day (mirrors `Calendar`'s `today`). */ today?: string } interface ChipDatePickerRangeProps extends ChipDatePickerBaseProps { mode: 'range' /** Range start as a `YYYY-MM-DD` (or `YYYY-MM-DDTHH:mm`) string. */ startDate?: string /** Range end as a `YYYY-MM-DD` (or `YYYY-MM-DDTHH:mm`) string. */ endDate?: string /** Adds start/end time-of-day inputs; emits `YYYY-MM-DDTHH:mm` bounds. */ showTime?: boolean /** Called on Apply with the ordered range bounds. */ onRangeChange: (start: string, end: string) => void } export type ChipDatePickerProps = ChipDatePickerSingleProps | ChipDatePickerRangeProps /** * Date counterpart to {@link ChipDropdown} — a chip-styled trigger that opens a * {@link Calendar} in a popover. The default `filled` trigger reuses * `chipVariants` (filled + border) and the owned chevron for visual parity with * the other chip field controls; `ghost` renders the bare toolbar pill instead. * * `mode='single'` (default) commits on day click. `mode='range'` opens the * range calendar — start/end staged behind Clear/Cancel/Apply, with optional * time-of-day inputs — and commits via `onRangeChange`. * * @example * * * @example * */ const ChipDatePicker = forwardRef( function ChipDatePicker(props, ref) { const { variant = 'filled', label, placeholder = props.mode === 'range' ? 'Select date range' : 'Select date', align = 'start', disabled, fullWidth, flush, className, } = props const [open, setOpen] = useState(false) const triggerText = label ?? (props.mode === 'range' ? formatDateRangeLabel(props.startDate, props.endDate) : formatDateLabel(props.value)) return ( {props.mode === 'range' ? ( { props.onRangeChange(start, end) setOpen(false) }} onCancel={() => setOpen(false)} /> ) : ( { props.onChange?.(next) setOpen(false) }} /> )} ) } ) ChipDatePicker.displayName = 'ChipDatePicker' export { ChipDatePicker }