Skip to content

Kanban

interface KanbanContextMenuConfig {
/** Compose application-provided row context-menu items after Kanban actions. */
readonly includeHostItems?: boolean;
/** Hide built-ins globally or per invoked card/batch while preserving the rest. */
readonly hidden?: Partial<Record<KanbanContextMenuItemId, KanbanContextMenuItemVisibility<T>>>
}

interface ResolveKanbanCardRuleOptions {
readonly config: KanbanConfig<T> | ResolvedKanbanConfig<T>;
readonly projectedCard: KanbanProjectedCard<T>;
readonly column: KanbanColumnDefinition<T>;
readonly swimlane: KanbanSwimlaneDefinition;
readonly selected?: boolean;
readonly dragging?: boolean;
/** Internal validation can evaluate visual card rules separately from global callbacks. */
readonly includeGlobalPermissions?: boolean
}

HTMLRevoGridElementEventMap (Extended from global)

Section titled “HTMLRevoGridElementEventMap (Extended from global)”
interface HTMLRevoGridElementEventMap {
[BEFORE_KANBAN_CARD_MOVE_EVENT]: KanbanBeforeCardMoveDetail;
[KANBAN_CARD_MOVE_EVENT]: KanbanCardMoveDetail;
[KANBAN_SELECTION_CHANGE_EVENT]: KanbanSelectionChangeDetail;
[KANBAN_COLUMN_ORDER_CHANGE_EVENT]: KanbanColumnOrderChangeDetail;
[KANBAN_DROP_STATE_CHANGE_EVENT]: KanbanDropStateChangeDetail;
[KANBAN_DIAGNOSTICS_EVENT]: KanbanDiagnosticsDetail;
[KANBAN_CARD_CREATE_REQUEST_EVENT]: KanbanCardRequestDetail;
[KANBAN_CARD_OPEN_REQUEST_EVENT]: KanbanCardRequestDetail;
[KANBAN_CARD_EDIT_REQUEST_EVENT]: KanbanCardRequestDetail;
[KANBAN_CARD_DELETE_REQUEST_EVENT]: KanbanCardRequestDetail;
[BEFORE_KANBAN_CARD_CREATE_EVENT]: KanbanCardCreateDetail;
[KANBAN_CARD_CREATE_EVENT]: KanbanCardCreateDetail;
[BEFORE_KANBAN_CARD_UPDATE_EVENT]: KanbanCardUpdateDetail;
[KANBAN_CARD_UPDATE_EVENT]: KanbanCardUpdateDetail;
[BEFORE_KANBAN_CARD_DELETE_EVENT]: KanbanCardDeleteDetail;
[KANBAN_CARD_DELETE_EVENT]: KanbanCardDeleteDetail
}

AdditionalData (Extended from @revolist/revogrid)

Section titled “AdditionalData (Extended from @revolist/revogrid)”
interface AdditionalData {
/** @deprecated Prefer the direct `grid.kanban` property. */
kanban?: KanbanConfig | false
}

HTMLRevoGridElement (Extended from global)

Section titled “HTMLRevoGridElement (Extended from global)”
interface HTMLRevoGridElement {
kanban?: KanbanConfig | false
}

Enterprise Kanban presentation for a canonical RevoGrid row source.

  • Auto-installed EventManagerPlugin, HistoryPlugin: Installs shared edit and history services for atomic Kanban moves.
  • Auto-installed ContextMenuPlugin: Uses the shared Pro context-menu surface for card actions.
  • Auto-installed KanbanCardEditorDialogPlugin: Provides the packaged card editor by default while preserving the explicit false opt-out.
  • Auto-installed FilterPlugin, ColumnMovePlugin: Uses core filtering for cards and core column movement for workflow columns.
class KanbanPlugin {
getCards(): readonly T[];
getProjection(): KanbanProjection<T> | null;
getConfig(): ResolvedKanbanConfig<T> | null;
createCard(card: T, options: KanbanCreateOptions = {}): KanbanMutationResult<T>;
updateCard(cardId: KanbanCardId, patch: Partial<T>, options: KanbanUpdateOptions = {}): KanbanMutationResult<T>;
deleteCards(cardIds: readonly KanbanCardId[], options: KanbanDeleteOptions = {}): KanbanMutationResult<T>;
getSelectedCardIds(): readonly KanbanCardId[];
setSelectedCardIds(cardIds: readonly KanbanCardId[]): void;
getColumnOrder(): readonly KanbanColumnProp[];
setColumnOrder(columnProps: readonly KanbanColumnProp[]): void;
getCollapsedColumnProps(): readonly KanbanColumnProp[];
setColumnCollapsed(columnProp: KanbanColumnProp, collapsed: boolean): void;
getSwimlaneColumnCollapsed(): boolean;
setSwimlaneColumnCollapsed(collapsed: boolean): void;
getDiagnostics(): readonly KanbanDiagnostic<T>[];
refresh(): void;
moveCards(
cardIds: readonly KanbanCardId[],
target: KanbanMoveTarget,
options: KanbanMoveOptions = {},
): boolean;
requestCreateCard(detail: KanbanCardRequestDetail<T> = {}): void;
requestOpenCard(cardId: KanbanCardId): void;
requestEditCard(cardId: KanbanCardId): void;
requestDeleteCards(cardIds: readonly KanbanCardId[]): void;
}

BEFORE_KANBAN_CARD_MOVE_EVENT: string;

KANBAN_CARD_MOVE_EVENT: string;

KANBAN_SELECTION_CHANGE_EVENT: string;

KANBAN_COLUMN_ORDER_CHANGE_EVENT: string;

KANBAN_DROP_STATE_CHANGE_EVENT: string;

