/** * Pure helpers for the SearchDateRangePicker hook. * * Goals: * - Keep the hook smaller and focused on React state/effects. * - Keep complex logic testable without rendering. */ export function normalizeDayClickArgs(args) { // react-day-picker handler signatures have differed across versions. // We normalize both of these variants: // - onDayClick(day, modifiers, event) // - onDayClick(event, day, modifiers) // // Background: // - There has been historical ambiguity around onDayClick argument order. :contentReference[oaicite:2]{index=2} const a0 = args?.[0]; const a1 = args?.[1]; const a2 = args?.[2]; if (a0 instanceof Date) return { day: a0, modifiers: a1 || null }; if (a1 instanceof Date) return { day: a1, modifiers: a2 || null }; return { day: null, modifiers: null }; } export function buildCalendarState({ fromDate, toDate, isRangeInvalid }) { let calendarSelected = undefined; let invalidInterval = null; if (fromDate && toDate) { if (isRangeInvalid) { const min = fromDate < toDate ? fromDate : toDate; const max = fromDate < toDate ? toDate : fromDate; calendarSelected = { from: min, to: max }; invalidInterval = { from: min, to: max }; } else { calendarSelected = { from: fromDate, to: toDate }; } } else if (fromDate) { calendarSelected = { from: fromDate, to: undefined }; } else if (toDate) { // "to only" -> visually represent as a single-day range calendarSelected = { from: toDate, to: toDate }; } const calendarModifiers = isRangeInvalid && invalidInterval ? { invalid_range: invalidInterval, invalid_range_edge: [fromDate, toDate].filter(Boolean), } : undefined; const calendarModifiersClassNames = isRangeInvalid && invalidInterval ? { invalid_range: "bg-destructive/10 text-destructive dark:bg-destructive/20 dark:text-destructive", invalid_range_edge: "!bg-destructive !text-white hover:!bg-destructive/90", } : undefined; return { calendarSelected, calendarModifiers, calendarModifiersClassNames }; }