import { KanbanBandToggleActivation } from "./column-band-header.js"; import { KanbanColumnBand, KanbanGroup } from "./grouping.js"; import { KanbanBoardCell, KanbanBoardColumn, KanbanBoardMatrix } from "./matrix.js"; import { ReactNode, Ref } from "react"; //#region src/kanban/subgroup-board.d.ts export type KanbanSubgroupColumnHeaderContext = { column: KanbanBoardColumn; count: number; }; export type KanbanSubgroupLaneIdentityContext = { group: KanbanGroup; count: number; }; /** One column's cell in a lane's own row, and what that cell stands for. */ export type KanbanSubgroupLaneColumnSummaryContext = { lane: KanbanGroup; column: KanbanBoardColumn; /** Rows in this lane/column intersection, including zero. */ count: number; }; export type KanbanSubgroupLaneColumnActionContext = { lane: KanbanGroup; column: KanbanBoardColumn; }; export type KanbanSubgroupCellContext = { cell: KanbanBoardCell; /** Number of rows in this lane/column intersection, including zero. */ count: number; laneValue: string | null; /** The band this cell's column belongs to, or `null` outside any band. */ band: KanbanColumnBand | null; }; export type KanbanSubgroupBandHeaderContext = { band: KanbanColumnBand; columns: KanbanBoardColumn[]; /** Rows across the band's columns, every lane included. */ count: number; /** The persisted state the toggle reports and flips. */ collapsed: boolean; /** * Whether the band renders as one narrow slot right now. False while a * collapsed band peeks open under the pointer, so a caption can show its * name and offer to pin the band open. */ folded: boolean; /** * A custom caption may report which way it was activated (pointer vs. * keyboard); the board itself has no use for the distinction and passes * it through unread, purely as information for a host's own header. */ onCollapsedChange: (collapsed: boolean, activation?: KanbanBandToggleActivation) => void; }; /** * One lane's slot for a collapsed band: the cells it hides, so a host can * register the slot as a drop target that lands in the band's first column * (or asks which), and the count it stands in for. */ export type KanbanSubgroupCollapsedBandCellContext = { band: KanbanColumnBand; cells: KanbanBoardCell[]; count: number; laneValue: string | null; }; type KanbanSubgroupCollapseControl = { isLaneCollapsed?: undefined; onLaneCollapsedChange?: undefined; } | { isLaneCollapsed: (group: KanbanGroup, count: number) => boolean; onLaneCollapsedChange: (group: KanbanGroup, collapsed: boolean) => void; }; export type KanbanSubgroupBoardProps = { scrollRef?: Ref | undefined; matrix: KanbanBoardMatrix; renderColumnHeader: (context: KanbanSubgroupColumnHeaderContext) => ReactNode; renderLaneIdentity: (context: KanbanSubgroupLaneIdentityContext) => ReactNode; renderCell: (context: KanbanSubgroupCellContext) => ReactNode; /** * What a lane's own row says about one column: its count by default. The * row is pinned, so this is the one line about a column that survives a * scroll down a lane hundreds of cards tall — a calculation belongs here * rather than at the end of a cell nobody reaches. */ renderLaneColumnSummary?: ((context: KanbanSubgroupLaneColumnSummaryContext) => ReactNode) | undefined; /** * The control at the end of a lane's cell for one column, such as adding a * card straight into that intersection. None by default. */ renderLaneColumnAction?: ((context: KanbanSubgroupLaneColumnActionContext) => ReactNode) | undefined; /** * The line above a band's columns. Defaults to `KanbanColumnBandHeader` * with the band's label and count. */ renderBandHeader?: ((context: KanbanSubgroupBandHeaderContext) => ReactNode) | undefined; /** * A lane's slot while its band is collapsed. Defaults to the band's name * set vertically over the count; a host that accepts drops into a collapsed * band renders its target here. Fill the slot's height (`h-full`) and * compose `KanbanCollapsedBandCaption` inside, so the name still stays * under the header halfway down a tall lane. */ renderCollapsedBandCell?: ((context: KanbanSubgroupCollapsedBandCellContext) => ReactNode) | undefined; /** Accessible name for a band's collapse toggle. */ formatBandToggleLabel?: ((band: KanbanColumnBand, collapsed: boolean) => string) | undefined; /** * Controlled band collapse. Omit both and the board keeps the collapsed * bands itself; a persisted view supplies both. */ isBandCollapsed?: ((band: KanbanColumnBand) => boolean) | undefined; onBandCollapsedChange?: ((band: KanbanColumnBand, collapsed: boolean) => void) | undefined; formatCount?: ((count: number) => ReactNode) | undefined; footer?: ReactNode; className?: string | undefined; } & KanbanSubgroupCollapseControl; /** * Reusable swimlane layout over the canonical two-axis Kanban matrix. * * Every lane leads with a row of its own, pinned on both axes: its name at the * visible inline edge, and beside each column what that column holds in this * lane, so a reader deep inside a lane still knows which lane it is and what * is around them. * * Columns that carry band metadata render under a one-line band caption and * can be collapsed as a run: the band folds into one narrow slot in every * row, whose cells stay reachable (a host renders its drop target in them), * and peeks open while a dragged card rests on it, so a drag can still land * on a specific column inside; a plain hover never opens it. Every row is laid out span by span with the same * widths, which is what keeps captions, headers, counts, and cells aligned * in every state; the caption line never grows past its own height, so a * folded band costs no vertical space. */ export declare const KanbanSubgroupBoard: ({ scrollRef, matrix, renderColumnHeader, renderLaneIdentity, renderCell, renderLaneColumnSummary, renderLaneColumnAction, renderBandHeader, renderCollapsedBandCell, formatBandToggleLabel, formatCount, isLaneCollapsed, onLaneCollapsedChange, isBandCollapsed, onBandCollapsedChange, footer, className }: KanbanSubgroupBoardProps) => import("react").JSX.Element; //#endregion