KANBAN_DIAGNOSTICS_EVENT: string;

KANBAN_CARD_CREATE_REQUEST_EVENT: string;

KANBAN_CARD_OPEN_REQUEST_EVENT: string;

KANBAN_CARD_EDIT_REQUEST_EVENT: string;

KANBAN_CARD_DELETE_REQUEST_EVENT: string;

BEFORE_KANBAN_CARD_CREATE_EVENT: string;

KANBAN_CARD_CREATE_EVENT: string;

BEFORE_KANBAN_CARD_UPDATE_EVENT: string;

KANBAN_CARD_UPDATE_EVENT: string;

BEFORE_KANBAN_CARD_DELETE_EVENT: string;

KANBAN_CARD_DELETE_EVENT: string;

export function resolveKanbanLabels(labels?: Partial<KanbanLabels>): KanbanLabels;

DEFAULT_KANBAN_LABELS: {
unmappedColumn: string;
implicitSwimlane: string;
emptyColumn: string;
dropCardHere: string;
progress: string;
schedule: string;
assignees: string;
cardCount: (visible: number, total: number) => string;
wipLimit: (count: number, limit: number) => string;
selectedCards: (count: number) => string;
pickedUpCards: (count: number) => string;
moveTarget: (column: string, swimlane: string, position: number) => string;
moveCompleted: (count: number, column: string, swimlane: string) => string;
moveCancelled: string;
currentPosition: string;
noDropTarget: string;
moveBlocked: (reason: string) => string;
noCardsSelected: string;
boardReadOnly: string;
invalidCardIdentity: string;
cardCannotMove: string;
transitionNotAllowed: string;
dropRejected: string;
wipExceeded: (limit: number, excess: number) => string;
moveTargetMissing: string;
selectedCardsMissing: string;
invalidMove: string;
projectionFailed: string;
stackLabel: (column: string, swimlane: string) => string;
readonlyCard: string;
invalidCard: string;
openCard: string;
editCard: string;
moveCard: string;
moveCards: (count: number) => string;
moveToColumn: string;
moveToSwimlane: string;
addCardHere: string;
deleteCard: string;
deleteCards: (count: number) => string;
cardContextMenu: string;
dragHandle: string;
collapseColumn: string;
expandColumn: string;
collapseSwimlane: string;
expandSwimlane: string;
collapseSwimlaneColumn: string;
expandSwimlaneColumn: string;
};

export function resolveKanbanHistoryConfig(history?: HistoryConfig): HistoryConfig;

export function isKanbanHistoryConfig(history?: HistoryConfig): boolean;

KANBAN_HISTORY_RECORD_EVENT: string;

class KanbanHistoryTool {
isHistoryRecord(detail: EventManagerEvent): boolean;
emitPatch(previousCards: readonly T[], nextCards: readonly T[]): boolean;
replayPatch(detail: EventManagerEvent): boolean;
}

interface KanbanLabels {
readonly unmappedColumn: string;
readonly implicitSwimlane: string;
readonly emptyColumn: string;
readonly dropCardHere: string;
readonly progress: string;
readonly schedule: string;
readonly assignees: string;
readonly cardCount: (visible: number, total: number) => string;
readonly wipLimit: (count: number, limit: number) => string;
readonly selectedCards: (count: number) => string;
readonly pickedUpCards: (count: number) => string;
readonly moveTarget: (column: string, swimlane: string, position: number) => string;
readonly moveCompleted: (count: number, column: string, swimlane: string) => string;
readonly moveCancelled: string;
readonly currentPosition: string;
readonly noDropTarget: string;
readonly moveBlocked: (reason: string) => string;
readonly noCardsSelected: string;
readonly boardReadOnly: string;
readonly invalidCardIdentity: string;
readonly cardCannotMove: string;
readonly transitionNotAllowed: string;
readonly dropRejected: string;
readonly wipExceeded: (limit: number, excess: number) => string;
readonly moveTargetMissing: string;
readonly selectedCardsMissing: string;
readonly invalidMove: string;
readonly projectionFailed: string;
readonly stackLabel: (column: string, swimlane: string) => string;
readonly readonlyCard: string;
readonly invalidCard: string;
readonly openCard: string;
readonly editCard: string;
readonly moveCard: string;
readonly moveCards: (count: number) => string;
readonly moveToColumn: string;
readonly moveToSwimlane: string;
readonly addCardHere: string;
readonly deleteCard: string;
readonly deleteCards: (count: number) => string;
readonly cardContextMenu: string;
/** @deprecated Cards use the whole managed shell as their drag surface. */
readonly dragHandle: string;
readonly collapseColumn: string;
readonly expandColumn: string;
readonly collapseSwimlane: string;
readonly expandSwimlane: string;
readonly collapseSwimlaneColumn: string;
readonly expandSwimlaneColumn: string
}

interface KanbanCardRuleResult {
readonly className?: string;
readonly style?: Readonly<Record<string, string | number>>;
readonly badges?: readonly KanbanBadge[];
readonly draggable?: boolean;
readonly selectable?: boolean;
readonly editable?: boolean
}

interface KanbanCardRule {
readonly id: string;
readonly when: (context: KanbanCardRenderContext<T>) => boolean;
readonly result: KanbanCardRuleResult
}

interface KanbanDropRuleContext {
readonly cards: readonly T[];
readonly sourceColumnProps: readonly KanbanColumnProp[];
readonly targetColumn: KanbanColumnDefinition<T>;
readonly targetSwimlane: KanbanSwimlaneDefinition
}

interface KanbanRules {
readonly canDrag?: (card: T) => boolean | string;
readonly canSelect?: (card: T) => boolean;
readonly canEdit?: (card: T) => boolean;
readonly canDrop?: (context: KanbanDropRuleContext<T>) => boolean | string
}

