import { type HTMLAttributes, type ReactNode } from 'react';
import { type VariantProps } from 'class-variance-authority';
import { type AppointmentItem } from '../appointment-card';
/** Curated imperative handle — identifiers + lifecycle state only. */
export interface AppointmentTimelineHandle {
getItems: () => Array<{
id: string;
state: string;
}>;
selectItem: (id: string) => void;
jumpToToday: () => void;
}
export interface AppointmentTimelineProps extends Omit, 'onClick' | 'id' | 'title'> {
/** Stable instance id, surfaced as `data-component-id`. */
id?: string;
/** Appointments to render — any order; grouped + sorted internally. */
items: AppointmentItem[];
/**
* ISO-8601 "now" anchor — the timeline scrolls to this day on mount and the
* "Today" preset returns to it. Defaults to the current instant. Stories pass
* a fixed value for deterministic snapshots.
*/
nowIso?: string;
/** Panel heading. Defaults to the localised "Appointments". */
title?: string;
/** BCP-47 locale override for day headers + each AppointmentCard. */
locale?: string;
/** ISO-4217 currency code passed to each AppointmentCard. */
currency?: string;
/** Visual density passed to each AppointmentCard. */
size?: 'sm' | 'md';
/**
* Lead each row with the PATIENT (avatar + name as the row title) rather
* than the operator. Default `false`: the timeline was built for a
* patient-scoped rail, where repeating the name on every row is noise. A
* clinic-wide agenda — "who is coming in next" across the practice —
* passes `true`, and rows with no patient read as "No patient".
*/
showPatient?: boolean;
/** Fires when a row is activated. */
onOpenAppointment?: (item: AppointmentItem) => void;
/**
* The id of the currently selected appointment. The matching card
* renders with `selected` (info-tinted accent + `aria-current`) so the
* eye keeps its place in the list after a click.
*/
selectedId?: string;
/** Load earlier (past) appointments — fired when the top edge is reached. */
onLoadEarlier?: () => void;
/** Load later (future) appointments — fired when the bottom edge is reached. */
onLoadLater?: () => void;
/** Whether more past appointments exist. Defaults to `true` when `onLoadEarlier` is set. */
hasMoreEarlier?: boolean;
/** Whether more future appointments exist. Defaults to `true` when `onLoadLater` is set. */
hasMoreLater?: boolean;
/** Show a loading row at the top edge. */
loadingEarlier?: boolean;
/** Show a loading row at the bottom edge. */
loadingLater?: boolean;
/** Show the date-filter row (presets + jump-to-date). Default `true`. */
showFilters?: boolean;
/**
* Fired when a jump-to-date / preset targets a day outside the loaded range,
* so the consumer can load it. The timeline scrolls to the nearest rendered
* day until then.
*/
onJumpToDate?: (dateIso: string) => void;
emptyTitle?: string;
emptyDescription?: string;
/** Accessible name for the panel region (defaults to `title`). */
'aria-label'?: string;
/**
* Content rendered between the header/filter row and the scroll region —
* a summary strip, a "happening now" band, anything the host needs
* ahead of the day-grouped list. Omitted by default (no change to
* today's layout). Not part of the scroll region: it stays fixed like
* the header above it.
*/
headerExtra?: ReactNode;
/**
* Forwarded to every row's `AppointmentCard`: withhold the lifecycle
* badge for the default/expected state (`confirmed`). Default `false`
* (today's behaviour — every state shows its badge).
*/
hideDefaultStatus?: boolean;
}
declare const rootVariants: (props?: ({
size?: "sm" | "md" | null | undefined;
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
export declare const AppointmentTimeline: import("react").ForwardRefExoticComponent>;
/** Re-export of the size variant union for downstream typing. */
export type AppointmentTimelineSize = NonNullable['size']>;
export {};
//# sourceMappingURL=appointment-timeline.d.ts.map