import type { ReactNode } from "react"; import type { PlainDate } from "./plainDate.ts"; export type DateGridProps = { firstDayOfWeek: number; focusedDate: PlainDate; /** * The month this grid draws — any date inside it. `DatePicker` * renders two of these in range mode, so the month is a prop * rather than derived from the focus. */ gridMonth: PlainDate; /** * Whether the keyboard is *in* the grid. Only the grid that owns * focus pulls it onto its focused cell; the other one would rip * focus back and forth between the two months on every arrow key. */ isGridFocused: boolean; isRange: boolean; label: string; locale?: string; maximum?: PlainDate; minimum?: PlainDate; onFocusDate: (date: PlainDate) => void; onHoverDate: (date: null | PlainDate) => void; onSelectDate: (date: PlainDate) => void; /** * The end of the band being drawn *right now* — the committed end, * or the hovered/keyboard-focused day while the second click is * still outstanding. Painting the pending half is the difference * between a range picker you can aim and one you have to guess at. */ previewEnd: null | PlainDate; rangeStart: null | PlainDate; selectedDates: readonly PlainDate[]; today: PlainDate; }; /** * One month, as a real ``. * * ### Why the roving focus is arithmetic and not `useRovingFocus` * * `@charcuterie/logic`'s `RovingFocus` is a **registration** kind: * members register from an effect and `next`/`previous`/`first`/ * `last` walk that list. `SegmentedControl` and `Tabs` are exactly * that shape, and a calendar is not, for two reasons that are worth * stating rather than discovering: * * - The movement is two-dimensional and it is *date* arithmetic, not * list traversal. ArrowDown is "+7 days", which is a different * thing from "the seventh next registered member" the moment a * month does not start on the first column. * - The move can leave the rendered set entirely. ArrowRight on 31 * August lands on 1 September, which is a day this grid has not * rendered and no member has registered. A registration list * cannot express a move to something that does not exist yet; a * day number can, and re-rendering the grid around it is the * correct response. * * So the focused *date* is the state and the DOM follows it. This is * the same conclusion `Field` reached about `createLinkedIds` — the * state kind is real and this is not its shape. * * ### The cell is the gridcell * * `
` rather than `