interface KanbanCardConfig {
readonly titleField?: ColumnProp;
readonly descriptionField?: ColumnProp;
readonly title?: (card: T) => string;
readonly description?: (card: T) => string | undefined;
readonly progressField?: ColumnProp;
readonly progress?: (card: T) => number | null | undefined;
readonly startDateField?: ColumnProp;
readonly endDateField?: ColumnProp;
readonly dateRange?: (card: T) => { readonly start: unknown; readonly end: unknown } | null | undefined;
readonly dateTimeZone?: string;
readonly assigneeField?: ColumnProp;
readonly assigneeAvatarField?: ColumnProp;
readonly assignees?: (card: T) => readonly KanbanCardAssignee[];
readonly priorityField?: ColumnProp;
readonly priority?: (card: T) => string | null | undefined;
readonly tagsField?: ColumnProp;
readonly tags?: (card: T) => readonly string[] | null | undefined;
readonly dueDateField?: ColumnProp;
readonly dueDate?: (card: T) => unknown;
readonly colorField?: ColumnProp;
readonly color?: (card: T) => string | null | undefined
}

interface KanbanFilterConfig {
readonly query?: string;
readonly fields?: readonly ColumnProp[];
readonly predicate?: (card: T) => boolean
}

interface KanbanSelectionConfig {
readonly mode?: 'single' | 'multiple';
readonly selectedIds?: readonly (string | number)[]
}

interface KanbanSwimlaneColumnConfig {
readonly title?: string;
readonly width?: number;
readonly collapsedWidth?: number;
readonly collapsible?: boolean;
readonly collapsed?: boolean
}

Placement of explicit swimlane identity and collapse controls.

/** Placement of explicit swimlane identity and collapse controls. */
export type KanbanSwimlaneLayout = 'column' | 'top';

export type KanbanContextMenuItemId =
/** @deprecated Open is no longer rendered separately from Edit. */
| 'open'
| 'edit'
| 'move'
| 'create'
| 'delete';

interface KanbanContextMenuItemContext {
/** Primary card whose shell opened the menu. */
readonly card: T;
/** Full invoked selection, or only the primary card when it was not selected. */
readonly cardIds: readonly KanbanCardId[];
readonly column: KanbanColumnDefinition<T>;
readonly swimlane: KanbanSwimlaneDefinition
}

export type KanbanContextMenuItemVisibility<T extends DataType = DataType> =
| boolean
| ((context: KanbanContextMenuItemContext<T>) => boolean);

interface KanbanConfig {
readonly columns?: readonly KanbanColumnDefinition<T>[];
readonly idField?: ColumnProp;
readonly columnField?: ColumnProp;
readonly orderField?: ColumnProp;
readonly swimlaneField?: ColumnProp;
readonly swimlanes?: readonly KanbanSwimlaneDefinition[];
/** Render swimlane identity in a row-header column or above each lane. @default 'column' */
readonly swimlaneLayout?: KanbanSwimlaneLayout;
/** Swimlane row-header presentation. Set to `false` to hide it. */
readonly swimlaneColumn?: KanbanSwimlaneColumnConfig | false;
/** Built-in card context menu. Enabled by default. */
readonly contextMenu?: KanbanContextMenuConfig<T> | false;
readonly readOnly?: boolean;
readonly wipBehavior?: 'warn' | 'block';
readonly rules?: KanbanRules<T>;
readonly cardRules?: readonly KanbanCardRule<T>[];
readonly selection?: KanbanSelectionConfig;
readonly card?: KanbanCardConfig<T>;
readonly customization?: KanbanCustomization<T>;
readonly filter?: KanbanFilterConfig<T>;
readonly labels?: Partial<KanbanLabels>;
readonly locale?: string;
/** Uniform projected row height reserved for each card. */
readonly cardRowHeight?: number;
/** @deprecated Use `cardRowHeight`. Retained as a compatibility alias. */
readonly laneHeight?: number;
readonly collapsedLaneHeight?: number;
readonly cardGap?: number;
readonly unmappedColumn?: boolean
}

ResolvedKanbanConfig (Extended from index.ts)

Section titled “ResolvedKanbanConfig (Extended from index.ts)”
interface ResolvedKanbanConfig {
readonly columns: readonly KanbanColumnDefinition<T>[];
readonly idField: ColumnProp;
readonly columnField: ColumnProp;
readonly orderField: ColumnProp;
readonly wipBehavior: 'warn' | 'block';
readonly selection: Required<KanbanSelectionConfig>;
readonly card: Required<Pick<KanbanCardConfig<T>, 'titleField'>> & KanbanCardConfig<T>;
readonly locale: string;
readonly cardRowHeight: number;
readonly laneHeight: number;
readonly collapsedLaneHeight: number;
readonly swimlaneLayout: KanbanSwimlaneLayout;
readonly swimlaneColumn: Required<KanbanSwimlaneColumnConfig> & { readonly enabled: boolean };
readonly contextMenu: false | Required<Pick<KanbanContextMenuConfig<T>, 'includeHostItems'>> & KanbanContextMenuConfig<T>;
readonly cardGap: number;
readonly unmappedColumn: boolean
}

interface KanbanCardMoveDetail {
readonly cardIds: readonly KanbanCardId[];
readonly cards: readonly T[];
/** Every canonical card changed by the move, including rank rebalances. */
readonly changedCards: readonly T[];
readonly previousCards: readonly T[];
readonly previousLocations: readonly KanbanCardLocation[];
readonly currentLocations: readonly KanbanCardLocation[];
readonly target: KanbanMoveTarget;
readonly reason: 'pointer' | 'keyboard' | 'api' | 'history';
readonly rebalancedCardIds: readonly KanbanCardId[]
}

