/* eslint-disable tailwindcss/no-custom-classname -- this adapter needs stable non-Tailwind class hooks for react-grid-layout handles. */ import { useCallback, useEffect, useMemo, useState } from 'react'; import ReactGridLayout, { WidthProvider } from 'react-grid-layout/legacy'; import { usePersistedGridLayout } from '@renderer/hooks/usePersistedGridLayout'; import { browserGridLayoutRepository } from '@renderer/services/layout-system/BrowserGridLayoutRepository'; import { GripVertical } from 'lucide-react'; import { KanbanColumn } from './KanbanColumn'; import type { PersistedGridLayoutItem } from '@renderer/services/layout-system/gridLayoutTypes'; import type { KanbanColumnId } from '@shared/types'; import type { ReactElement, Ref } from 'react'; import type { Layout, LayoutItem, ResizeHandleAxis } from 'react-grid-layout/legacy'; const GRID_COLS = 12; const GRID_ROW_HEIGHT = 18; const GRID_MARGIN: [number, number] = [12, 12]; const DEFAULT_ITEM_WIDTH = 4; const DEFAULT_ITEM_HEIGHT_PX = 400; const DEFAULT_ITEM_HEIGHT = Math.max( 1, Math.round((DEFAULT_ITEM_HEIGHT_PX + GRID_MARGIN[1]) / (GRID_ROW_HEIGHT + GRID_MARGIN[1])) ); const DEFAULT_MIN_HEIGHT = 10; const DEFAULT_MIN_WIDTH = 3; const GRID_SCOPE_KEY = 'kanban-grid-layout:global'; const SKELETON_HIDE_DELAY_MS = 500; const RESIZE_HANDLES: ResizeHandleAxis[] = ['s', 'w', 'e', 'n', 'sw', 'nw', 'se', 'ne']; const WidthAwareGridLayout = WidthProvider(ReactGridLayout); export interface KanbanGridColumn { id: KanbanColumnId; title: string; count: number; icon?: React.ReactNode; headerBg?: string; bodyBg?: string; content: React.ReactNode; } interface KanbanGridLayoutProps { columns: KanbanGridColumn[]; allColumnIds: KanbanColumnId[]; } interface LoadedKanbanGridLayoutProps { readonly columns: KanbanGridColumn[]; readonly visibleItems: PersistedGridLayoutItem[]; readonly onPersistLayout: (layout: Layout, options?: { persist?: boolean }) => void; } interface LoadingKanbanGridLayoutProps { readonly columns: KanbanGridColumn[]; readonly visibleItems: PersistedGridLayoutItem[]; } function buildDefaultItems(itemIds: string[]): PersistedGridLayoutItem[] { return itemIds.map((id, index) => ({ id, x: (index % 3) * DEFAULT_ITEM_WIDTH, y: Math.floor(index / 3) * DEFAULT_ITEM_HEIGHT, w: DEFAULT_ITEM_WIDTH, h: DEFAULT_ITEM_HEIGHT, minW: DEFAULT_MIN_WIDTH, minH: DEFAULT_MIN_HEIGHT, })); } function toReactGridLayoutItem(item: PersistedGridLayoutItem): LayoutItem { return { i: item.id, x: item.x, y: item.y, w: item.w, h: item.h, minW: item.minW, minH: item.minH, maxW: item.maxW, maxH: item.maxH, }; } function fromReactGridLayout(layout: Layout): PersistedGridLayoutItem[] { return layout.map((item) => ({ id: item.i, x: item.x, y: item.y, w: item.w, h: item.h, minW: item.minW, minH: item.minH, maxW: item.maxW, maxH: item.maxH, })); } function renderResizeHandle(axis: ResizeHandleAxis, ref: Ref): ReactElement { return (