import type { BreakdownItem } from "./breakdown"; import { type ColorName } from "./color_tokens"; /** DEADLINES — the countdown vocabulary: days left, what to call them, how loud they read. */ /** Usable as a `Text` `color`; `deadlineColor` is the badge side, keeping hue nuance. */ export type DeadlineTone = "danger" | "warning" | "muted"; /** * Defaults (1 / 3) from freight: a missed cut-off costs a sailing, and demurrage accrues inside * three days. */ export interface DeadlineThresholds { /** Default 1 (today and tomorrow). */ dangerWithinDays?: number; /** Default 3. */ warningWithinDays?: number; } /** * `due`: past it somebody is late. `expires`: past it a window has closed and nothing is late. They * read alike while ahead. */ export type DeadlineSense = "due" | "expires"; /** From `LoticsLocale.deadline`, or per instance. */ export interface DeadlineLabels { /** Given a positive count. */ overdue: (days: number) => string; /** Given a positive count; nothing is late, so nothing alarms. */ expired: (days: number) => string; /** "0 days left" is not what a reader wants. */ today: string; tomorrow: string; inDays: (days: number) => string; /** A deadline with an hour, on its own day: how long is left, in whole hours or minutes. */ inTime: (amount: number, unit: "hour" | "minute") => string; /** Gone past on its own day. */ overTime: (amount: number, unit: "hour" | "minute") => string; } export interface Deadline { label: string; date: Date; /** Negative once passed. */ days: number; } /** * Both ends collapse to midnight: rounding raw instants errs whenever `now` and the deadline * straddle noon, and cut-offs sit at 02:00. */ export declare function daysUntil(due: Date, now: Date): number; /** * Overdue folds into `danger` (the label distinguishes it); a closed `expires` window reads * `muted`, as nothing is left to act on. */ export declare function deadlineTone(days: number, thresholds?: DeadlineThresholds, sense?: DeadlineSense): DeadlineTone; /** For `Status`, where hue nuance survives; `muted` becomes `zinc`. */ export declare function deadlineColor(days: number, thresholds?: DeadlineThresholds): ColorName; export type AgeUnit = "day" | "week" | "month" | "year"; /** * Days for a week, weeks to two months, months to a year, then years: "3w" vs "5d" reads at a * glance. Floored, and a future day reads as today. */ export declare function ageSpan(days: number): { count: number; unit: AgeUnit; }; /** 0 and 1 get words: "0 days left" reads as broken. */ export declare function countdownLabel(days: number, labels: DeadlineLabels, sense?: DeadlineSense): string; /** * A deadline that holds its hour counts down by the clock on its own day — a departure at 14:00 is "2 h * left" at noon, never "Today" all day — and by days before and after it. */ export declare function countdownAt(due: Date, now: Date, labels: DeadlineLabels): { label: string; days: number; past: boolean; }; /** Late, today or tomorrow, which a queue is worked by; further out the date alone reads. */ export declare function dueWords(days: number, labels: DeadlineLabels): string | undefined; /** * Spread onto the date's `DetailRow`: due or overdue is `error`, the warning window `warning`, else * `description`. Spread it before the row's own `description`, or it silently overwrites it on * non-urgent rows. */ export declare function deadlineAnnotation(days: number, labels: DeadlineLabels, thresholds?: DeadlineThresholds): { description?: string; warning?: string; error?: string; }; /** * Undated candidates drop and overdue sorts first, so pass only open milestones: done-ness is not * knowable from a date. */ export declare function nearestDeadline(candidates: ReadonlyArray<{ label: string; date: Date | null | undefined; }>, now: Date): Deadline | null; /** From `LoticsLocale.ageing`, or per instance. */ export interface AgeingLabels { /** The amount not yet due. */ current: string; /** `(1, 30)` → "1–30 days". */ band: (from: number, to: number) => string; /** `(90)` → "90+ days". */ beyond: (from: number) => string; } /** Thirty / sixty / ninety is how receivables age; a faster trade passes its own. */ export declare const AGEING_EDGES: readonly number[]; /** * The bands a `Breakdown` draws above a receivables register, named and coloured: one hue strongest * at the oldest (`ramp`), not-yet-due neutral. Every band is returned, empty ones too; not-yet-due * is a band so the bar reads. Items are dated by construction: an undated amount has no age, so the * caller decides. */ export declare function ageingBands(items: ReadonlyArray<{ amount: number; due: Date; }>, now: Date, labels: AgeingLabels, edges?: readonly number[]): BreakdownItem[];