KanbanBeforeCardMoveDetail (Extended from index.ts)

Section titled “KanbanBeforeCardMoveDetail (Extended from index.ts)”
interface KanbanBeforeCardMoveDetail {
readonly proposedCards: readonly T[]
}

interface KanbanSelectionChangeDetail {
readonly cardIds: readonly KanbanCardId[];
readonly cards: readonly T[];
readonly mode: 'replace' | 'toggle' | 'range' | 'clear' | 'api'
}

interface KanbanColumnOrderChangeDetail {
readonly columnProps: readonly KanbanColumnProp[];
readonly reason: 'drag' | 'api'
}

interface KanbanDropStateChangeDetail {
readonly cardIds: readonly KanbanCardId[];
readonly target?: KanbanMoveTarget;
readonly valid: boolean;
/** Distinguishes actionable, blocked, and order-preserving pointer targets. */
readonly state?: 'valid' | 'invalid' | 'noop';
readonly reason?: string
}

interface KanbanDiagnosticsDetail {
readonly diagnostics: readonly KanbanDiagnostic<T>[]
}

interface KanbanCardRequestDetail {
readonly cardId?: KanbanCardId;
readonly card?: T;
readonly cardIds?: readonly KanbanCardId[];
readonly cards?: readonly T[];
readonly columnProp?: KanbanColumnProp;
readonly swimlaneId?: KanbanSwimlaneId
}

export type KanbanMutationReason = 'api' | 'editor' | 'history';

interface KanbanCardCreateDetail {
readonly card: T;
readonly cardId: KanbanCardId;
readonly sourceIndex: number;
readonly reason: KanbanMutationReason
}

interface KanbanCardUpdateDetail {
readonly card: T;
readonly previousCard: T;
readonly cardId: KanbanCardId;
readonly sourceIndex: number;
readonly reason: KanbanMutationReason
}

interface KanbanCardDeleteDetail {
readonly cards: readonly T[];
readonly cardIds: readonly KanbanCardId[];
readonly sourceIndexes: readonly number[];
readonly reason: KanbanMutationReason
}

export type KanbanMutationResult<T extends DataType = DataType> =
| { readonly ok: true; readonly cards: readonly T[]; readonly cardIds: readonly KanbanCardId[] }
| { readonly ok: false; readonly reason: string; readonly code: 'inactive' | 'readonly' | 'invalid' | 'duplicate' | 'missing' | 'rule' | 'cancelled' };

export type KanbanCardId = string | number;

export type KanbanColumnProp = ColumnProp;

export type KanbanSwimlaneId = string | number;

interface KanbanCardLocation {
readonly columnProp: KanbanColumnProp;
readonly swimlaneId: KanbanSwimlaneId;
readonly index: number;
readonly rank: number
}

interface KanbanColumnDefinition {
readonly prop: KanbanColumnProp;
readonly name?: string;
readonly size?: number;
readonly minSize?: number;
readonly maxSize?: number;
readonly columnTemplate?: KanbanColumnTemplate<T>;
readonly columnProperties?: KanbanColumnProperties<T>;
readonly wipLimit?: number;
readonly collapsed?: boolean;
readonly collapsible?: boolean;
readonly allowedFrom?: readonly KanbanColumnProp[];
readonly metadata?: Readonly<Record<string, unknown>>;
readonly cardFilter?: (card: T) => boolean
}

interface KanbanColumnHeaderRenderContext {
readonly column: KanbanColumnDefinition<T>;
readonly visibleCount: number;
readonly totalCount: number;
readonly overWipLimit: boolean;
readonly toggleCollapsed: () => void
}

KanbanColumnTemplateProp (Extended from index.ts)

Section titled “KanbanColumnTemplateProp (Extended from index.ts)”
interface KanbanColumnTemplateProp {
readonly kanban: KanbanColumnHeaderRenderContext<T>
}

export type KanbanColumnTemplate<T extends DataType = DataType> = (
createElement: HyperFunc<VNode>,
props: KanbanColumnTemplateProp<T>,
additionalData?: any,
) => any;

export type KanbanColumnProperties<T extends DataType = DataType> = (
props: KanbanColumnTemplateProp<T>,
) => CellProps | void | undefined;

interface KanbanSwimlaneDefinition {
readonly id: KanbanSwimlaneId;
readonly title: string;
readonly height?: number;
readonly collapsed?: boolean;
readonly collapsible?: boolean;
readonly wipLimits?: Readonly<Record<string, number>>;
readonly className?: string;
readonly style?: Readonly<Record<string, string | number>>;
readonly metadata?: Readonly<Record<string, unknown>>
}

export type KanbanDiagnosticCode =
| 'duplicate-column-prop'
| 'missing-card-id'
| 'duplicate-card-id'
| 'invalid-rank'
| 'unknown-column'
| 'unknown-swimlane';

interface KanbanDiagnostic {
readonly code: KanbanDiagnosticCode;
readonly message: string;
readonly card?: T;
readonly cardIndex?: number;
readonly value?: unknown;
readonly blocking: boolean
}

interface KanbanProjectedCard {
readonly id: KanbanCardId;
readonly card: T;
readonly sourceIndex: number;
readonly location: KanbanCardLocation;
readonly mutable: boolean
}

