/**
* Planner — a month of days, each carrying what falls on it.
*
* ```tsx
* const [month, setMonth] = useState(new Date());
*
*
*
*
*
*
*
*
*
*
* {(date, entries) => {entries.length} on {date.toDateString()}}
*
*
* ```
*
* ## How it differs from Calendar
*
* `Calendar` picks a date and answers with one. This shows what is already on
* the days and answers with the day you asked about — the selection exists to
* open something, not to be submitted.
*
* ## Why it draws its own Frame
*
* A month at a glance is a widget: a boundary, a strip along the top carrying
* the month and the way through it, and a footer that holds still while the
* middle changes. That is `Frame`, so the root renders one instead of leaving
* every caller to assemble the same shell. Pass `frame={false}` to drop it,
* for a planner in a sheet or a card that already draws its own edge.
*
* ## Why the grid is always six weeks
*
* A month can span five weeks or six. Drawn at its natural height the panel
* jumps as you page through the year and the days appear to move under your
* thumb, so the grid is always six rows and the last one is sometimes all
* next month. `Calendar` fixes its height for the same reason.
*
* ## Why a day says more than its date
*
* The marker on a day is a coloured dot, and colour is a signal that does not
* reach everyone looking at it. So the legend prints its label beside every
* swatch, and a day is spoken as its date, how many entries it carries and
* which categories they belong to. Neither is decoration: between them they
* are the whole content of the grid for somebody who cannot see it.
*/
import { type ReactNode } from 'react';
import { View, type ViewProps } from 'react-native';
import { type TextProps } from '../../primitives/text.js';
import { type CalendarSystem, type DateLocale } from '../../utils/date.js';
import { type PlannerCountedCategory } from './planner-entries.js';
/**
* What a day cell draws.
*
* `default` is a number, a marker and small icons. `tiles` gives the day over
* to one large icon tinted with its category's colour, with the date in the
* corner. `calendar` names each entry in a block under a centred date, on an
* open grid ruled off by week.
*/
export type PlannerVariant = 'default' | 'tiles' | 'calendar';
/** One thing that falls on a day. */
export interface PlannerEntry {
/** Stable across renders; it keys the cell's contents. */
id: string;
/** When it falls. The time of day is kept but not read by the grid. */
date: Date;
/** Named in the dialog and, through its category, in the day's spoken label. */
label: string;
/** Matches a `PlannerCategory` id. Without one the entry is still counted. */
category?: string;
/** Drawn in the cell — a brand mark, an avatar, a glyph. */
icon?: ReactNode;
/**
* This entry's own colour, for a mark that belongs to the entry rather than
* to a group of them — a brand. It wins over the category's colour, and
* under `tiles` it is what tints the day.
*/
color?: string;
}
/** A group of entries: the key to a colour, and a line in the legend. */
export interface PlannerCategory {
id: string;
/** Printed beside the swatch, and spoken as part of a day that carries it. */
label: string;
/**
* Which `--color-chart-*` token the dot takes, 1 to 5. Categories without
* one are numbered in the order they are declared.
*/
colorIndex?: number;
/** An explicit colour, for a brand that is not the theme's to choose. */
color?: string;
}
export interface PlannerProps extends Omit {
className?: string;
/** The month on show. Leave it out for an uncontrolled planner. */
month?: Date;
defaultMonth?: Date;
onMonthChange?: (month: Date) => void;
/** Everything the planner knows about, in any order and any month. */
entries?: PlannerEntry[];
/** The colour key. Declaration order is legend order and palette order. */
categories?: PlannerCategory[];
/** The open day. `null` is none. Leave it out for an uncontrolled planner. */
selected?: Date | null;
defaultSelected?: Date | null;
onSelectedChange?: (date: Date | null) => void;
/** Runs before the selection moves, whether or not `Details` is present. */
onDayPress?: (date: Date, entries: PlannerEntry[]) => void;
/**
* What each day draws. `tiles` is one large icon per day, tinted by its
* category; `calendar` names every entry and needs the height to do it.
*/
variant?: PlannerVariant;
/**
* Stretch the grid to its container instead of standing at its own height.
* For a planner that owns a screen — the six weeks share out whatever is
* left after the header, the legend and anything below them.
*/
fill?: boolean;
/**
* How many entries a cell draws before it counts the rest. Default `2`, or
* `3` under `calendar`, which has the room; `tiles` draws one whatever you
* pass.
*/
entryLimit?: number;
/** First day of the week, 0 is Sunday. Defaults to the locale's. */
weekStartsOn?: number | 'auto';
locale?: DateLocale;
calendar?: CalendarSystem;
/** Draw the surrounding `Frame`. Off for a planner in a sheet or a card. */
frame?: boolean;
children?: ReactNode;
}
export interface PlannerHeaderProps {
children?: ReactNode;
}
/**
* The strip along the top of the frame. Put `Title`, `Today` and `Nav` in it.
*
* The strip has two ends rather than an even spread. What the month *is* —
* its name, and the way back to today — reads from the leading edge; what
* *moves* it sits at the trailing edge, under the thumb that reaches for it.
* Spaced evenly across a full-width strip they read as three unrelated
* controls instead of a label and a pair of buttons.
*/
declare function PlannerHeader({ children }: PlannerHeaderProps): import("react").JSX.Element;
declare namespace PlannerHeader {
var displayName: string;
}
export interface PlannerTitleProps extends Omit {
/** Replaces the month name, for a title that says something else. */
children?: ReactNode;
}
/** The month on show, in the calendar system and locale the grid uses. */
declare function PlannerTitle({ children, className, ...props }: PlannerTitleProps): import("react").JSX.Element;
declare namespace PlannerTitle {
var displayName: string;
}
export interface PlannerTodayProps {
/** Replaces the word on the pill. */
children?: ReactNode;
}
/** Jumps back to the month today is in, and selects nothing. */
declare function PlannerToday({ children }: PlannerTodayProps): import("react").JSX.Element;
declare namespace PlannerToday {
var displayName: string;
}
export interface PlannerNavProps {
className?: string;
}
/** Back and forward a month. */
declare function PlannerNav({ className }: PlannerNavProps): import("react").JSX.Element;
declare namespace PlannerNav {
var displayName: string;
}
export interface PlannerActionProps {
children?: ReactNode;
}
/** The trailing end of the header strip, for a button of the caller's. */
declare function PlannerAction({ children }: PlannerActionProps): import("react").JSX.Element;
declare namespace PlannerAction {
var displayName: string;
}
/** What a custom cell is handed. Everything the default cell draws from. */
export interface PlannerDayState {
date: Date;
entries: PlannerEntry[];
isToday: boolean;
isSelected: boolean;
isInMonth: boolean;
}
export type PlannerDayRenderer = (state: PlannerDayState) => ReactNode;
export interface PlannerGridProps {
className?: string;
/** Draws a cell yourself. It is handed the day and what falls on it. */
renderDay?: PlannerDayRenderer;
}
/**
* The weekday row and the six weeks below it.
*
* React Native has no per-cell grid vocabulary — no `gridcell`, no `row` — so
* a screen reader never hears "row three, column five" and cannot fall back on
* position for context. Every day therefore carries its own full date, and the
* weekday headings are hidden rather than read out 42 times over.
*/
declare function PlannerGrid({ className, renderDay }: PlannerGridProps): import("react").JSX.Element;
declare namespace PlannerGrid {
var displayName: string;
}
export interface PlannerDayProps {
date: Date;
renderDay?: PlannerDayRenderer;
}
/** One cell. Pressing it selects the day and opens whatever is bound to it. */
declare function PlannerDay({ date, renderDay }: PlannerDayProps): import("react").JSX.Element;
export interface PlannerLegendProps {
className?: string;
/** Print each category's count for the month beside its label. */
counts?: boolean;
/** Sits at the trailing end — a total, a currency, whatever the month adds to. */
children?: ReactNode;
}
/**
* The key to the dots.
*
* It prints the label beside every swatch, because a column of coloured dots
* with nothing to read them against is a quiz.
*/
declare function PlannerLegend({ className, counts, children }: PlannerLegendProps): import("react").JSX.Element;
declare namespace PlannerLegend {
var displayName: string;
}
export interface PlannerSummaryProps extends Omit {
/** Replaces the count, for a total that is money rather than entries. */
children?: ReactNode;
}
/** What the month adds up to. Counts this month only, never the days either side. */
declare function PlannerSummary({ children, ...props }: PlannerSummaryProps): import("react").JSX.Element;
declare namespace PlannerSummary {
var displayName: string;
}
export interface PlannerFooterProps {
className?: string;
children?: ReactNode;
}
/** The strip along the bottom, for tools that act on the month. */
declare function PlannerFooter({ className, children }: PlannerFooterProps): import("react").JSX.Element;
declare namespace PlannerFooter {
var displayName: string;
}
export interface PlannerDetailsProps {
className?: string;
/** Title above the children. Defaults to the day's full date. */
title?: ReactNode;
/**
* The line under the title. Defaults to how many entries the day carries,
* so the dialog answers "how much of this is there" before it is read.
* Pass `null` to drop it.
*/
description?: ReactNode;
/** Given the open day and what falls on it. */
children: (date: Date, entries: PlannerEntry[]) => ReactNode;
}
/**
* A dialog bound to the open day.
*
* The planner owns the grid and the binding; what the dialog says is the
* application's, because the contents of a day are its data and not the
* component's. Leave it out and `onDayPress` is still called — a planner that
* pushes a screen instead of opening a dialog wants that and nothing else.
*/
declare function PlannerDetails({ className, title, description, children }: PlannerDetailsProps): import("react").JSX.Element;
declare namespace PlannerDetails {
var displayName: string;
}
export interface PlannerScrollerProps {
className?: string;
/**
* How many weeks either side of the opening month can be reached. Default
* `53`, about a year each way.
*/
weeks?: number;
/** The height of one week row. Default `96`. */
rowHeight?: number;
/** Draws a cell yourself. It is handed the day and what falls on it. */
renderDay?: PlannerDayRenderer;
}
/**
* The weeks of the year, scrolled through rather than paged.
*
* A month grid answers "what does this month look like"; a scroller answers
* "what is coming", which does not stop at the end of a month. The week
* straddling the boundary is drawn once, in one piece, instead of appearing cut
* in half at the bottom of one page and again at the top of the next.
*
* The range is bounded rather than endless. A scroller has to know its own
* height to place a scrollbar and to jump to a month without rendering its way
* there, and neither is possible over a list with no end.
*
* The month in the header follows the scroll: whichever month holds most of the
* first week on screen is the one named, and the days either side of it grey
* out. `Planner.Nav` and `Planner.Today` still work — they scroll the list
* rather than replacing what is in it.
*/
declare function PlannerScroller({ className, weeks: span, rowHeight, renderDay, }: PlannerScrollerProps): import("react").JSX.Element;
declare namespace PlannerScroller {
var displayName: string;
}
export declare const Planner: import("react").ForwardRefExoticComponent> & {
Header: typeof PlannerHeader;
Title: typeof PlannerTitle;
Today: typeof PlannerToday;
Nav: typeof PlannerNav;
Action: typeof PlannerAction;
Grid: typeof PlannerGrid;
Scroller: typeof PlannerScroller;
Day: typeof PlannerDay;
Legend: typeof PlannerLegend;
Summary: typeof PlannerSummary;
Footer: typeof PlannerFooter;
Details: typeof PlannerDetails;
};
export type { PlannerCountedCategory };
//# sourceMappingURL=index.d.ts.map