import * as React from 'react'; import { summarizeFilterValues, translateOptionLabels } from './filter-chips'; import type { TableMetadata, ColumnDefinition, StageMeta, StageTransition } from './types'; export { summarizeFilterValues, translateOptionLabels }; /** * Resolves the board lanes for a kanban view. Prefers the model-level * `metadata.stages` (the kernel's `stages[]`); falls back to the `group_by` * column's `options` (the kernel projects the stage machine onto the status * display). Returns lanes sorted by `order` (then declared order). Empty when * neither source is present — the caller renders a "no stages" notice. */ export declare function deriveStages(metadata: TableMetadata): StageMeta[]; /** * Buckets records into a `stageKey → rows[]` map, one entry per declared stage * (in stage order), plus a trailing `__unassigned__` bucket for rows whose * stage value matches no declared lane (so nothing silently vanishes). Empty * lanes are kept so the board always shows every stage. */ export declare const UNASSIGNED_LANE = "__unassigned__"; export declare function groupByStage(records: any[], groupByKey: string, stages: StageMeta[]): Map; /** * Whether a card may move `from → to` given the declared transitions. No * transitions declared → unrestricted (the kernel still validates server-side). * A move to the same stage is always a no-op "allowed". `'*'` is a wildcard on * either side. */ export declare function isTransitionAllowed(transitions: StageTransition[] | undefined, from: string, to: string): boolean; /** * Returns a NEW grouping with `cardId` moved from `fromStage` to `toStage` * (appended to the destination lane). Pure — does not mutate the input map. * Used by the optimistic drop handler so the board updates before the PUT * resolves, and so the previous grouping can be restored on failure. */ export declare function applyOptimisticMove(grouped: Map, cardId: string | number, fromStage: string, toStage: string, groupByKey: string): Map; /** * Returns a NEW per-lane pagination map with the server totals adjusted for a * card moving `fromStage` → `toStage`: the source loses one, the destination * gains one. Lanes whose `total` is still unknown (`null`, not yet topped up) * are left alone. Pure — backs the optimistic drag so a partial lane's * `count/total` header stays truthful, and can be restored on PUT failure. */ export declare function applyLaneTotalsOnMove(pagination: Record, fromStage: string, toStage: string): Record; /** * Formats a lane header's count badge. Three cases: * - A lane filter/search is active → `shown/loaded` (the client-side narrowed * count over what this lane has loaded). * - Otherwise, when the stage's server total is known → `shown` alone once * everything is loaded (`shown >= total`), else `shown/total` (partial). * - Total still unknown → just `shown`. * Pure — exported for unit tests. */ export declare function formatLaneCount(shown: number, loaded: number, serverTotal: number | null, laneActive: boolean): string; /** * Picks the columns shown on a card: a `title` column (first searchable column, * else first text-ish column) and up to `maxFields` secondary columns. Excludes * the group_by column (it's the lane itself) and any column hidden from the * table view (visibility modal/list, or `hidden`). */ export declare function selectCardColumns(metadata: TableMetadata, maxFields?: number): { title: ColumnDefinition | null; fields: ColumnDefinition[]; }; /** * The value a card cell should render for a column — same resolution the * table's cells apply. An FK column (`_id`) prefers the backend-resolved * sibling object (`card.`, e.g. `{ name }` / `{ value, label }`) over the * raw UUID; a zero-UUID FK counts as unset (renders the em-dash). Pure — * exported for unit tests. */ export declare function cardCellValue(card: any, col: ColumnDefinition): unknown; /** * Whether a card passes a lane funnel. Picked select/facet `values` match by * equality (IN — the card's field value must be one of them); a free-text * `text` matches by case-insensitive substring. No field / no criteria → passes. * Pure — exported for unit tests. */ export declare function cardMatchesLaneFunnel(card: any, filter: { field?: string; values?: string[]; text?: string; } | undefined): boolean; /** * Count of applied criteria on a lane funnel: the number of picked select/facet * `values`, else 1 for a free-text `text`, else 0. Drives the funnel's count * badge. Pure — exported for unit tests. */ export declare function laneFunnelCount(value: { values?: string[]; text?: string; } | undefined): number; /** * Whether a card matches a free-text lane search: a case-insensitive substring * over the card's title + every visible field value (`String(v)`). Empty query * matches everything. Pure — exported for unit tests. */ export declare function cardMatchesLaneQuery(card: any, cols: ColumnDefinition[], query: string): boolean; export interface DynamicKanbanProps { /** Model key as registered on the backend (e.g. "issue"). */ model: string; /** * Data endpoint base — the org-scoped LIST endpoint (e.g. * `/data//me`). The optimistic update PUTs to `/`. */ endpoint?: string; /** Bump to force a metadata + records refetch (same contract as DynamicTable). */ refreshTrigger?: any; /** * Refetch the board when the host's realtime client reports a data event * for this model (same contract as DynamicTable's `realtime`). Off by * default; `` flips the default. */ realtime?: boolean; /** Called when a card is clicked (outside its action menu). */ onCardClick?: (row: any) => void; /** * Host hook for `view`/`edit` card actions (STRING contract — same as * DynamicTable's `onAction`). When provided, `view`/`edit` route to the host * (e.g. its seeded record modal); when omitted they open the SDK's built-in * record dialog. `delete`/link/custom actions are always handled in-SDK. */ onAction?: (action: string, row: any) => void; /** * Size of the INITIAL board page (one request, grouped into lanes). Each * lane then tops up incrementally on scroll (see `lanePageSize`). Defaults * to 50 — enough to fill the visible lanes without loading the whole board. */ pageSize?: number; /** * Page size for a lane's incremental top-up fetch (scoped by * `f_=`). Defaults to 25. */ lanePageSize?: number; /** IANA timezone for datetime card fields (org config). */ timeZone?: string; /** ISO 4217 currency for money card fields (org config). */ currency?: string; /** * Static equality filters always applied to the board (never shown as a * removable chip). Same contract as DynamicTable's `defaultFilters`. */ defaultFilters?: Record; } export declare function DynamicKanban({ model, endpoint, refreshTrigger, realtime: realtimeProp, onCardClick, onAction, pageSize, lanePageSize, timeZone, currency, defaultFilters, }: DynamicKanbanProps): React.JSX.Element; //# sourceMappingURL=dynamic-kanban.d.ts.map