interface KanbanGridRow {
readonly __kanbanRow: true;
readonly __kanbanLaneId: KanbanSwimlaneId;
readonly __kanbanLaneTitle: string;
readonly __kanbanLaneCollapsed: boolean;
/** Dedicated lane identity row rendered across the workflow viewport. */
readonly __kanbanLaneHeaderRow: boolean;
readonly __kanbanLaneRowIndex: number;
readonly __kanbanLaneRowCount: number;
readonly __kanbanDropRow: boolean;
readonly __kanbanCardsByColumn: Readonly<Record<string, readonly KanbanProjectedCard<T>[]>>
}

interface KanbanProjection {
readonly cards: readonly KanbanProjectedCard<T>[];
readonly rows: readonly KanbanGridRow<T>[];
readonly columns: readonly KanbanColumnDefinition<T>[];
readonly swimlanes: readonly KanbanSwimlaneDefinition[];
readonly diagnostics: readonly KanbanDiagnostic<T>[];
readonly visibleCardIds: ReadonlySet<KanbanCardId>;
readonly cardById: ReadonlyMap<KanbanCardId, KanbanProjectedCard<T>>;
readonly totalCounts: ReadonlyMap<string, number>;
readonly visibleCounts: ReadonlyMap<string, number>
}

interface KanbanMoveTarget {
readonly columnProp: KanbanColumnProp;
readonly swimlaneId?: KanbanSwimlaneId;
/** Full-bucket insertion index. Omit to append. */
readonly index?: number;
/** Visible card before which the batch should be inserted. */
readonly beforeCardId?: KanbanCardId
}

interface KanbanMoveOptions {
readonly reason?: 'pointer' | 'keyboard' | 'api' | 'history';
readonly skipHistory?: boolean
}

interface KanbanCreateOptions {
readonly columnProp?: KanbanColumnProp;
readonly swimlaneId?: KanbanSwimlaneId;
readonly sourceIndex?: number;
readonly reason?: 'api' | 'editor' | 'history';
readonly skipHistory?: boolean
}

interface KanbanUpdateOptions {
readonly reason?: 'api' | 'editor' | 'history';
readonly skipHistory?: boolean
}

KanbanDeleteOptions (Extended from index.ts)

Section titled “KanbanDeleteOptions (Extended from index.ts)”
interface KanbanDeleteOptions {
}

export type KanbanField = ColumnProp;

export type KanbanTemplateResult = VNode | string | number | null | undefined;

export type KanbanTemplateH = (
tag: string,
props?: Record<string, unknown>,
children?: unknown,
) => VNode;

interface KanbanBadge {
readonly label: string;
readonly className?: string;
readonly title?: string
}

interface KanbanCardAssignee {
readonly id?: string | number;
readonly label: string;
readonly avatar?: unknown
}

interface KanbanProgressRenderOptions {
readonly value: number;
readonly label: string;
readonly className?: string;
readonly showValue?: boolean
}

interface KanbanAssigneesRenderOptions {
readonly assignees: readonly KanbanCardAssignee[];
readonly label: string;
readonly className?: string;
readonly maxVisible?: number;
readonly avatarSize?: number
}

interface KanbanDateRangeRenderOptions {
readonly start: unknown;
readonly end: unknown;
readonly label: string;
readonly locale?: string;
readonly timeZone?: string;
readonly className?: string
}

interface KanbanCardRenderContext {
readonly projectedCard: KanbanProjectedCard<T>;
readonly card: T;
readonly column: KanbanColumnDefinition<T>;
readonly swimlane: KanbanSwimlaneDefinition;
readonly selected: boolean;
readonly dragging: boolean;
readonly readonly: boolean;
readonly badges: readonly KanbanBadge[]
}

interface KanbanSwimlaneHeaderRenderContext {
readonly swimlane: KanbanSwimlaneDefinition;
readonly visibleCount: number;
readonly totalCount: number;
readonly swimlaneColumnCollapsed: boolean
}

interface KanbanSwimlaneColumnHeaderRenderContext {
readonly collapsed: boolean
}

interface KanbanCustomization {
readonly cardContent?: (h: KanbanTemplateH, context: KanbanCardRenderContext<T>) => KanbanTemplateResult;
readonly cardProps?: (context: KanbanCardRenderContext<T>) => Record<string, unknown> | undefined;
readonly dragPreview?: (h: KanbanTemplateH, context: KanbanCardRenderContext<T>) => KanbanTemplateResult;
readonly swimlaneHeader?: (h: KanbanTemplateH, context: KanbanSwimlaneHeaderRenderContext) => KanbanTemplateResult;
readonly swimlaneColumnHeader?: (h: KanbanTemplateH, context: KanbanSwimlaneColumnHeaderRenderContext) => KanbanTemplateResult;
readonly emptyState?: (h: KanbanTemplateH, context: { column: KanbanColumnDefinition<T>; swimlane: KanbanSwimlaneDefinition }) => KanbanTemplateResult
}

export function cardMatchesKanbanFilter<T extends DataType>(
card: T,
config: Pick<ResolvedKanbanConfig<T>, 'card' | 'filter' | 'locale'>,
): boolean;

export function filterKanbanCards<T extends DataType>(
cards: readonly T[],
config: Pick<ResolvedKanbanConfig<T>, 'card' | 'filter' | 'locale'>,
externalPredicate?: (card: T, sourceIndex: number) => boolean,
): readonly T[];

export function withKanbanQuery<T extends DataType>(
filter: KanbanFilterConfig<T> | undefined,
query: string,
): KanbanFilterConfig<T>;

Keeps numeric and string identifiers distinct in maps and serialized row fields.

export function kanbanIdKey(id: KanbanIdentity): string;

export function kanbanBucketKey(columnProp: KanbanColumnProp, swimlaneId: KanbanSwimlaneId): string;

export function resolveKanbanColumnName<T extends DataType>(column: KanbanColumnDefinition<T>): string;

