AI
Kanban logov1.0.0

Permissions & Move Validation

Nofinite Kanban provides robust validation hooks allowing teams to intercept drag-and-drop actions, enforce state machine transitions, and apply role-based permission checks before any state update commits.

When a validation hook returns false, the dragged card snaps smoothly back to its origin without DOM mutation or data corruption.

typescript
// Framework-Agnostic Core
import { createKanbanBoard, type CardMoveEvent } from '@nofinite/kanban';

// React Adapter
import { Kanban } from '@nofinite/kanban/react';

1. Framework-Agnostic Core Validation

Pass canMoveCard to createKanbanBoard() to validate card transitions:

typescript
import { createKanbanBoard, type CardMoveEvent } from '@nofinite/kanban';
import '@nofinite/nuicss/styles.css';

const board = createKanbanBoard(document.getElementById('board'), {
  columns: initialColumns,
  enforceWipLimit: true,
  
  // Intercept and evaluate card move legality
  canMoveCard: (event: CardMoveEvent): boolean => {
    const { cardId, sourceColumnId, targetColumnId } = event;

    // Rule 1: Cannot skip from 'Backlog' directly to 'Done'
    if (sourceColumnId === 'backlog' && targetColumnId === 'done') {
      console.warn('Forbidden transition: tasks must pass through In Progress.');
      return false; // Automatically triggers smooth snap-back animation
    }

    // Rule 2: Role-based permissions
    const currentUserRole = 'engineer'; // From session
    if (targetColumnId === 'production' && currentUserRole !== 'admin') {
      alert('Only administrators can promote tasks to Production.');
      return false;
    }

    return true; // Move permitted
  }
});

2. React Adapter Validation

In React applications, provide canMoveCard and canMoveColumn as declarative component props:

tsx
import React, { useState } from 'react';
import { Kanban, type KanbanColumnProps, type CardMoveEvent } from '@nofinite/kanban/react';
import '@nofinite/nuicss/styles.css';

export function ValidatedWorkflowBoard({ userRole }: { userRole: string }) {
  const [columns, setColumns] = useState<KanbanColumnProps[]>(/* ... */);

  const validateCardMove = (event: CardMoveEvent): boolean => {
    // Prevent non-QA members from moving cards to 'Verified'
    if (event.targetColumnId === 'verified' && userRole !== 'qa') {
      return false;
    }
    return true;
  };

  return (
    <Kanban
      columns={columns}
      onChange={setColumns}
      canMoveCard={validateCardMove}
      enforceWipLimit={true}
    />
  );
}