export function readKanbanField<T extends DataType>(card: T, field: ColumnProp): unknown;

export function writeKanbanFields<T extends DataType>(
card: T,
patch: ReadonlyMap<ColumnProp, unknown>,
): T;

export function isKanbanId(value: unknown): value is KanbanIdentity;

export type KanbanIdentity = KanbanCardId | KanbanColumnProp | KanbanSwimlaneId;

Returns true when a proposed drop preserves the complete destination order.

export function isKanbanMoveNoop<T extends DataType>(
options: IsKanbanMoveNoopOptions<T>,
): boolean;

Produces one immutable, all-or-nothing canonical card move.

export function moveKanbanCards<T extends DataType>(
options: MoveKanbanCardsOptions<T>,
): KanbanMoveMutationResult<T>;

export function getKanbanMoveBucketKey(target: KanbanMoveTarget): string;

interface MoveKanbanCardsOptions {
readonly cards: readonly T[];
readonly projection: KanbanProjection<T>;
readonly config: KanbanConfig<T> | ResolvedKanbanConfig<T>;
readonly cardIds: readonly KanbanCardId[];
readonly target: KanbanMoveTarget
}

interface KanbanMoveMutationSuccess {
readonly ok: true;
readonly cards: readonly T[];
readonly movedCardIds: readonly KanbanCardId[];
readonly movedCards: readonly T[];
readonly previousCards: readonly T[];
readonly previousLocations: readonly KanbanCardLocation[];
readonly currentLocations: readonly KanbanCardLocation[];
readonly changedCards: readonly T[];
readonly rebalancedCardIds: readonly KanbanCardId[];
readonly validation: KanbanDropValidation;
readonly projection: KanbanProjection<T>
}

interface KanbanMoveMutationFailure {
readonly ok: false;
readonly cards: readonly T[];
readonly reason: string;
readonly validation?: KanbanDropValidation
}

export type KanbanMoveMutationResult<T extends DataType = DataType> =
| KanbanMoveMutationSuccess<T>
| KanbanMoveMutationFailure<T>;

export type IsKanbanMoveNoopOptions<T extends DataType = DataType> = Pick<
MoveKanbanCardsOptions<T>,
'projection' | 'cardIds' | 'target'
>;

export function resolveKanbanConfig<T extends DataType>(config: KanbanConfig<T>): ResolvedKanbanConfig<T>;

export function normalizeKanbanBoard<T extends DataType>(
cards: readonly T[],
config: KanbanConfig<T>,
): NormalizedKanbanBoard<T>;

Orders known workflow columns by runtime preference and appends omitted columns stably.

export function orderKanbanColumns<T extends DataType>(
columns: readonly KanbanColumnDefinition<T>[],
columnOrder: readonly KanbanColumnProp[],
): readonly KanbanColumnDefinition<T>[];

KANBAN_IMPLICIT_SWIMLANE_ID: string;

KANBAN_UNMAPPED_COLUMN_PROP: string;

interface NormalizedKanbanBoard {
readonly config: ResolvedKanbanConfig<T>;
readonly columns: readonly KanbanColumnDefinition<T>[];
readonly swimlanes: readonly KanbanSwimlaneDefinition[];
readonly diagnostics: readonly KanbanDiagnostic<T>[]
}

export function createKanbanProjection<T extends DataType>(
cards: readonly T[],
config: KanbanConfig<T> | ResolvedKanbanConfig<T>,
options: CreateKanbanProjectionOptions<T> = {},
): KanbanProjection<T>;

export function getKanbanBucketCards<T extends DataType>(
projection: KanbanProjection<T>,
columnProp: KanbanColumnProp,
swimlaneId: string | number,
visibleOnly = false,
): readonly KanbanProjectedCard<T>[];

export function getKanbanBoardOrder<T extends DataType>(projection: KanbanProjection<T>): readonly KanbanCardId[];

interface CreateKanbanProjectionOptions {
/** Physical canonical indexes that passed an external filter. */
readonly externallyVisibleSourceIndexes?: ReadonlySet<number>;
/** @deprecated Prefer source indexes so invalid and duplicate card ids remain distinguishable. */
readonly externallyVisibleCardIds?: ReadonlySet<KanbanCardId>;
readonly isExternallyVisible?: (card: T, sourceIndex: number) => boolean
}

Allocates ordered ranks in a gap, or returns undefined when the bucket must be rebalanced.

export function allocateFractionalRanks(options: AllocateKanbanRanksOptions): readonly number[] | undefined;

export function createRebalancedKanbanRanks<T extends DataType>(
cards: readonly Pick<KanbanProjectedCard<T>, 'id'>[],
spacing = KANBAN_RANK_SPACING,
): ReadonlyMap<KanbanCardId, number>;

KANBAN_RANK_SPACING: 1024;

interface AllocateKanbanRanksOptions {
readonly beforeRank?: number;
readonly afterRank?: number;
readonly count: number;
readonly spacing?: number;
readonly minimumGap?: number
}

export function resolveKanbanCardRuleState<T extends DataType>(
options: ResolveKanbanCardRuleOptions<T>,
): ResolvedKanbanCardRuleState;

export function validateKanbanDrop<T extends DataType>(
options: ValidateKanbanDropOptions<T>,
): KanbanDropValidation;

interface ResolvedKanbanCardRuleState {
readonly classNames: readonly string[];
readonly style: Readonly<Record<string, string | number>>;
readonly badges: readonly KanbanBadge[];
readonly draggable: boolean;
readonly selectable: boolean;
readonly editable: boolean
}

interface ValidateKanbanDropOptions {
readonly config: KanbanConfig<T> | ResolvedKanbanConfig<T>;
readonly cards: readonly KanbanProjectedCard<T>[];
readonly targetColumn: KanbanColumnDefinition<T>;
readonly targetSwimlane: KanbanSwimlaneDefinition;
/** Canonical count in the target column across every swimlane. */
readonly targetColumnTotalCount?: number;
/** Canonical count in the target column/swimlane bucket. */
readonly targetTotalCount: number
}

interface KanbanDropValidation {
readonly valid: boolean;
readonly reason?: string;
readonly warning?: string;
readonly projectedCount: number;
readonly wipLimit?: number
}

export function uniqueKanbanCardIds(ids: Iterable<KanbanCardId>): KanbanCardId[];

export function pruneKanbanSelection(
selectedIds: readonly KanbanCardId[],
allowedIds: ReadonlySet<KanbanCardId> | readonly KanbanCardId[],
): readonly KanbanCardId[];

export function updateKanbanSelection(options: UpdateKanbanSelectionOptions): readonly KanbanCardId[];

export type KanbanSelectionMode = 'replace' | 'toggle' | 'range' | 'clear' | 'api';

interface UpdateKanbanSelectionOptions {
readonly currentIds: readonly KanbanCardId[];
readonly cardId?: KanbanCardId;
readonly mode: KanbanSelectionMode;
readonly orderedCardIds: readonly KanbanCardId[];
readonly anchorId?: KanbanCardId;
readonly selectionMode?: 'single' | 'multiple'
}

Renders a compact locale-aware schedule shared by default and custom cards.

export function renderKanbanDateRange(
h: KanbanTemplateH,
options: KanbanDateRangeRenderOptions,
): KanbanTemplateResult;

Renders compact, theme-aware progress content for managed or custom cards.

export function renderKanbanProgress(
h: KanbanTemplateH,
options: KanbanProgressRenderOptions,
): KanbanTemplateResult;

Renders assignees with the shared Pro avatar component.

export function renderKanbanAssignees(
h: KanbanTemplateH,
options: KanbanAssigneesRenderOptions,
): KanbanTemplateResult;

export function createKanbanColumns<T extends DataType>(
projection: KanbanProjection<T>,
): KanbanGridColumn<T>[];

export function createKanbanColumnTypes<T extends DataType>(
options: KanbanColumnTypeOptions<T>,
): Record<string, ColumnType<DataType>>;

export function createKanbanRowHeaders<T extends DataType>(
options: KanbanColumnTypeOptions<T>,
): RowHeaders;

KANBAN_COLUMN_TYPE: string;

interface KanbanGridColumn {
}

export function installKanbanDependencies(
grid: HTMLRevoGridElement,
providers: PluginProviders,
): KanbanInstalledDependencies;

interface KanbanInstalledDependencies {
activate(): void;
deactivate(): void;
destroy(): void
}

class KanbanGridSync {
initialize(): void;
applyProjection(
projection: KanbanProjection<T>,
options: { readonly applyColumns?: boolean } = {},
): void;
captureSource(source: readonly T[]): void;
captureColumns(columns: readonly (ColumnGrouping | ColumnRegular)[]): void;
restore(source?: readonly T[]): void;
isApplyingSource(): boolean;
isApplyingColumns(): boolean;
refresh(): void;
}

export function renderKanbanCard<T extends DataType>(
h: KanbanTemplateH,
projectedCard: KanbanProjectedCard<T>,
column: KanbanColumnDefinition<T>,
swimlane: KanbanSwimlaneDefinition,
options: KanbanColumnTypeOptions<T>,
index: number,
);

interface KanbanRendererActions {
readonly getSelectedCardIds: () => readonly KanbanCardId[];
readonly getDraggingCardIds?: () => readonly KanbanCardId[];
readonly onCardSelect: (event: MouseEvent | KeyboardEvent, cardId: KanbanCardId) => void;
readonly onCardPointerDown: (event: PointerEvent, cardId: KanbanCardId, element: HTMLElement) => void;
readonly onCardKeyDown: (event: KeyboardEvent, cardId: KanbanCardId) => void;
readonly onCardEditRequest: (cardId: KanbanCardId) => void;
readonly onColumnToggle?: (columnProp: KanbanColumnProp) => void;
readonly onSwimlaneToggle?: (swimlaneId: string | number) => void;
readonly isSwimlaneColumnCollapsed?: () => boolean;
readonly onSwimlaneColumnToggle?: () => void;
readonly onMoveRequest?: (cardIds: readonly KanbanCardId[], target: KanbanMoveTarget) => void
}

interface KanbanColumnTypeOptions {
readonly getProjection: () => KanbanProjection<T> | null;
readonly getConfig: () => KanbanConfig<T> | ResolvedKanbanConfig<T>;
readonly getLabels: () => KanbanLabels;
readonly actions: KanbanRendererActions<T>
}

interface KanbanContextMenuControllerOptions {
readonly grid: HTMLRevoGridElement;
readonly getProjection: () => KanbanProjection<T> | null;
readonly getConfig: () => ResolvedKanbanConfig<T> | null;
readonly getLabels: () => KanbanLabels;
readonly getSelectedCardIds: () => readonly KanbanCardId[];
readonly canEditCard: (cardId: KanbanCardId) => boolean;
readonly validateMove: (
cardIds: readonly KanbanCardId[],
target: KanbanMoveTarget,
) => true | string | { readonly valid: true; readonly warning: string };
readonly moveCards: (cardIds: readonly KanbanCardId[], target: KanbanMoveTarget) => void;
readonly requestEditCard: (cardId: KanbanCardId) => void;
readonly requestCreateCard: (detail: KanbanCardRequestDetail<T>) => void;
readonly requestDeleteCards: (cardIds: readonly KanbanCardId[]) => void
}

Composes card actions into the shared Pro context-menu surface.

class KanbanContextMenuController {
apply(): void;
remove(): void;
}

export function toDomCardId(value: KanbanCardId): string;

KanbanDomDropTarget (Extended from index.ts)

Section titled “KanbanDomDropTarget (Extended from index.ts)”
interface KanbanDomDropTarget {
readonly element: HTMLElement;
readonly anchorElement?: HTMLElement
}

export type KanbanDropVisualState = 'valid' | 'invalid' | 'noop';

Owns the small amount of DOM state required by pointer drag and drop.

class KanbanDomLayer {
hitTest(clientX: number, clientY: number): KanbanDomDropTarget | undefined;
createPreview(source: HTMLElement, count: number): void;
movePreview(clientX: number, clientY: number): void;
showIndicator(target: KanbanDomDropTarget, state: KanbanDropVisualState): void;
clearDropFeedback(): void;
autoScroll(clientX: number, clientY: number, margin = 48, speed = 18): boolean;
clear(): void;
focusCardHandle(cardId: KanbanCardId, fallbackTarget?: KanbanMoveTarget): void;
}

KanbanKeyboardPosition (Extended from index.ts)

Section titled “KanbanKeyboardPosition (Extended from index.ts)”
interface KanbanKeyboardPosition {
readonly columnName: string;
readonly swimlaneTitle: string
}

interface KanbanKeyboardControllerOptions {
readonly getSelectedCardIds: () => readonly KanbanCardId[];
readonly selectForDrag: (cardId: KanbanCardId) => void;
readonly getPositions: () => readonly KanbanKeyboardPosition[];
readonly announce: (message: string) => void;
readonly pickedUpLabel: (count: number) => string;
readonly targetLabel: (position: KanbanKeyboardPosition) => string;
readonly cancelledLabel: () => string;
readonly onStateChange?: () => void;
readonly onMove: (cardIds: readonly KanbanCardId[], target: KanbanMoveTarget, reason: 'keyboard') => void | Promise<void>
}

class KanbanKeyboardController {
keyDown(event: KeyboardEvent, cardId: KanbanCardId): boolean;
cancel(): void;
getActiveCardIds(): readonly KanbanCardId[];
}

class KanbanLiveRegion {
mount(): void;
announce(message: string): void;
destroy(): void;
}

interface KanbanPointerDropState {
readonly cardIds: readonly KanbanCardId[];
readonly target?: KanbanMoveTarget;
readonly valid: boolean;
readonly state: KanbanDropVisualState;
readonly reason?: string
}

interface KanbanPointerControllerOptions {
readonly getSelectedCardIds: () => readonly KanbanCardId[];
readonly selectForDrag: (cardId: KanbanCardId) => void;
readonly validateTarget?: (
cardIds: readonly KanbanCardId[],
target: KanbanMoveTarget,
) => true | string | { readonly valid: true; readonly warning: string };
readonly isNoopTarget?: (cardIds: readonly KanbanCardId[], target: KanbanMoveTarget) => boolean;
readonly getNoopReason?: () => string;
readonly getNoTargetReason?: () => string;
readonly onDropStateChange?: (state: KanbanPointerDropState) => void;
readonly announceValidation?: (message: string) => void;
readonly onMove: (cardIds: readonly KanbanCardId[], target: KanbanMoveTarget, reason: 'pointer') => void | Promise<void>
}

class KanbanPointerController {
pointerDown(event: PointerEvent, cardId: KanbanCardId, source: HTMLElement): void;
cancel(): void;
getDraggingCardIds(): readonly KanbanCardId[];
consumeSuppressedClick(cardId: KanbanCardId): boolean;
destroy(): void;
}

interface KanbanSelectionUpdate {
readonly cardIds: readonly KanbanCardId[];
readonly mode: KanbanSelectionMode
}

class KanbanSelectionController {
get(): readonly KanbanCardId[];
has(id: KanbanCardId): boolean;
set(ids: readonly KanbanCardId[], mode: KanbanSelectionMode = 'api'): void;
clear(mode: KanbanSelectionMode = 'clear'): void;
select(
id: KanbanCardId,
orderedIds: readonly KanbanCardId[],
modifiers: { readonly toggle?: boolean; readonly range?: boolean } = {},
): void;
prune(visibleIds: ReadonlySet<KanbanCardId>): void;
}

interface KanbanSwimlaneGroupRowRendererOptions {
readonly getProjection: () => KanbanProjection<T> | null;
readonly getConfig: () => ResolvedKanbanConfig<T>;
readonly getLabels: () => KanbanLabels;
readonly onSwimlaneToggle: (swimlaneId: KanbanSwimlaneId) => void
}

Renders projected lane identity rows across the full workflow viewport.

class KanbanSwimlaneGroupRowRenderer {
apply(detail: BeforeRowRenderEvent<KanbanGridRow<T>>): void;
}

export function renderKanbanToggleIcon(h: KanbanTemplateH);

export function getCoreFilteredKanbanCardIds<T extends DataType>(options: {
readonly cards: readonly T[];
readonly idField: ColumnProp;
readonly filterPlugin?: FilterPlugin;
readonly hostColumns: readonly (ColumnGrouping | ColumnRegular)[];
}): ReadonlySet<KanbanCardId> | undefined;

Preserves physical identity for missing and duplicate card ids during core filtering.

export function getCoreFilteredKanbanSourceIndexes<T extends DataType>(options: {
readonly cards: readonly T[];
readonly filterPlugin?: FilterPlugin;
readonly hostColumns: readonly (ColumnGrouping | ColumnRegular)[];
}): ReadonlySet<number> | undefined;