@composy/kanban-core 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +171 -37
- package/dist/index.css +114 -114
- package/dist/index.js +221 -126
- package/dist/index.js.map +1 -1
- package/dist/index.min.css +1 -1
- package/dist/index.min.js +758 -1
- package/dist/index.min.js.map +1 -0
- package/es/.dts-output-manifest.json +1 -0
- package/es/.dts.tsbuildinfo +1 -0
- package/es/core/ColumnManager.d.ts +4 -3
- package/es/core/ColumnManager.js +43 -18
- package/es/core/ColumnManager.js.map +1 -1
- package/es/core/DragController.d.ts +1 -2
- package/es/core/DragController.js +11 -1
- package/es/core/DragController.js.map +1 -1
- package/es/core/EventEmitter.d.ts +0 -1
- package/es/core/EventEmitter.js +8 -3
- package/es/core/EventEmitter.js.map +1 -1
- package/es/core/FilterEngine.d.ts +1 -2
- package/es/core/FilterEngine.js +10 -5
- package/es/core/FilterEngine.js.map +1 -1
- package/es/core/KanbanBoard.d.ts +3 -3
- package/es/core/KanbanBoard.js +61 -15
- package/es/core/KanbanBoard.js.map +1 -1
- package/es/core/Renderer.d.ts +2 -3
- package/es/core/Renderer.js +11 -7
- package/es/core/Renderer.js.map +1 -1
- package/es/core/index.d.ts +2 -3
- package/es/core/index.js +1 -1
- package/es/index.d.ts +3 -4
- package/es/index.js +2 -2
- package/es/styles/kanban.css +114 -114
- package/es/types/index.d.ts +3 -4
- package/es/types/index.js +1 -1
- package/es/utils/dom.d.ts +0 -1
- package/es/utils/dom.js +1 -1
- package/es/utils/dom.js.map +1 -1
- package/es/utils/id.d.ts +0 -1
- package/es/utils/id.js +1 -1
- package/es/utils/id.js.map +1 -1
- package/es/utils/index.d.ts +1 -2
- package/es/utils/index.js +1 -1
- package/es/utils/index.js.map +1 -1
- package/es/version.d.ts +0 -1
- package/es/version.js +1 -1
- package/es/version.js.map +1 -1
- package/esm/core/ColumnManager.js +43 -18
- package/esm/core/ColumnManager.js.map +1 -1
- package/esm/core/DragController.js +11 -1
- package/esm/core/DragController.js.map +1 -1
- package/esm/core/EventEmitter.js +8 -3
- package/esm/core/EventEmitter.js.map +1 -1
- package/esm/core/FilterEngine.js +10 -5
- package/esm/core/FilterEngine.js.map +1 -1
- package/esm/core/KanbanBoard.js +63 -17
- package/esm/core/KanbanBoard.js.map +1 -1
- package/esm/core/Renderer.js +11 -7
- package/esm/core/Renderer.js.map +1 -1
- package/esm/index.js +4 -4
- package/esm/styles/kanban.less +357 -339
- package/esm/utils/dom.js +1 -1
- package/esm/utils/dom.js.map +1 -1
- package/esm/utils/id.js +1 -1
- package/esm/utils/id.js.map +1 -1
- package/esm/utils/index.js +2 -2
- package/esm/utils/index.js.map +1 -1
- package/esm/version.js +1 -1
- package/esm/version.js.map +1 -1
- package/lib/core/ColumnManager.cjs +43 -18
- package/lib/core/ColumnManager.cjs.map +1 -1
- package/{esm/core/ColumnManager.d.ts → lib/core/ColumnManager.d.cts} +4 -3
- package/lib/core/DragController.cjs +11 -1
- package/lib/core/DragController.cjs.map +1 -1
- package/{esm/core/DragController.d.ts → lib/core/DragController.d.cts} +1 -2
- package/lib/core/EventEmitter.cjs +8 -3
- package/lib/core/EventEmitter.cjs.map +1 -1
- package/lib/core/{EventEmitter.d.ts → EventEmitter.d.cts} +0 -1
- package/lib/core/FilterEngine.cjs +10 -5
- package/lib/core/FilterEngine.cjs.map +1 -1
- package/{esm/core/FilterEngine.d.ts → lib/core/FilterEngine.d.cts} +1 -2
- package/lib/core/KanbanBoard.cjs +61 -15
- package/lib/core/KanbanBoard.cjs.map +1 -1
- package/{esm/core/KanbanBoard.d.ts → lib/core/KanbanBoard.d.cts} +3 -3
- package/lib/core/Renderer.cjs +11 -7
- package/lib/core/Renderer.cjs.map +1 -1
- package/{esm/core/Renderer.d.ts → lib/core/Renderer.d.cts} +2 -3
- package/lib/core/index.cjs +1 -1
- package/{esm/core/index.d.ts → lib/core/index.d.cts} +2 -3
- package/lib/index.cjs +2 -2
- package/lib/{index.d.ts → index.d.cts} +3 -4
- package/lib/styles/kanban.css +114 -114
- package/lib/types/index.cjs +1 -1
- package/{esm/types/index.d.ts → lib/types/index.d.cts} +3 -4
- package/lib/utils/dom.cjs +1 -1
- package/lib/utils/dom.cjs.map +1 -1
- package/lib/utils/{dom.d.ts → dom.d.cts} +0 -1
- package/lib/utils/id.cjs +1 -1
- package/lib/utils/id.cjs.map +1 -1
- package/{esm/utils/id.d.ts → lib/utils/id.d.cts} +0 -1
- package/lib/utils/index.cjs +1 -1
- package/lib/utils/index.cjs.map +1 -1
- package/lib/utils/{index.d.ts → index.d.cts} +1 -2
- package/lib/version.cjs +1 -1
- package/lib/version.cjs.map +1 -1
- package/{esm/version.d.ts → lib/version.d.cts} +0 -1
- package/package.json +23 -21
- package/es/core/ColumnManager.d.ts.map +0 -1
- package/es/core/DragController.d.ts.map +0 -1
- package/es/core/EventEmitter.d.ts.map +0 -1
- package/es/core/FilterEngine.d.ts.map +0 -1
- package/es/core/KanbanBoard.d.ts.map +0 -1
- package/es/core/Renderer.d.ts.map +0 -1
- package/es/core/index.d.ts.map +0 -1
- package/es/index.d.ts.map +0 -1
- package/es/types/index.d.ts.map +0 -1
- package/es/utils/dom.d.ts.map +0 -1
- package/es/utils/id.d.ts.map +0 -1
- package/es/utils/index.d.ts.map +0 -1
- package/es/version.d.ts.map +0 -1
- package/esm/core/ColumnManager.d.ts.map +0 -1
- package/esm/core/DragController.d.ts.map +0 -1
- package/esm/core/EventEmitter.d.ts +0 -35
- package/esm/core/EventEmitter.d.ts.map +0 -1
- package/esm/core/FilterEngine.d.ts.map +0 -1
- package/esm/core/KanbanBoard.d.ts.map +0 -1
- package/esm/core/Renderer.d.ts.map +0 -1
- package/esm/core/index.d.ts.map +0 -1
- package/esm/core/index.js +0 -17
- package/esm/index.d.ts +0 -15
- package/esm/index.d.ts.map +0 -1
- package/esm/types/index.d.ts.map +0 -1
- package/esm/types/index.js +0 -10
- package/esm/utils/dom.d.ts +0 -24
- package/esm/utils/dom.d.ts.map +0 -1
- package/esm/utils/id.d.ts.map +0 -1
- package/esm/utils/index.d.ts +0 -25
- package/esm/utils/index.d.ts.map +0 -1
- package/esm/version.d.ts.map +0 -1
- package/lib/core/ColumnManager.d.ts +0 -99
- package/lib/core/DragController.d.ts +0 -55
- package/lib/core/FilterEngine.d.ts +0 -45
- package/lib/core/KanbanBoard.d.ts +0 -152
- package/lib/core/Renderer.d.ts +0 -59
- package/lib/core/index.d.ts +0 -11
- package/lib/types/index.d.ts +0 -209
- package/lib/utils/id.d.ts +0 -9
- package/lib/version.d.ts +0 -6
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/utils/dom.ts","../src/core/EventEmitter.ts","../src/utils/id.ts","../src/core/ColumnManager.ts","../src/core/DragController.ts","../src/core/FilterEngine.ts","../src/core/Renderer.ts","../src/version.ts","../src/core/KanbanBoard.ts","../src/utils/index.ts"],"sourcesContent":["/**\n * DOM 工具函数\n */\n\n/**\n * 创建 DOM 元素\n */\nexport function createElement<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n className?: string,\n attributes?: Record<string, string>,\n): HTMLElementTagNameMap[K] {\n const el = document.createElement(tag);\n if (className) el.className = className;\n if (attributes) {\n Object.entries(attributes).forEach(([key, value]) => {\n el.setAttribute(key, value);\n });\n }\n return el;\n}\n\n/**\n * 从选择器或元素获取 HTMLElement\n */\nexport function resolveElement(target: HTMLElement | string): HTMLElement | null {\n if (typeof target === 'string') {\n return document.querySelector(target);\n }\n return target;\n}\n\n/**\n * 清空元素内容\n */\nexport function clearElement(el: HTMLElement): void {\n el.innerHTML = '';\n}\n\n/**\n * 安全移除元素\n */\nexport function removeElement(el: HTMLElement | null): void {\n el?.parentNode?.removeChild(el);\n}\n\n/**\n * 插入元素到指定位置\n */\nexport function insertAt(parent: HTMLElement, child: HTMLElement, index: number): void {\n const ref = parent.children[index] as HTMLElement | undefined;\n if (ref) {\n parent.insertBefore(child, ref);\n } else {\n parent.appendChild(child);\n }\n}\n","/**\n * 轻量级事件发射器\n */\nexport type EventHandler = (...args: unknown[]) => void;\n\n/**\n * EventEmitter - Event Emitter class\n */\nexport class EventEmitter {\n private listeners = new Map<string, Set<EventHandler>>();\n\n /**\n * 监听事件\n */\n on(event: string, handler: EventHandler): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(handler);\n return () => this.off(event, handler);\n }\n\n /**\n * 监听一次性事件\n */\n once(event: string, handler: EventHandler): () => void {\n const wrapper: EventHandler = (...args) => {\n this.off(event, wrapper);\n handler(...args);\n };\n return this.on(event, wrapper);\n }\n\n /**\n * 移除监听器\n */\n off(event: string, handler: EventHandler): void {\n this.listeners.get(event)?.delete(handler);\n }\n\n /**\n * 触发事件\n */\n emit(event: string, payload?: unknown): void {\n const handlers = this.listeners.get(event);\n if (handlers) {\n handlers.forEach(handler => {\n try {\n handler(payload);\n } catch (err) {\n console.error(`[KanbanBoard] Error in event handler for \"${event}\":`, err);\n }\n });\n }\n }\n\n /**\n * 移除所有监听器\n */\n removeAll(): void {\n this.listeners.clear();\n }\n\n /**\n * 获取监听器数量\n */\n listenerCount(event: string): number {\n return this.listeners.get(event)?.size ?? 0;\n }\n}\n","let counter = 0;\n\n/**\n * 生成唯一 ID\n */\nexport function generateId(prefix = 'kb'): string {\n counter++;\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 6);\n return `${prefix}_${timestamp}_${random}_${counter}`;\n}\n\n/**\n * 重置计数器(仅测试用)\n */\nexport function resetIdCounter(): void {\n counter = 0;\n}\n","import type { Column, Card } from '../types';\nimport { generateId } from '../utils/id';\nimport { EventEmitter } from './EventEmitter';\n\n/**\n * 列管理器\n */\nexport class ColumnManager {\n private columns: Column[] = [];\n private events: EventEmitter;\n\n constructor(events: EventEmitter) {\n this.events = events;\n }\n\n /**\n * 初始化列\n */\n init(columns: Partial<Column>[]): void {\n this.columns = columns.map((col, index) => this.normalizeColumn(col, index));\n }\n\n /**\n * 标准化列数据\n */\n private normalizeColumn(partial: Partial<Column>, index: number): Column {\n return {\n id: partial.id || generateId('col'),\n title: partial.title || `Column ${index + 1}`,\n cards: (partial.cards || []).map((card, cardIndex) =>\n this.normalizeCard(card, partial.id || '', cardIndex),\n ),\n wipLimit: partial.wipLimit,\n collapsed: partial.collapsed ?? false,\n color: partial.color,\n order: partial.order ?? index,\n };\n }\n\n /**\n * 标准化卡片数据\n */\n private normalizeCard(partial: Partial<Card>, columnId: string, index: number): Card {\n const id = partial.id || generateId('card');\n return {\n id,\n title: partial.title || '',\n description: partial.description,\n labels: partial.labels || [],\n assignees: partial.assignees || [],\n dueDate: partial.dueDate,\n priority: partial.priority,\n order: partial.order ?? index,\n columnId: partial.columnId || columnId,\n data: partial.data,\n createdAt: partial.createdAt || new Date().toISOString(),\n updatedAt: partial.updatedAt,\n };\n }\n\n /**\n * 获取所有列\n */\n getColumns(): Column[] {\n return [...this.columns].sort((a, b) => a.order - b.order);\n }\n\n /**\n * 获取单列\n */\n getColumn(id: string): Column | undefined {\n return this.columns.find(c => c.id === id);\n }\n\n /**\n * 添加列\n */\n addColumn(partial: Partial<Column>): Column {\n const column = this.normalizeColumn(partial, this.columns.length);\n // 确保新列的 cards 关联 columnId\n column.cards = column.cards.map(card => ({ ...card, columnId: column.id }));\n this.columns.push(column);\n this.events.emit('column:add', { column });\n return column;\n }\n\n /**\n * 移除列\n */\n removeColumn(id: string): Column | undefined {\n const index = this.columns.findIndex(c => c.id === id);\n if (index === -1) return undefined;\n const [column] = this.columns.splice(index, 1);\n this.reorderColumns();\n this.events.emit('column:remove', { column });\n return column;\n }\n\n /**\n * 更新列\n */\n updateColumn(id: string, changes: Partial<Column>): Column | undefined {\n const column = this.columns.find(c => c.id === id);\n if (!column) return undefined;\n Object.assign(column, changes, { id }); // 不允许更改 id\n this.events.emit('column:update', { column, changes });\n return column;\n }\n\n /**\n * 移动列\n */\n moveColumn(id: string, toIndex: number): void {\n const fromIndex = this.columns.findIndex(c => c.id === id);\n if (fromIndex === -1) return;\n const [column] = this.columns.splice(fromIndex, 1);\n this.columns.splice(toIndex, 0, column);\n this.reorderColumns();\n this.events.emit('column:move', { column, fromIndex, toIndex });\n }\n\n /**\n * 折叠/展开列\n */\n toggleCollapse(id: string): void {\n const column = this.columns.find(c => c.id === id);\n if (!column) return;\n column.collapsed = !column.collapsed;\n this.events.emit('column:collapse', { column, collapsed: column.collapsed });\n }\n\n /**\n * 获取列中的卡片\n */\n getCards(columnId: string): Card[] {\n const column = this.columns.find(c => c.id === columnId);\n return column ? [...column.cards].sort((a, b) => a.order - b.order) : [];\n }\n\n /**\n * 添加卡片到列\n */\n addCard(columnId: string, partial: Partial<Card>): Card | undefined {\n const column = this.columns.find(c => c.id === columnId);\n if (!column) return undefined;\n\n // 检查 WIP 限制\n if (column.wipLimit && column.cards.length >= column.wipLimit) {\n this.events.emit('error', {\n error: new Error(`Column \"${column.title}\" reached WIP limit (${column.wipLimit})`),\n });\n return undefined;\n }\n\n const card = this.normalizeCard(\n { ...partial, columnId },\n columnId,\n column.cards.length,\n );\n column.cards.push(card);\n this.events.emit('card:add', { card, columnId });\n return card;\n }\n\n /**\n * 移除卡片\n */\n removeCard(cardId: string): Card | undefined {\n for (const column of this.columns) {\n const index = column.cards.findIndex(c => c.id === cardId);\n if (index !== -1) {\n const [card] = column.cards.splice(index, 1);\n this.reorderCards(column);\n this.events.emit('card:remove', { card, columnId: column.id });\n return card;\n }\n }\n return undefined;\n }\n\n /**\n * 更新卡片\n */\n updateCard(cardId: string, changes: Partial<Card>): Card | undefined {\n for (const column of this.columns) {\n const card = column.cards.find(c => c.id === cardId);\n if (card) {\n Object.assign(card, changes, { id: cardId, columnId: column.id });\n card.updatedAt = new Date().toISOString();\n this.events.emit('card:update', { card, changes });\n return card;\n }\n }\n return undefined;\n }\n\n /**\n * 获取单张卡片\n */\n getCard(cardId: string): Card | undefined {\n for (const column of this.columns) {\n const card = column.cards.find(c => c.id === cardId);\n if (card) return card;\n }\n return undefined;\n }\n\n /**\n * 移动卡片\n */\n moveCard(cardId: string, toColumnId: string, toIndex: number): void {\n let fromColumn: Column | undefined;\n let cardIndex = -1;\n\n for (const column of this.columns) {\n const idx = column.cards.findIndex(c => c.id === cardId);\n if (idx !== -1) {\n fromColumn = column;\n cardIndex = idx;\n break;\n }\n }\n\n if (!fromColumn || cardIndex === -1) return;\n\n const toColumn = this.columns.find(c => c.id === toColumnId);\n if (!toColumn) return;\n\n // 检查 WIP 限制(跨列移动时)\n if (\n fromColumn.id !== toColumnId &&\n toColumn.wipLimit &&\n toColumn.cards.length >= toColumn.wipLimit\n ) {\n this.events.emit('error', {\n error: new Error(`Column \"${toColumn.title}\" reached WIP limit (${toColumn.wipLimit})`),\n });\n return;\n }\n\n const [card] = fromColumn.cards.splice(cardIndex, 1);\n card.columnId = toColumnId;\n toColumn.cards.splice(toIndex, 0, card);\n\n this.reorderCards(fromColumn);\n this.reorderCards(toColumn);\n\n this.events.emit('card:move', {\n card,\n fromColumnId: fromColumn.id,\n toColumnId,\n toIndex,\n });\n }\n\n /**\n * 获取所有卡片\n */\n getAllCards(): Card[] {\n const cards: Card[] = [];\n for (const column of this.columns) {\n cards.push(...column.cards);\n }\n return cards;\n }\n\n /**\n * 获取卡片总数\n */\n getCardCount(): number {\n return this.columns.reduce((sum, col) => sum + col.cards.length, 0);\n }\n\n /**\n * 重新排序列\n */\n private reorderColumns(): void {\n this.columns.forEach((col, index) => {\n col.order = index;\n });\n }\n\n /**\n * 重新排序列中的卡片\n */\n private reorderCards(column: Column): void {\n column.cards.forEach((card, index) => {\n card.order = index;\n });\n }\n\n /**\n * 设置列数据(用于导入)\n */\n setColumns(columns: Column[]): void {\n this.columns = columns;\n }\n\n /**\n * 清空所有数据\n */\n clear(): void {\n this.columns = [];\n }\n}\n","import { EventEmitter } from './EventEmitter';\n\n/**\n * DragState - Drag State interface\n */\nexport interface DragState {\n dragging: boolean;\n cardId: string | null;\n sourceColumnId: string | null;\n targetColumnId: string | null;\n targetIndex: number;\n placeholder: HTMLElement | null;\n}\n\n/**\n * 拖拽控制器 - HTML5 Drag & Drop API\n */\nexport class DragController {\n private events: EventEmitter;\n private state: DragState = {\n dragging: false,\n cardId: null,\n sourceColumnId: null,\n targetColumnId: null,\n targetIndex: 0,\n placeholder: null,\n };\n private prefix: string;\n private cleanupFns: (() => void)[] = [];\n\n constructor(events: EventEmitter, prefix: string) {\n this.events = events;\n this.prefix = prefix;\n }\n\n /**\n * 为卡片元素启用拖拽\n */\n enableCardDrag(cardEl: HTMLElement, cardId: string, columnId: string): void {\n cardEl.setAttribute('draggable', 'true');\n cardEl.dataset.cardId = cardId;\n cardEl.dataset.columnId = columnId;\n\n const onDragStart = (e: DragEvent) => {\n if (!e.dataTransfer) return;\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/plain', cardId);\n\n this.state.dragging = true;\n this.state.cardId = cardId;\n this.state.sourceColumnId = columnId;\n\n cardEl.classList.add(`${this.prefix}-card--dragging`);\n this.events.emit('card:drag-start', { cardId, columnId });\n\n // 创建占位符\n this.createPlaceholder(cardEl);\n };\n\n const onDragEnd = () => {\n cardEl.classList.remove(`${this.prefix}-card--dragging`);\n this.removePlaceholder();\n this.state.dragging = false;\n this.state.cardId = null;\n this.state.sourceColumnId = null;\n this.events.emit('card:drag-end', { cardId });\n };\n\n cardEl.addEventListener('dragstart', onDragStart);\n cardEl.addEventListener('dragend', onDragEnd);\n\n this.cleanupFns.push(() => {\n cardEl.removeEventListener('dragstart', onDragStart);\n cardEl.removeEventListener('dragend', onDragEnd);\n });\n }\n\n /**\n * 为列容器启用拖拽接受\n */\n enableColumnDrop(columnBodyEl: HTMLElement, columnId: string): void {\n const onDragOver = (e: DragEvent) => {\n e.preventDefault();\n if (!e.dataTransfer) return;\n e.dataTransfer.dropEffect = 'move';\n\n this.state.targetColumnId = columnId;\n\n // 计算插入位置\n const afterElement = this.getDragAfterElement(columnBodyEl, e.clientY);\n const placeholder = this.state.placeholder;\n if (placeholder) {\n if (afterElement) {\n columnBodyEl.insertBefore(placeholder, afterElement);\n } else {\n // 插入到最后一张卡片之后,但在“添加卡片”按钮之前\n const addBtn = columnBodyEl.querySelector(`.${this.prefix}-add-card`);\n if (addBtn) {\n columnBodyEl.insertBefore(placeholder, addBtn);\n } else {\n columnBodyEl.appendChild(placeholder);\n }\n }\n }\n };\n\n const onDragEnter = (e: DragEvent) => {\n e.preventDefault();\n columnBodyEl.classList.add(`${this.prefix}-column-body--drag-over`);\n };\n\n const onDragLeave = (e: DragEvent) => {\n // 检查是否真的离开了列\n const rect = columnBodyEl.getBoundingClientRect();\n if (\n e.clientX < rect.left ||\n e.clientX > rect.right ||\n e.clientY < rect.top ||\n e.clientY > rect.bottom\n ) {\n columnBodyEl.classList.remove(`${this.prefix}-column-body--drag-over`);\n }\n };\n\n const onDrop = (e: DragEvent) => {\n e.preventDefault();\n columnBodyEl.classList.remove(`${this.prefix}-column-body--drag-over`);\n\n const cardId = this.state.cardId;\n if (!cardId) return;\n\n // 计算 drop 位置:只统计占位符前面的可见卡片数量\n const placeholder = this.state.placeholder;\n let dropIndex = 0;\n\n if (placeholder && placeholder.parentNode === columnBodyEl) {\n const children = [...columnBodyEl.children];\n for (const child of children) {\n if (child === placeholder) break;\n if (\n (child as HTMLElement).hasAttribute('data-card-id') &&\n !(child as HTMLElement).classList.contains(`${this.prefix}-card--dragging`)\n ) {\n dropIndex++;\n }\n }\n } else {\n // 占位符不在当前列时,放到末尾\n const cards = columnBodyEl.querySelectorAll(\n `[data-card-id]:not(.${this.prefix}-card--dragging)`,\n );\n dropIndex = cards.length;\n }\n\n this.events.emit('card:drop', {\n cardId,\n fromColumnId: this.state.sourceColumnId,\n toColumnId: columnId,\n toIndex: dropIndex,\n });\n\n this.removePlaceholder();\n };\n\n columnBodyEl.addEventListener('dragover', onDragOver);\n columnBodyEl.addEventListener('dragenter', onDragEnter);\n columnBodyEl.addEventListener('dragleave', onDragLeave);\n columnBodyEl.addEventListener('drop', onDrop);\n\n this.cleanupFns.push(() => {\n columnBodyEl.removeEventListener('dragover', onDragOver);\n columnBodyEl.removeEventListener('dragenter', onDragEnter);\n columnBodyEl.removeEventListener('dragleave', onDragLeave);\n columnBodyEl.removeEventListener('drop', onDrop);\n });\n }\n\n /**\n * 为列头部启用列拖拽\n */\n enableColumnDrag(\n columnEl: HTMLElement,\n handleEl: HTMLElement,\n columnId: string,\n boardEl: HTMLElement,\n ): void {\n handleEl.setAttribute('draggable', 'true');\n\n const onDragStart = (e: DragEvent) => {\n if (!e.dataTransfer) return;\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('application/kanban-column', columnId);\n columnEl.classList.add(`${this.prefix}-column--dragging`);\n };\n\n const onDragEnd = () => {\n columnEl.classList.remove(`${this.prefix}-column--dragging`);\n // 清除所有列的 drag-over 状态\n boardEl.querySelectorAll(`.${this.prefix}-column--drag-over`).forEach(el => {\n el.classList.remove(`${this.prefix}-column--drag-over`);\n });\n };\n\n const onDragOver = (e: DragEvent) => {\n if (!e.dataTransfer?.types.includes('application/kanban-column')) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n columnEl.classList.add(`${this.prefix}-column--drag-over`);\n };\n\n const onDragLeave = () => {\n columnEl.classList.remove(`${this.prefix}-column--drag-over`);\n };\n\n const onDrop = (e: DragEvent) => {\n e.preventDefault();\n columnEl.classList.remove(`${this.prefix}-column--drag-over`);\n const fromColumnId = e.dataTransfer?.getData('application/kanban-column');\n if (!fromColumnId || fromColumnId === columnId) return;\n\n // 计算目标位置\n const columns = [...boardEl.querySelectorAll(`[data-column-id]`)];\n const toIndex = columns.indexOf(columnEl);\n this.events.emit('column:drop', { fromColumnId, toColumnId: columnId, toIndex });\n };\n\n handleEl.addEventListener('dragstart', onDragStart);\n handleEl.addEventListener('dragend', onDragEnd);\n columnEl.addEventListener('dragover', onDragOver);\n columnEl.addEventListener('dragleave', onDragLeave);\n columnEl.addEventListener('drop', onDrop);\n\n this.cleanupFns.push(() => {\n handleEl.removeEventListener('dragstart', onDragStart);\n handleEl.removeEventListener('dragend', onDragEnd);\n columnEl.removeEventListener('dragover', onDragOver);\n columnEl.removeEventListener('dragleave', onDragLeave);\n columnEl.removeEventListener('drop', onDrop);\n });\n }\n\n /**\n * 获取鼠标位置之后的元素\n */\n private getDragAfterElement(container: HTMLElement, y: number): HTMLElement | null {\n const draggableElements = [\n ...container.querySelectorAll(\n `[data-card-id]:not(.${this.prefix}-card--dragging):not(.${this.prefix}-placeholder)`,\n ),\n ] as HTMLElement[];\n\n let closestOffset = Number.NEGATIVE_INFINITY;\n let closestElement: HTMLElement | null = null;\n\n draggableElements.forEach(child => {\n const box = child.getBoundingClientRect();\n const offset = y - box.top - box.height / 2;\n if (offset < 0 && offset > closestOffset) {\n closestOffset = offset;\n closestElement = child;\n }\n });\n\n return closestElement;\n }\n\n /**\n * 创建占位符\n */\n private createPlaceholder(cardEl: HTMLElement): void {\n this.removePlaceholder();\n const placeholder = document.createElement('div');\n placeholder.className = `${this.prefix}-placeholder`;\n placeholder.style.height = `${cardEl.offsetHeight}px`;\n this.state.placeholder = placeholder;\n }\n\n /**\n * 移除占位符\n */\n private removePlaceholder(): void {\n if (this.state.placeholder) {\n this.state.placeholder.parentNode?.removeChild(this.state.placeholder);\n this.state.placeholder = null;\n }\n }\n\n /**\n * 获取当前拖拽状态\n */\n getState(): Readonly<DragState> {\n return { ...this.state };\n }\n\n /**\n * 销毁\n */\n destroy(): void {\n this.cleanupFns.forEach(fn => fn());\n this.cleanupFns = [];\n this.removePlaceholder();\n }\n}\n","import type { Card, Column, FilterCriteria } from '../types';\nimport { EventEmitter } from './EventEmitter';\n\n/**\n * 筛选/搜索引擎\n */\nexport class FilterEngine {\n private events: EventEmitter;\n private currentCriteria: FilterCriteria | null = null;\n /** 被过滤隐藏的卡片 ID 集合 */\n private hiddenCardIds = new Set<string>();\n\n constructor(events: EventEmitter) {\n this.events = events;\n }\n\n /**\n * 应用筛选条件\n */\n filter(criteria: FilterCriteria, columns: Column[]): Set<string> {\n this.currentCriteria = criteria;\n this.hiddenCardIds.clear();\n\n const allCards = columns.flatMap(col => col.cards);\n\n for (const card of allCards) {\n if (!this.matchCriteria(card, criteria)) {\n this.hiddenCardIds.add(card.id);\n }\n }\n\n this.events.emit('filter:change', { criteria });\n return new Set(this.hiddenCardIds);\n }\n\n /**\n * 搜索卡片\n */\n search(keyword: string, columns: Column[]): Card[] {\n this.events.emit('search:change', { keyword });\n\n if (!keyword.trim()) {\n this.clearFilter();\n return columns.flatMap(col => col.cards);\n }\n\n const lowerKeyword = keyword.toLowerCase();\n const allCards = columns.flatMap(col => col.cards);\n const matched: Card[] = [];\n\n this.hiddenCardIds.clear();\n\n for (const card of allCards) {\n const titleMatch = card.title.toLowerCase().includes(lowerKeyword);\n const descMatch = card.description?.toLowerCase().includes(lowerKeyword) ?? false;\n const labelMatch = card.labels?.some(l => l.name.toLowerCase().includes(lowerKeyword)) ?? false;\n const assigneeMatch = card.assignees?.some(a => a.toLowerCase().includes(lowerKeyword)) ?? false;\n\n if (titleMatch || descMatch || labelMatch || assigneeMatch) {\n matched.push(card);\n } else {\n this.hiddenCardIds.add(card.id);\n }\n }\n\n return matched;\n }\n\n /**\n * 清除筛选\n */\n clearFilter(): void {\n this.currentCriteria = null;\n this.hiddenCardIds.clear();\n this.events.emit('filter:clear', undefined);\n }\n\n /**\n * 检查卡片是否可见\n */\n isCardVisible(cardId: string): boolean {\n return !this.hiddenCardIds.has(cardId);\n }\n\n /**\n * 获取隐藏的卡片 ID 集合\n */\n getHiddenCardIds(): Set<string> {\n return new Set(this.hiddenCardIds);\n }\n\n /**\n * 获取当前筛选条件\n */\n getCurrentCriteria(): FilterCriteria | null {\n return this.currentCriteria;\n }\n\n /**\n * 匹配筛选条件\n */\n private matchCriteria(card: Card, criteria: FilterCriteria): boolean {\n // 关键词\n if (criteria.keyword) {\n const kw = criteria.keyword.toLowerCase();\n const titleMatch = card.title.toLowerCase().includes(kw);\n const descMatch = card.description?.toLowerCase().includes(kw) ?? false;\n if (!titleMatch && !descMatch) return false;\n }\n\n // 标签\n if (criteria.labelIds?.length) {\n const cardLabelIds = card.labels?.map(l => l.id) ?? [];\n if (!criteria.labelIds.some(id => cardLabelIds.includes(id))) return false;\n }\n\n // 成员\n if (criteria.assignees?.length) {\n if (!criteria.assignees.some(a => card.assignees?.includes(a))) return false;\n }\n\n // 优先级\n if (criteria.priorities?.length) {\n if (!card.priority || !criteria.priorities.includes(card.priority)) return false;\n }\n\n // 列\n if (criteria.columnIds?.length) {\n if (!criteria.columnIds.includes(card.columnId)) return false;\n }\n\n // 截止日期\n if (criteria.dueDateRange) {\n if (!card.dueDate) return false;\n const dueDate = new Date(card.dueDate).getTime();\n if (criteria.dueDateRange.start) {\n if (dueDate < new Date(criteria.dueDateRange.start).getTime()) return false;\n }\n if (criteria.dueDateRange.end) {\n if (dueDate > new Date(criteria.dueDateRange.end).getTime()) return false;\n }\n }\n\n // 自定义函数\n if (criteria.custom) {\n if (!criteria.custom(card)) return false;\n }\n\n return true;\n }\n\n /**\n * 销毁\n */\n destroy(): void {\n this.hiddenCardIds.clear();\n this.currentCriteria = null;\n }\n}\n","import type { Column, Card, KanbanOptions } from '../types';\nimport { createElement } from '../utils/dom';\nimport { EventEmitter } from './EventEmitter';\nimport { DragController } from './DragController';\n\n/**\n * DOM 渲染器\n */\nexport class Renderer {\n private container: HTMLElement;\n private boardEl: HTMLElement | null = null;\n private events: EventEmitter;\n private dragController: DragController;\n private options: KanbanOptions;\n private prefix: string;\n private columnElements = new Map<string, HTMLElement>();\n private columnBodyElements = new Map<string, HTMLElement>();\n private cardElements = new Map<string, HTMLElement>();\n\n constructor(\n container: HTMLElement,\n events: EventEmitter,\n dragController: DragController,\n options: KanbanOptions,\n ) {\n this.container = container;\n this.events = events;\n this.dragController = dragController;\n this.options = options;\n this.prefix = options.classPrefix || 'kanban';\n }\n\n /**\n * 渲染整个看板\n */\n render(columns: Column[], hiddenCardIds?: Set<string>): void {\n this.cleanup();\n\n // 清除容器中残留的旧看板元素(HMR / 重复渲染保护)\n const staleBoards = this.container.querySelectorAll('[data-kanban-board]');\n staleBoards.forEach(el => el.remove());\n\n const p = this.prefix;\n this.boardEl = createElement('div', `${p}-board`);\n this.boardEl.setAttribute('data-kanban-board', '');\n\n // 列容器\n const columnsContainer = createElement('div', `${p}-columns`);\n\n for (const column of columns) {\n const colEl = this.renderColumn(column, hiddenCardIds);\n columnsContainer.appendChild(colEl);\n }\n\n // 添加列按钮\n if (this.options.showAddColumn !== false) {\n const addColBtn = createElement('div', `${p}-add-column`);\n addColBtn.innerHTML = `<button class=\"${p}-add-column-btn\">+ 添加列</button>`;\n addColBtn.querySelector('button')!.addEventListener('click', () => {\n this.events.emit('ui:add-column');\n });\n columnsContainer.appendChild(addColBtn);\n }\n\n this.boardEl.appendChild(columnsContainer);\n this.container.appendChild(this.boardEl);\n }\n\n /**\n * 渲染单个列\n */\n private renderColumn(column: Column, hiddenCardIds?: Set<string>): HTMLElement {\n const p = this.prefix;\n const colEl = createElement('div', `${p}-column`, { 'data-column-id': column.id });\n if (column.collapsed) colEl.classList.add(`${p}-column--collapsed`);\n\n // 列头部\n const header = this.renderColumnHeader(column);\n colEl.appendChild(header);\n\n // 列内容\n const body = createElement('div', `${p}-column-body`);\n body.dataset.columnId = column.id;\n\n if (!column.collapsed) {\n const visibleCards = column.cards\n .filter(card => !hiddenCardIds || !hiddenCardIds.has(card.id))\n .sort((a, b) => a.order - b.order);\n\n for (const card of visibleCards) {\n const cardEl = this.renderCard(card, column.id);\n body.appendChild(cardEl);\n }\n\n // 添加卡片按钮\n if (this.options.showAddCard !== false) {\n const addBtn = createElement('div', `${p}-add-card`);\n addBtn.innerHTML = `<button class=\"${p}-add-card-btn\">+ 添加卡片</button>`;\n addBtn.querySelector('button')!.addEventListener('click', () => {\n this.events.emit('ui:add-card', { columnId: column.id });\n });\n body.appendChild(addBtn);\n }\n\n // 启用列内拖拽放置\n if (this.options.draggable !== false) {\n this.dragController.enableColumnDrop(body, column.id);\n }\n }\n\n colEl.appendChild(body);\n\n // 列拖拽\n if (this.options.columnDraggable !== false && this.boardEl) {\n const dragHandle = header.querySelector(`.${p}-column-drag-handle`) as HTMLElement;\n if (dragHandle) {\n this.dragController.enableColumnDrag(colEl, dragHandle, column.id, this.boardEl!);\n }\n }\n\n this.columnElements.set(column.id, colEl);\n this.columnBodyElements.set(column.id, body);\n\n return colEl;\n }\n\n /**\n * 渲染列头部\n */\n private renderColumnHeader(column: Column): HTMLElement {\n const p = this.prefix;\n const header = createElement('div', `${p}-column-header`);\n\n if (this.options.columnHeaderRenderer) {\n this.options.columnHeaderRenderer(column, header);\n return header;\n }\n\n // 拖拽手柄\n if (this.options.columnDraggable !== false) {\n const handle = createElement('span', `${p}-column-drag-handle`);\n handle.innerHTML = '⋮⋮';\n handle.title = '拖拽排序';\n header.appendChild(handle);\n }\n\n // 颜色指示器\n if (column.color) {\n const indicator = createElement('span', `${p}-column-color`);\n indicator.style.backgroundColor = column.color;\n header.appendChild(indicator);\n }\n\n // 标题\n const titleEl = createElement('span', `${p}-column-title`);\n titleEl.textContent = column.title;\n header.appendChild(titleEl);\n\n // 卡片计数\n if (this.options.showCardCount !== false) {\n const count = createElement('span', `${p}-column-count`);\n const wipText = column.wipLimit ? `/${column.wipLimit}` : '';\n count.textContent = `${column.cards.length}${wipText}`;\n if (column.wipLimit && column.cards.length >= column.wipLimit) {\n count.classList.add(`${p}-column-count--limit`);\n }\n header.appendChild(count);\n }\n\n // 折叠按钮\n const collapseBtn = createElement('button', `${p}-column-collapse-btn`);\n collapseBtn.innerHTML = column.collapsed ? '▶' : '▼';\n collapseBtn.title = column.collapsed ? '展开' : '折叠';\n collapseBtn.addEventListener('click', () => {\n this.events.emit('ui:toggle-collapse', { columnId: column.id });\n });\n header.appendChild(collapseBtn);\n\n // 操作菜单\n if (this.options.showColumnActions !== false) {\n const actions = createElement('button', `${p}-column-actions-btn`);\n actions.innerHTML = '⋯';\n actions.title = '更多操作';\n actions.addEventListener('click', (e) => {\n e.stopPropagation();\n this.events.emit('ui:column-actions', { columnId: column.id, event: e });\n });\n header.appendChild(actions);\n }\n\n return header;\n }\n\n /**\n * 渲染单张卡片\n */\n private renderCard(card: Card, columnId: string): HTMLElement {\n const p = this.prefix;\n const cardEl = createElement('div', `${p}-card`, { 'data-card-id': card.id });\n\n if (this.options.cardRenderer) {\n this.options.cardRenderer(card, cardEl);\n } else {\n this.renderDefaultCard(card, cardEl);\n }\n\n // 启用卡片拖拽\n if (this.options.draggable !== false) {\n this.dragController.enableCardDrag(cardEl, card.id, columnId);\n }\n\n // 点击事件\n cardEl.addEventListener('click', () => {\n this.events.emit('card:click', { card });\n });\n\n this.cardElements.set(card.id, cardEl);\n return cardEl;\n }\n\n /**\n * 默认卡片渲染\n */\n private renderDefaultCard(card: Card, cardEl: HTMLElement): void {\n const p = this.prefix;\n\n // 优先级指示器\n if (card.priority) {\n const priorityEl = createElement('div', `${p}-card-priority ${p}-card-priority--${card.priority}`);\n cardEl.appendChild(priorityEl);\n }\n\n // 标签\n if (card.labels?.length) {\n const labelsEl = createElement('div', `${p}-card-labels`);\n for (const label of card.labels) {\n const labelEl = createElement('span', `${p}-card-label`);\n labelEl.style.backgroundColor = label.color;\n labelEl.textContent = label.name;\n labelsEl.appendChild(labelEl);\n }\n cardEl.appendChild(labelsEl);\n }\n\n // 标题\n const titleEl = createElement('div', `${p}-card-title`);\n titleEl.textContent = card.title;\n cardEl.appendChild(titleEl);\n\n // 描述\n if (card.description) {\n const descEl = createElement('div', `${p}-card-desc`);\n descEl.textContent = card.description;\n cardEl.appendChild(descEl);\n }\n\n // 底部信息栏\n const hasFooter = card.assignees?.length || card.dueDate;\n if (hasFooter) {\n const footer = createElement('div', `${p}-card-footer`);\n\n if (card.assignees?.length) {\n const assigneesEl = createElement('div', `${p}-card-assignees`);\n for (const assignee of card.assignees.slice(0, 3)) {\n const avatar = createElement('span', `${p}-card-avatar`);\n avatar.textContent = assignee.charAt(0).toUpperCase();\n avatar.title = assignee;\n assigneesEl.appendChild(avatar);\n }\n if (card.assignees.length > 3) {\n const more = createElement('span', `${p}-card-avatar-more`);\n more.textContent = `+${card.assignees.length - 3}`;\n assigneesEl.appendChild(more);\n }\n footer.appendChild(assigneesEl);\n }\n\n if (card.dueDate) {\n const dueEl = createElement('span', `${p}-card-due`);\n const date = new Date(card.dueDate);\n dueEl.textContent = `${date.getMonth() + 1}/${date.getDate()}`;\n const now = new Date();\n if (date < now) dueEl.classList.add(`${p}-card-due--overdue`);\n footer.appendChild(dueEl);\n }\n\n cardEl.appendChild(footer);\n }\n }\n\n /**\n * 获取列元素\n */\n getColumnElement(columnId: string): HTMLElement | undefined {\n return this.columnElements.get(columnId);\n }\n\n /**\n * 获取卡片元素\n */\n getCardElement(cardId: string): HTMLElement | undefined {\n return this.cardElements.get(cardId);\n }\n\n /**\n * 获取看板根元素\n */\n getBoardElement(): HTMLElement | null {\n return this.boardEl;\n }\n\n /**\n * 清理 DOM\n */\n private cleanup(): void {\n this.columnElements.clear();\n this.columnBodyElements.clear();\n this.cardElements.clear();\n if (this.boardEl) {\n this.boardEl.remove();\n this.boardEl = null;\n }\n }\n\n /**\n * 销毁\n */\n destroy(): void {\n this.cleanup();\n }\n}\n","/**\n * @file version.ts\n * @description version 模块\n */\n\nexport const VERSION = '0.1.0';\n","import type { KanbanOptions, Column, Card, FilterCriteria, BoardData, Label } from '../types';\nimport { resolveElement } from '../utils/dom';\nimport { EventEmitter, type EventHandler } from './EventEmitter';\nimport { ColumnManager } from './ColumnManager';\nimport { DragController } from './DragController';\nimport { FilterEngine } from './FilterEngine';\nimport { Renderer } from './Renderer';\nimport { VERSION } from '../version';\n\n/**\n * KanbanBoard - 看板视图库,支持拖拽卡片与列管理\n */\nexport class KanbanBoard {\n private container: HTMLElement;\n private options: KanbanOptions;\n private destroyed = false;\n\n readonly events: EventEmitter;\n private columnManager: ColumnManager;\n private dragController: DragController;\n private filterEngine: FilterEngine;\n private renderer: Renderer;\n private labels: Label[] = [];\n\n constructor(options: KanbanOptions) {\n this.options = {\n draggable: true,\n columnDraggable: true,\n crossColumnDrag: true,\n searchable: true,\n showAddCard: true,\n showAddColumn: true,\n showColumnActions: true,\n showCardCount: true,\n classPrefix: 'kanban',\n ...options,\n };\n\n const el = resolveElement(options.container);\n if (!el) {\n throw new Error('[KanbanBoard] Container element not found');\n }\n this.container = el;\n\n // 初始化子系统\n this.events = new EventEmitter();\n this.columnManager = new ColumnManager(this.events);\n this.dragController = new DragController(this.events, this.options.classPrefix || 'kanban');\n this.filterEngine = new FilterEngine(this.events);\n this.renderer = new Renderer(this.container, this.events, this.dragController, this.options);\n\n // 初始化标签\n this.labels = options.labels || [];\n\n this.init();\n }\n\n private init(): void {\n // 初始化列数据\n if (this.options.columns?.length) {\n this.columnManager.init(this.options.columns as Partial<Column>[]);\n }\n\n // 绑定内部事件\n this.bindInternalEvents();\n\n // 首次渲染\n this.render();\n\n // 触发 ready\n this.events.emit('ready', { instance: this });\n this.options.onReady?.(this);\n\n if (this.options.debug) {\n console.log('[KanbanBoard] Initialized', {\n columns: this.columnManager.getColumns().length,\n cards: this.columnManager.getCardCount(),\n });\n }\n }\n\n /**\n * 绑定内部事件\n */\n private bindInternalEvents(): void {\n // 卡片拖拽放置\n this.events.on('card:drop', (payload: unknown) => {\n this.columnManager.moveCard(payload.cardId, payload.toColumnId, payload.toIndex);\n this.options.onCardMove?.(this.columnManager.getCard(payload.cardId)!, payload.fromColumnId, payload.toColumnId, payload.toIndex);\n // 延迟渲染,等待浏览器完成拖拽操作(dragend 事件触发后再重建 DOM)\n this.scheduleRender();\n });\n\n // 列拖拽放置\n this.events.on('column:drop', (payload: unknown) => {\n const columns = this.columnManager.getColumns();\n const fromIndex = columns.findIndex(c => c.id === payload.fromColumnId);\n this.columnManager.moveColumn(payload.fromColumnId, payload.toIndex);\n const col = this.columnManager.getColumn(payload.fromColumnId);\n if (col) this.options.onColumnMove?.(col, fromIndex, payload.toIndex);\n this.scheduleRender();\n });\n\n // UI 事件 - 折叠列\n this.events.on('ui:toggle-collapse', (payload: unknown) => {\n this.columnManager.toggleCollapse(payload.columnId);\n const col = this.columnManager.getColumn(payload.columnId);\n if (col) this.options.onColumnCollapse?.(col, col.collapsed ?? false);\n this.render();\n });\n\n // 回调转发\n this.events.on('card:add', (p: unknown) => this.options.onCardAdd?.(p.card, p.columnId));\n this.events.on('card:remove', (p: unknown) => this.options.onCardRemove?.(p.card, p.columnId));\n this.events.on('card:click', (p: unknown) => this.options.onCardClick?.(p.card));\n this.events.on('card:update', (p: unknown) => this.options.onCardUpdate?.(p.card));\n this.events.on('column:add', (p: unknown) => this.options.onColumnAdd?.(p.column));\n this.events.on('column:remove', (p: unknown) => this.options.onColumnRemove?.(p.column));\n this.events.on('error', (p: unknown) => this.options.onError?.(p.error));\n }\n\n // ============================================================\n // Column API\n // ============================================================\n\n /**\n * 添加列\n */\n addColumn(partial: Partial<Column>): Column {\n const column = this.columnManager.addColumn(partial);\n this.render();\n return column;\n }\n\n /**\n * 移除列\n */\n removeColumn(id: string): Column | undefined {\n const column = this.columnManager.removeColumn(id);\n if (column) this.render();\n return column;\n }\n\n /**\n * 更新列\n */\n updateColumn(id: string, changes: Partial<Column>): Column | undefined {\n const column = this.columnManager.updateColumn(id, changes);\n if (column) this.render();\n return column;\n }\n\n /**\n * 移动列\n */\n moveColumn(id: string, toIndex: number): void {\n this.columnManager.moveColumn(id, toIndex);\n this.render();\n }\n\n /**\n * 折叠/展开列\n */\n toggleColumnCollapse(id: string): void {\n this.columnManager.toggleCollapse(id);\n this.render();\n }\n\n /**\n * 获取所有列\n */\n getColumns(): Column[] {\n return this.columnManager.getColumns();\n }\n\n /**\n * 获取单列\n */\n getColumn(id: string): Column | undefined {\n return this.columnManager.getColumn(id);\n }\n\n // ============================================================\n // Card API\n // ============================================================\n\n /**\n * 添加卡片\n */\n addCard(columnId: string, partial: Partial<Card>): Card | undefined {\n const card = this.columnManager.addCard(columnId, partial);\n if (card) this.render();\n return card;\n }\n\n /**\n * 移除卡片\n */\n removeCard(cardId: string): Card | undefined {\n const card = this.columnManager.removeCard(cardId);\n if (card) this.render();\n return card;\n }\n\n /**\n * 更新卡片\n */\n updateCard(cardId: string, changes: Partial<Card>): Card | undefined {\n const card = this.columnManager.updateCard(cardId, changes);\n if (card) this.render();\n return card;\n }\n\n /**\n * 移动卡片\n */\n moveCard(cardId: string, toColumnId: string, toIndex: number): void {\n this.columnManager.moveCard(cardId, toColumnId, toIndex);\n this.render();\n }\n\n /**\n * 获取单张卡片\n */\n getCard(cardId: string): Card | undefined {\n return this.columnManager.getCard(cardId);\n }\n\n /**\n * 获取所有卡片\n */\n getAllCards(): Card[] {\n return this.columnManager.getAllCards();\n }\n\n /**\n * 获取卡片总数\n */\n getCardCount(): number {\n return this.columnManager.getCardCount();\n }\n\n // ============================================================\n // Filter / Search API\n // ============================================================\n\n /**\n * 筛选卡片\n */\n filter(criteria: FilterCriteria): void {\n this.filterEngine.filter(criteria, this.columnManager.getColumns());\n this.render();\n }\n\n /**\n * 搜索卡片\n */\n search(keyword: string): Card[] {\n const result = this.filterEngine.search(keyword, this.columnManager.getColumns());\n this.render();\n return result;\n }\n\n /**\n * 清除筛选\n */\n clearFilter(): void {\n this.filterEngine.clearFilter();\n this.render();\n }\n\n // ============================================================\n // Import / Export API\n // ============================================================\n\n /**\n * 导出看板数据\n */\n exportData(): BoardData {\n const data: BoardData = {\n version: VERSION,\n title: this.options.title || 'Kanban Board',\n columns: this.columnManager.getColumns(),\n labels: this.labels,\n exportedAt: new Date().toISOString(),\n };\n this.events.emit('data:export', { board: data });\n return data;\n }\n\n /**\n * 导入看板数据\n */\n importData(data: BoardData): void {\n this.columnManager.setColumns(data.columns);\n this.labels = data.labels || [];\n this.filterEngine.clearFilter();\n this.events.emit('data:import', { board: data });\n this.render();\n }\n\n // ============================================================\n // Event API\n // ============================================================\n\n /**\n * 监听事件\n */\n on(event: string, handler: EventHandler): () => void {\n return this.events.on(event, handler);\n }\n\n /**\n * 监听一次性事件\n */\n once(event: string, handler: EventHandler): () => void {\n return this.events.once(event, handler);\n }\n\n /**\n * 移除事件监听\n */\n off(event: string, handler: EventHandler): void {\n this.events.off(event, handler);\n }\n\n // ============================================================\n // Label API\n // ============================================================\n\n /**\n * 获取所有标签\n */\n getLabels(): Label[] {\n return [...this.labels];\n }\n\n /**\n * 添加标签\n */\n addLabel(label: Label): void {\n this.labels.push(label);\n }\n\n /**\n * 移除标签\n */\n removeLabel(id: string): void {\n this.labels = this.labels.filter(l => l.id !== id);\n }\n\n // ============================================================\n // Render\n // ============================================================\n\n private renderTimer: ReturnType<typeof setTimeout> | null = null;\n\n /**\n * 延迟渲染(合并多次调用,等待浏览器拖拽操作完成)\n */\n private scheduleRender(): void {\n if (this.renderTimer !== null) return;\n this.renderTimer = setTimeout(() => {\n this.renderTimer = null;\n this.render();\n }, 0);\n }\n\n /**\n * 重新渲染\n */\n render(): void {\n if (this.destroyed) return;\n this.dragController.destroy();\n this.dragController = new DragController(this.events, this.options.classPrefix || 'kanban');\n this.renderer = new Renderer(this.container, this.events, this.dragController, this.options);\n this.renderer.render(\n this.columnManager.getColumns(),\n this.filterEngine.getHiddenCardIds(),\n );\n }\n\n /**\n * 获取看板根元素\n */\n getBoardElement(): HTMLElement | null {\n return this.renderer.getBoardElement();\n }\n\n /**\n * 获取配置\n */\n getOptions(): Readonly<KanbanOptions> {\n return { ...this.options };\n }\n\n // ============================================================\n // Lifecycle\n // ============================================================\n\n /**\n * 销毁实例\n */\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n if (this.renderTimer !== null) {\n clearTimeout(this.renderTimer);\n this.renderTimer = null;\n }\n\n this.dragController.destroy();\n this.filterEngine.destroy();\n this.renderer.destroy();\n this.columnManager.clear();\n\n this.events.emit('destroy', undefined);\n this.options.onDestroy?.();\n this.events.removeAll();\n\n if (this.options.debug) {\n console.log('[KanbanBoard] Destroyed');\n }\n }\n\n /**\n * 是否已销毁\n */\n isDestroyed(): boolean {\n return this.destroyed;\n }\n}\n\n/**\n * 创建看板实例(工厂函数)\n */\nexport function createKanbanBoard(options: KanbanOptions): KanbanBoard {\n return new KanbanBoard(options);\n}\n","/**\n * @file index.ts\n * @description index 模块\n */\n\n/**\n * Utility functions for @composy/kanban-core\n */\n\nexport { generateId, resetIdCounter } from './id';\nexport { createElement, resolveElement, clearElement, removeElement, insertAt } from './dom';\n\n/**\n * Get element from selector or element\n * @deprecated Use resolveElement instead\n */\n/**\n * getElement 函数\n * @param target - 参数\n * @returns 返回值\n */\n/**\n * getElement - get Element function\n * @param target - 参数说明\n * @returns 返回值说明\n */\nexport function getElement(target: HTMLElement | string): HTMLElement | null {\n if (typeof target === 'string') {\n return document.querySelector(target);\n }\n return target;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/utils/id.ts","../src/core/ColumnManager.ts","../src/core/DragController.ts","../src/core/EventEmitter.ts","../src/core/FilterEngine.ts","../src/utils/dom.ts","../src/version.ts","../src/core/Renderer.ts","../src/core/KanbanBoard.ts","../src/utils/index.ts"],"sourcesContent":["let counter = 0\r\n\r\n/**\r\n * 生成唯一 ID\r\n */\r\nexport function generateId(prefix = 'kb'): string {\r\n counter++\r\n const timestamp = Date.now().toString(36)\r\n const random = Math.random().toString(36).substring(2, 6)\r\n return `${prefix}_${timestamp}_${random}_${counter}`\r\n}\r\n\r\n/**\r\n * 重置计数器(仅测试用)\r\n */\r\nexport function resetIdCounter(): void {\r\n counter = 0\r\n}\r\n","import type { Card, Column } from '../types'\r\nimport type { EventEmitter } from './EventEmitter'\r\nimport { generateId } from '../utils/id'\r\n\r\n/**\r\n * 列管理器\r\n */\r\nexport class ColumnManager {\r\n private columns: Column[] = []\r\n private events: EventEmitter\r\n\r\n constructor(events: EventEmitter) {\r\n this.events = events\r\n }\r\n\r\n /**\r\n * 初始化列\r\n */\r\n init(columns: Partial<Column>[]): void {\r\n this.columns = columns.map((col, index) => this.normalizeColumn(col, index))\r\n this.sortColumns()\r\n }\r\n\r\n /**\r\n * 标准化列数据\r\n */\r\n private normalizeColumn(partial: Partial<Column>, index: number): Column {\r\n const id = partial.id || generateId('col')\r\n const cards = (partial.cards ?? []).map((card, cardIndex) =>\r\n this.normalizeCard({ ...card, columnId: id }, id, cardIndex)\r\n )\r\n cards.sort((a, b) => a.order - b.order)\r\n cards.forEach((card, cardIndex) => {\r\n card.order = cardIndex\r\n })\r\n return {\r\n id,\r\n title: partial.title ?? `Column ${index + 1}`,\r\n cards,\r\n wipLimit: partial.wipLimit,\r\n collapsed: partial.collapsed ?? false,\r\n color: partial.color,\r\n order: partial.order ?? index,\r\n }\r\n }\r\n\r\n /**\r\n * 标准化卡片数据\r\n */\r\n private normalizeCard(\r\n partial: Partial<Card>,\r\n columnId: string,\r\n index: number\r\n ): Card {\r\n const id = partial.id || generateId('card')\r\n return {\r\n id,\r\n title: partial.title ?? '',\r\n description: partial.description,\r\n labels: partial.labels?.map(label => ({ ...label })) ?? [],\r\n assignees: partial.assignees ? [...partial.assignees] : [],\r\n dueDate: partial.dueDate,\r\n priority: partial.priority,\r\n order: partial.order ?? index,\r\n columnId: partial.columnId ?? columnId,\r\n data: partial.data,\r\n createdAt: partial.createdAt ?? new Date().toISOString(),\r\n updatedAt: partial.updatedAt,\r\n }\r\n }\r\n\r\n /**\r\n * 获取所有列\r\n */\r\n getColumns(): Column[] {\r\n return [...this.columns].sort((a, b) => a.order - b.order)\r\n }\r\n\r\n /**\r\n * 获取单列\r\n */\r\n getColumn(id: string): Column | undefined {\r\n return this.columns.find(c => c.id === id)\r\n }\r\n\r\n /**\r\n * 添加列\r\n */\r\n addColumn(partial: Partial<Column>): Column {\r\n const column = this.normalizeColumn(partial, this.columns.length)\r\n this.columns.push(column)\r\n this.sortColumns()\r\n this.events.emit('column:add', { column })\r\n return column\r\n }\r\n\r\n /**\r\n * 移除列\r\n */\r\n removeColumn(id: string): Column | undefined {\r\n const index = this.columns.findIndex(c => c.id === id)\r\n if (index === -1) return undefined\r\n const [column] = this.columns.splice(index, 1)\r\n this.reorderColumns()\r\n this.events.emit('column:remove', { column })\r\n return column\r\n }\r\n\r\n /**\r\n * 更新列\r\n */\r\n updateColumn(id: string, changes: Partial<Column>): Column | undefined {\r\n const column = this.columns.find(c => c.id === id)\r\n if (!column) return undefined\r\n Object.assign(column, changes, { id }) // 不允许更改 id\r\n if (changes.cards) {\r\n column.cards = changes.cards.map((card, index) =>\r\n this.normalizeCard(card, id, index)\r\n )\r\n column.cards.sort((a, b) => a.order - b.order)\r\n this.reorderCards(column)\r\n }\r\n if (changes.order !== undefined) this.sortColumns()\r\n this.events.emit('column:update', { column, changes })\r\n return column\r\n }\r\n\r\n /**\r\n * 移动列\r\n */\r\n moveColumn(id: string, toIndex: number): void {\r\n this.sortColumns()\r\n const fromIndex = this.columns.findIndex(c => c.id === id)\r\n if (fromIndex === -1) return\r\n const [column] = this.columns.splice(fromIndex, 1)\r\n const targetIndex = this.clampIndex(toIndex, this.columns.length)\r\n this.columns.splice(targetIndex, 0, column)\r\n this.reorderColumns()\r\n this.events.emit('column:move', { column, fromIndex, toIndex: targetIndex })\r\n }\r\n\r\n /**\r\n * 折叠/展开列\r\n */\r\n toggleCollapse(id: string): void {\r\n const column = this.columns.find(c => c.id === id)\r\n if (!column) return\r\n column.collapsed = !column.collapsed\r\n this.events.emit('column:collapse', { column, collapsed: column.collapsed })\r\n }\r\n\r\n /**\r\n * 获取列中的卡片\r\n */\r\n getCards(columnId: string): Card[] {\r\n const column = this.columns.find(c => c.id === columnId)\r\n return column ? [...column.cards].sort((a, b) => a.order - b.order) : []\r\n }\r\n\r\n /**\r\n * 添加卡片到列\r\n */\r\n addCard(columnId: string, partial: Partial<Card>): Card | undefined {\r\n const column = this.columns.find(c => c.id === columnId)\r\n if (!column) return undefined\r\n\r\n // 检查 WIP 限制\r\n if (column.wipLimit && column.cards.length >= column.wipLimit) {\r\n this.events.emit('error', {\r\n error: new Error(\r\n `Column \"${column.title}\" reached WIP limit (${column.wipLimit})`\r\n ),\r\n })\r\n return undefined\r\n }\r\n\r\n const card = this.normalizeCard(\r\n { ...partial, columnId },\r\n columnId,\r\n column.cards.length\r\n )\r\n column.cards.push(card)\r\n this.events.emit('card:add', { card, columnId })\r\n return card\r\n }\r\n\r\n /**\r\n * 移除卡片\r\n */\r\n removeCard(cardId: string): Card | undefined {\r\n for (const column of this.columns) {\r\n const index = column.cards.findIndex(c => c.id === cardId)\r\n if (index !== -1) {\r\n const [card] = column.cards.splice(index, 1)\r\n this.reorderCards(column)\r\n this.events.emit('card:remove', { card, columnId: column.id })\r\n return card\r\n }\r\n }\r\n return undefined\r\n }\r\n\r\n /**\r\n * 更新卡片\r\n */\r\n updateCard(cardId: string, changes: Partial<Card>): Card | undefined {\r\n for (const column of this.columns) {\r\n const card = column.cards.find(c => c.id === cardId)\r\n if (card) {\r\n Object.assign(card, changes, { id: cardId, columnId: column.id })\r\n card.updatedAt = new Date().toISOString()\r\n this.events.emit('card:update', { card, changes })\r\n return card\r\n }\r\n }\r\n return undefined\r\n }\r\n\r\n /**\r\n * 获取单张卡片\r\n */\r\n getCard(cardId: string): Card | undefined {\r\n for (const column of this.columns) {\r\n const card = column.cards.find(c => c.id === cardId)\r\n if (card) return card\r\n }\r\n return undefined\r\n }\r\n\r\n /**\r\n * 移动卡片\r\n */\r\n moveCard(cardId: string, toColumnId: string, toIndex: number): void {\r\n let fromColumn: Column | undefined\r\n let cardIndex = -1\r\n\r\n for (const column of this.columns) {\r\n const idx = column.cards.findIndex(c => c.id === cardId)\r\n if (idx !== -1) {\r\n fromColumn = column\r\n cardIndex = idx\r\n break\r\n }\r\n }\r\n\r\n if (!fromColumn || cardIndex === -1) return\r\n\r\n const toColumn = this.columns.find(c => c.id === toColumnId)\r\n if (!toColumn) return\r\n\r\n // 检查 WIP 限制(跨列移动时)\r\n if (\r\n fromColumn.id !== toColumnId &&\r\n toColumn.wipLimit &&\r\n toColumn.cards.length >= toColumn.wipLimit\r\n ) {\r\n this.events.emit('error', {\r\n error: new Error(\r\n `Column \"${toColumn.title}\" reached WIP limit (${toColumn.wipLimit})`\r\n ),\r\n })\r\n return\r\n }\r\n\r\n const [card] = fromColumn.cards.splice(cardIndex, 1)\r\n card.columnId = toColumnId\r\n const targetIndex = this.clampIndex(toIndex, toColumn.cards.length)\r\n toColumn.cards.splice(targetIndex, 0, card)\r\n\r\n this.reorderCards(fromColumn)\r\n this.reorderCards(toColumn)\r\n\r\n this.events.emit('card:move', {\r\n card,\r\n fromColumnId: fromColumn.id,\r\n toColumnId,\r\n toIndex: targetIndex,\r\n })\r\n }\r\n\r\n /**\r\n * 获取所有卡片\r\n */\r\n getAllCards(): Card[] {\r\n const cards: Card[] = []\r\n for (const column of this.columns) {\r\n cards.push(...column.cards)\r\n }\r\n return cards\r\n }\r\n\r\n /**\r\n * 获取卡片总数\r\n */\r\n getCardCount(): number {\r\n return this.columns.reduce((sum, col) => sum + col.cards.length, 0)\r\n }\r\n\r\n /**\r\n * 重新排序列\r\n */\r\n private reorderColumns(): void {\r\n this.columns.forEach((col, index) => {\r\n col.order = index\r\n })\r\n }\r\n\r\n /**\r\n * 重新排序列中的卡片\r\n */\r\n private reorderCards(column: Column): void {\r\n column.cards.forEach((card, index) => {\r\n card.order = index\r\n })\r\n }\r\n\r\n /**\r\n * 设置列数据(用于导入)\r\n */\r\n setColumns(columns: Column[]): void {\r\n this.columns = columns.map((column, index) =>\r\n this.normalizeColumn(column, index)\r\n )\r\n this.sortColumns()\r\n }\r\n\r\n /**\r\n * 清空所有数据\r\n */\r\n clear(): void {\r\n this.columns = []\r\n }\r\n\r\n private clampIndex(index: number, length: number): number {\r\n if (!Number.isFinite(index)) return length\r\n return Math.min(Math.max(Math.trunc(index), 0), length)\r\n }\r\n\r\n private sortColumns(): void {\r\n this.columns.sort((a, b) => a.order - b.order)\r\n this.reorderColumns()\r\n }\r\n}\r\n","import type { EventEmitter } from './EventEmitter'\r\n\r\n/**\r\n * DragState - Drag State interface\r\n */\r\nexport interface DragState {\r\n dragging: boolean\r\n cardId: string | null\r\n sourceColumnId: string | null\r\n targetColumnId: string | null\r\n targetIndex: number\r\n placeholder: HTMLElement | null\r\n}\r\n\r\n/**\r\n * 拖拽控制器 - HTML5 Drag & Drop API\r\n */\r\nexport class DragController {\r\n private events: EventEmitter\r\n private state: DragState = {\r\n dragging: false,\r\n cardId: null,\r\n sourceColumnId: null,\r\n targetColumnId: null,\r\n targetIndex: 0,\r\n placeholder: null,\r\n }\r\n private prefix: string\r\n private cleanupFns: (() => void)[] = []\r\n\r\n constructor(events: EventEmitter, prefix: string) {\r\n this.events = events\r\n this.prefix = prefix\r\n }\r\n\r\n /**\r\n * 为卡片元素启用拖拽\r\n */\r\n enableCardDrag(cardEl: HTMLElement, cardId: string, columnId: string): void {\r\n cardEl.setAttribute('draggable', 'true')\r\n cardEl.dataset.cardId = cardId\r\n cardEl.dataset.columnId = columnId\r\n\r\n const onDragStart = (e: DragEvent) => {\r\n if (!e.dataTransfer) return\r\n e.dataTransfer.effectAllowed = 'move'\r\n e.dataTransfer.setData('text/plain', cardId)\r\n\r\n this.state.dragging = true\r\n this.state.cardId = cardId\r\n this.state.sourceColumnId = columnId\r\n this.state.targetColumnId = columnId\r\n this.state.targetIndex = 0\r\n\r\n cardEl.classList.add(`${this.prefix}-card--dragging`)\r\n this.events.emit('card:drag-start', { cardId, columnId })\r\n\r\n // 创建占位符\r\n this.createPlaceholder(cardEl)\r\n }\r\n\r\n const onDragEnd = () => {\r\n cardEl.classList.remove(`${this.prefix}-card--dragging`)\r\n this.removePlaceholder()\r\n this.state.dragging = false\r\n this.state.cardId = null\r\n this.state.sourceColumnId = null\r\n this.state.targetColumnId = null\r\n this.state.targetIndex = 0\r\n this.events.emit('card:drag-end', { cardId })\r\n }\r\n\r\n cardEl.addEventListener('dragstart', onDragStart)\r\n cardEl.addEventListener('dragend', onDragEnd)\r\n\r\n this.cleanupFns.push(() => {\r\n cardEl.removeEventListener('dragstart', onDragStart)\r\n cardEl.removeEventListener('dragend', onDragEnd)\r\n })\r\n }\r\n\r\n /**\r\n * 为列容器启用拖拽接受\r\n */\r\n enableColumnDrop(columnBodyEl: HTMLElement, columnId: string): void {\r\n const onDragOver = (e: DragEvent) => {\r\n e.preventDefault()\r\n if (!e.dataTransfer) return\r\n e.dataTransfer.dropEffect = 'move'\r\n\r\n this.state.targetColumnId = columnId\r\n\r\n // 计算插入位置\r\n const afterElement = this.getDragAfterElement(columnBodyEl, e.clientY)\r\n const placeholder = this.state.placeholder\r\n if (placeholder) {\r\n if (afterElement) {\r\n columnBodyEl.insertBefore(placeholder, afterElement)\r\n } else {\r\n // 插入到最后一张卡片之后,但在“添加卡片”按钮之前\r\n const addBtn = columnBodyEl.querySelector(`.${this.prefix}-add-card`)\r\n if (addBtn) {\r\n columnBodyEl.insertBefore(placeholder, addBtn)\r\n } else {\r\n columnBodyEl.appendChild(placeholder)\r\n }\r\n }\r\n }\r\n }\r\n\r\n const onDragEnter = (e: DragEvent) => {\r\n e.preventDefault()\r\n columnBodyEl.classList.add(`${this.prefix}-column-body--drag-over`)\r\n }\r\n\r\n const onDragLeave = (e: DragEvent) => {\r\n // 检查是否真的离开了列\r\n const rect = columnBodyEl.getBoundingClientRect()\r\n if (\r\n e.clientX < rect.left ||\r\n e.clientX > rect.right ||\r\n e.clientY < rect.top ||\r\n e.clientY > rect.bottom\r\n ) {\r\n columnBodyEl.classList.remove(`${this.prefix}-column-body--drag-over`)\r\n }\r\n }\r\n\r\n const onDrop = (e: DragEvent) => {\r\n e.preventDefault()\r\n columnBodyEl.classList.remove(`${this.prefix}-column-body--drag-over`)\r\n\r\n const cardId = this.state.cardId\r\n if (!cardId) return\r\n\r\n // 计算 drop 位置:只统计占位符前面的可见卡片数量\r\n const placeholder = this.state.placeholder\r\n let dropIndex = 0\r\n\r\n if (placeholder && placeholder.parentNode === columnBodyEl) {\r\n const children = [...columnBodyEl.children]\r\n for (const child of children) {\r\n if (child === placeholder) break\r\n if (\r\n (child as HTMLElement).hasAttribute('data-card-id') &&\r\n !(child as HTMLElement).classList.contains(\r\n `${this.prefix}-card--dragging`\r\n )\r\n ) {\r\n dropIndex++\r\n }\r\n }\r\n } else {\r\n // 占位符不在当前列时,放到末尾\r\n const cards = columnBodyEl.querySelectorAll(\r\n `[data-card-id]:not(.${this.prefix}-card--dragging)`\r\n )\r\n dropIndex = cards.length\r\n }\r\n\r\n this.state.targetIndex = dropIndex\r\n\r\n this.events.emit('card:drop', {\r\n cardId,\r\n fromColumnId: this.state.sourceColumnId,\r\n toColumnId: columnId,\r\n toIndex: dropIndex,\r\n })\r\n\r\n this.removePlaceholder()\r\n }\r\n\r\n columnBodyEl.addEventListener('dragover', onDragOver)\r\n columnBodyEl.addEventListener('dragenter', onDragEnter)\r\n columnBodyEl.addEventListener('dragleave', onDragLeave)\r\n columnBodyEl.addEventListener('drop', onDrop)\r\n\r\n this.cleanupFns.push(() => {\r\n columnBodyEl.removeEventListener('dragover', onDragOver)\r\n columnBodyEl.removeEventListener('dragenter', onDragEnter)\r\n columnBodyEl.removeEventListener('dragleave', onDragLeave)\r\n columnBodyEl.removeEventListener('drop', onDrop)\r\n })\r\n }\r\n\r\n /**\r\n * 为列头部启用列拖拽\r\n */\r\n enableColumnDrag(\r\n columnEl: HTMLElement,\r\n handleEl: HTMLElement,\r\n columnId: string,\r\n boardEl: HTMLElement\r\n ): void {\r\n handleEl.setAttribute('draggable', 'true')\r\n\r\n const onDragStart = (e: DragEvent) => {\r\n if (!e.dataTransfer) return\r\n e.dataTransfer.effectAllowed = 'move'\r\n e.dataTransfer.setData('application/kanban-column', columnId)\r\n columnEl.classList.add(`${this.prefix}-column--dragging`)\r\n }\r\n\r\n const onDragEnd = () => {\r\n columnEl.classList.remove(`${this.prefix}-column--dragging`)\r\n // 清除所有列的 drag-over 状态\r\n boardEl\r\n .querySelectorAll(`.${this.prefix}-column--drag-over`)\r\n .forEach(el => {\r\n el.classList.remove(`${this.prefix}-column--drag-over`)\r\n })\r\n }\r\n\r\n const onDragOver = (e: DragEvent) => {\r\n if (!e.dataTransfer?.types.includes('application/kanban-column')) return\r\n e.preventDefault()\r\n e.dataTransfer.dropEffect = 'move'\r\n columnEl.classList.add(`${this.prefix}-column--drag-over`)\r\n }\r\n\r\n const onDragLeave = () => {\r\n columnEl.classList.remove(`${this.prefix}-column--drag-over`)\r\n }\r\n\r\n const onDrop = (e: DragEvent) => {\r\n e.preventDefault()\r\n columnEl.classList.remove(`${this.prefix}-column--drag-over`)\r\n const fromColumnId = e.dataTransfer?.getData('application/kanban-column')\r\n if (!fromColumnId || fromColumnId === columnId) return\r\n\r\n // 计算目标位置\r\n const columns = [...boardEl.querySelectorAll(`[data-column-id]`)]\r\n const toIndex = columns.indexOf(columnEl)\r\n this.events.emit('column:drop', {\r\n fromColumnId,\r\n toColumnId: columnId,\r\n toIndex,\r\n })\r\n }\r\n\r\n handleEl.addEventListener('dragstart', onDragStart)\r\n handleEl.addEventListener('dragend', onDragEnd)\r\n columnEl.addEventListener('dragover', onDragOver)\r\n columnEl.addEventListener('dragleave', onDragLeave)\r\n columnEl.addEventListener('drop', onDrop)\r\n\r\n this.cleanupFns.push(() => {\r\n handleEl.removeEventListener('dragstart', onDragStart)\r\n handleEl.removeEventListener('dragend', onDragEnd)\r\n columnEl.removeEventListener('dragover', onDragOver)\r\n columnEl.removeEventListener('dragleave', onDragLeave)\r\n columnEl.removeEventListener('drop', onDrop)\r\n })\r\n }\r\n\r\n /**\r\n * 获取鼠标位置之后的元素\r\n */\r\n private getDragAfterElement(\r\n container: HTMLElement,\r\n y: number\r\n ): HTMLElement | null {\r\n const draggableElements = [\r\n ...container.querySelectorAll(\r\n `[data-card-id]:not(.${this.prefix}-card--dragging):not(.${this.prefix}-placeholder)`\r\n ),\r\n ] as HTMLElement[]\r\n\r\n let closestOffset = Number.NEGATIVE_INFINITY\r\n let closestElement: HTMLElement | null = null\r\n\r\n draggableElements.forEach(child => {\r\n const box = child.getBoundingClientRect()\r\n const offset = y - box.top - box.height / 2\r\n if (offset < 0 && offset > closestOffset) {\r\n closestOffset = offset\r\n closestElement = child\r\n }\r\n })\r\n\r\n return closestElement\r\n }\r\n\r\n /**\r\n * 创建占位符\r\n */\r\n private createPlaceholder(cardEl: HTMLElement): void {\r\n this.removePlaceholder()\r\n const placeholder = document.createElement('div')\r\n placeholder.className = `${this.prefix}-placeholder`\r\n placeholder.style.height = `${cardEl.offsetHeight}px`\r\n this.state.placeholder = placeholder\r\n }\r\n\r\n /**\r\n * 移除占位符\r\n */\r\n private removePlaceholder(): void {\r\n if (this.state.placeholder) {\r\n this.state.placeholder.parentNode?.removeChild(this.state.placeholder)\r\n this.state.placeholder = null\r\n }\r\n }\r\n\r\n /**\r\n * 获取当前拖拽状态\r\n */\r\n getState(): Readonly<DragState> {\r\n return { ...this.state }\r\n }\r\n\r\n /**\r\n * 销毁\r\n */\r\n destroy(): void {\r\n this.cleanupFns.forEach(fn => fn())\r\n this.cleanupFns = []\r\n this.removePlaceholder()\r\n this.state.dragging = false\r\n this.state.cardId = null\r\n this.state.sourceColumnId = null\r\n this.state.targetColumnId = null\r\n this.state.targetIndex = 0\r\n }\r\n}\r\n","/**\r\n * 轻量级事件发射器\r\n */\r\nexport type EventHandler = (...args: unknown[]) => void\r\n\r\n/**\r\n * EventEmitter - Event Emitter class\r\n */\r\nexport class EventEmitter {\r\n private listeners = new Map<string, Set<EventHandler>>()\r\n\r\n /**\r\n * 监听事件\r\n */\r\n on(event: string, handler: EventHandler): () => void {\r\n if (!this.listeners.has(event)) {\r\n this.listeners.set(event, new Set())\r\n }\r\n const handlers = this.listeners.get(event)\r\n if (!handlers) return () => this.off(event, handler)\r\n handlers.add(handler)\r\n return () => this.off(event, handler)\r\n }\r\n\r\n /**\r\n * 监听一次性事件\r\n */\r\n once(event: string, handler: EventHandler): () => void {\r\n const wrapper: EventHandler = (...args) => {\r\n this.off(event, wrapper)\r\n handler(...args)\r\n }\r\n return this.on(event, wrapper)\r\n }\r\n\r\n /**\r\n * 移除监听器\r\n */\r\n off(event: string, handler: EventHandler): void {\r\n const handlers = this.listeners.get(event)\r\n if (!handlers) return\r\n handlers.delete(handler)\r\n if (handlers.size === 0) this.listeners.delete(event)\r\n }\r\n\r\n /**\r\n * 触发事件\r\n */\r\n emit(event: string, payload?: unknown): void {\r\n const handlers = this.listeners.get(event)\r\n if (handlers) {\r\n handlers.forEach(handler => {\r\n try {\r\n handler(payload)\r\n } catch (err) {\r\n console.error(\r\n `[KanbanBoard] Error in event handler for \"${event}\":`,\r\n err\r\n )\r\n }\r\n })\r\n }\r\n }\r\n\r\n /**\r\n * 移除所有监听器\r\n */\r\n removeAll(): void {\r\n this.listeners.clear()\r\n }\r\n\r\n /**\r\n * 获取监听器数量\r\n */\r\n listenerCount(event: string): number {\r\n return this.listeners.get(event)?.size ?? 0\r\n }\r\n}\r\n","import type { Card, Column, FilterCriteria } from '../types'\r\nimport type { EventEmitter } from './EventEmitter'\r\n\r\n/**\r\n * 筛选/搜索引擎\r\n */\r\nexport class FilterEngine {\r\n private events: EventEmitter\r\n private currentCriteria: FilterCriteria | null = null\r\n /** 被过滤隐藏的卡片 ID 集合 */\r\n private hiddenCardIds = new Set<string>()\r\n\r\n constructor(events: EventEmitter) {\r\n this.events = events\r\n }\r\n\r\n /**\r\n * 应用筛选条件\r\n */\r\n filter(criteria: FilterCriteria, columns: Column[]): Set<string> {\r\n this.currentCriteria = criteria\r\n this.hiddenCardIds.clear()\r\n\r\n const allCards = columns.flatMap(col => col.cards)\r\n\r\n for (const card of allCards) {\r\n if (!this.matchCriteria(card, criteria)) {\r\n this.hiddenCardIds.add(card.id)\r\n }\r\n }\r\n\r\n this.events.emit('filter:change', { criteria })\r\n return new Set(this.hiddenCardIds)\r\n }\r\n\r\n /**\r\n * 搜索卡片\r\n */\r\n search(keyword: string, columns: Column[]): Card[] {\r\n this.events.emit('search:change', { keyword })\r\n const normalizedKeyword = keyword.trim()\r\n this.currentCriteria = normalizedKeyword\r\n ? { keyword: normalizedKeyword }\r\n : null\r\n\r\n if (!normalizedKeyword) {\r\n this.clearFilter()\r\n return columns.flatMap(col => col.cards)\r\n }\r\n\r\n const lowerKeyword = normalizedKeyword.toLowerCase()\r\n const allCards = columns.flatMap(col => col.cards)\r\n const matched: Card[] = []\r\n\r\n this.hiddenCardIds.clear()\r\n\r\n for (const card of allCards) {\r\n const titleMatch = card.title.toLowerCase().includes(lowerKeyword)\r\n const descMatch =\r\n card.description?.toLowerCase().includes(lowerKeyword) ?? false\r\n const labelMatch =\r\n card.labels?.some(l => l.name.toLowerCase().includes(lowerKeyword)) ??\r\n false\r\n const assigneeMatch =\r\n card.assignees?.some(a => a.toLowerCase().includes(lowerKeyword)) ??\r\n false\r\n\r\n if (titleMatch || descMatch || labelMatch || assigneeMatch) {\r\n matched.push(card)\r\n } else {\r\n this.hiddenCardIds.add(card.id)\r\n }\r\n }\r\n\r\n return matched\r\n }\r\n\r\n /**\r\n * 清除筛选\r\n */\r\n clearFilter(): void {\r\n this.currentCriteria = null\r\n this.hiddenCardIds.clear()\r\n this.events.emit('filter:clear', undefined)\r\n }\r\n\r\n /**\r\n * 检查卡片是否可见\r\n */\r\n isCardVisible(cardId: string): boolean {\r\n return !this.hiddenCardIds.has(cardId)\r\n }\r\n\r\n /**\r\n * 获取隐藏的卡片 ID 集合\r\n */\r\n getHiddenCardIds(): Set<string> {\r\n return new Set(this.hiddenCardIds)\r\n }\r\n\r\n /**\r\n * 获取当前筛选条件\r\n */\r\n getCurrentCriteria(): FilterCriteria | null {\r\n return this.currentCriteria\r\n }\r\n\r\n /**\r\n * 匹配筛选条件\r\n */\r\n private matchCriteria(card: Card, criteria: FilterCriteria): boolean {\r\n // 关键词\r\n if (criteria.keyword) {\r\n const kw = criteria.keyword.toLowerCase()\r\n const titleMatch = card.title.toLowerCase().includes(kw)\r\n const descMatch = card.description?.toLowerCase().includes(kw) ?? false\r\n if (!titleMatch && !descMatch) return false\r\n }\r\n\r\n // 标签\r\n if (criteria.labelIds?.length) {\r\n const cardLabelIds = card.labels?.map(l => l.id) ?? []\r\n if (!criteria.labelIds.some(id => cardLabelIds.includes(id))) return false\r\n }\r\n\r\n // 成员\r\n if (criteria.assignees?.length) {\r\n if (!criteria.assignees.some(a => card.assignees?.includes(a)))\r\n return false\r\n }\r\n\r\n // 优先级\r\n if (criteria.priorities?.length) {\r\n if (!card.priority || !criteria.priorities.includes(card.priority))\r\n return false\r\n }\r\n\r\n // 列\r\n if (criteria.columnIds?.length) {\r\n if (!criteria.columnIds.includes(card.columnId)) return false\r\n }\r\n\r\n // 截止日期\r\n if (criteria.dueDateRange) {\r\n if (!card.dueDate) return false\r\n const dueDate = new Date(card.dueDate).getTime()\r\n if (Number.isNaN(dueDate)) return false\r\n if (criteria.dueDateRange.start) {\r\n const start = new Date(criteria.dueDateRange.start).getTime()\r\n if (Number.isNaN(start) || dueDate < start) return false\r\n }\r\n if (criteria.dueDateRange.end) {\r\n const end = new Date(criteria.dueDateRange.end).getTime()\r\n if (Number.isNaN(end) || dueDate > end) return false\r\n }\r\n }\r\n\r\n // 自定义函数\r\n if (criteria.custom) {\r\n if (!criteria.custom(card)) return false\r\n }\r\n\r\n return true\r\n }\r\n\r\n /**\r\n * 销毁\r\n */\r\n destroy(): void {\r\n this.hiddenCardIds.clear()\r\n this.currentCriteria = null\r\n }\r\n}\r\n","/**\r\n * DOM 工具函数\r\n */\r\n\r\n/**\r\n * 创建 DOM 元素\r\n */\r\nexport function createElement<K extends keyof HTMLElementTagNameMap>(\r\n tag: K,\r\n className?: string,\r\n attributes?: Record<string, string>\r\n): HTMLElementTagNameMap[K] {\r\n const el = document.createElement(tag)\r\n if (className) el.className = className\r\n if (attributes) {\r\n Object.entries(attributes).forEach(([key, value]) => {\r\n el.setAttribute(key, value)\r\n })\r\n }\r\n return el\r\n}\r\n\r\n/**\r\n * 从选择器或元素获取 HTMLElement\r\n */\r\nexport function resolveElement(\r\n target: HTMLElement | string\r\n): HTMLElement | null {\r\n if (typeof target === 'string') {\r\n return document.querySelector(target)\r\n }\r\n return target\r\n}\r\n\r\n/**\r\n * 清空元素内容\r\n */\r\nexport function clearElement(el: HTMLElement): void {\r\n el.innerHTML = ''\r\n}\r\n\r\n/**\r\n * 安全移除元素\r\n */\r\nexport function removeElement(el: HTMLElement | null): void {\r\n el?.parentNode?.removeChild(el)\r\n}\r\n\r\n/**\r\n * 插入元素到指定位置\r\n */\r\nexport function insertAt(\r\n parent: HTMLElement,\r\n child: HTMLElement,\r\n index: number\r\n): void {\r\n const ref = parent.children[index] as HTMLElement | undefined\r\n if (ref) {\r\n parent.insertBefore(child, ref)\r\n } else {\r\n parent.appendChild(child)\r\n }\r\n}\r\n","/**\r\n * @file version.ts\r\n * @description version 模块\r\n */\r\n\r\nexport const VERSION = '0.1.0'\r\n","import type { Card, Column, KanbanOptions } from '../types'\r\nimport type { DragController } from './DragController'\r\nimport type { EventEmitter } from './EventEmitter'\r\nimport { createElement } from '../utils/dom'\r\n\r\n/**\r\n * DOM 渲染器\r\n */\r\nexport class Renderer {\r\n private container: HTMLElement\r\n private boardEl: HTMLElement | null = null\r\n private events: EventEmitter\r\n private dragController: DragController\r\n private options: KanbanOptions\r\n private prefix: string\r\n private columnElements = new Map<string, HTMLElement>()\r\n private columnBodyElements = new Map<string, HTMLElement>()\r\n private cardElements = new Map<string, HTMLElement>()\r\n\r\n constructor(\r\n container: HTMLElement,\r\n events: EventEmitter,\r\n dragController: DragController,\r\n options: KanbanOptions\r\n ) {\r\n this.container = container\r\n this.events = events\r\n this.dragController = dragController\r\n this.options = options\r\n this.prefix = options.classPrefix || 'kanban'\r\n }\r\n\r\n /**\r\n * 渲染整个看板\r\n */\r\n render(columns: Column[], hiddenCardIds?: Set<string>): void {\r\n this.cleanup()\r\n\r\n // 清除容器中残留的旧看板元素(HMR / 重复渲染保护)\r\n const staleBoards = this.container.querySelectorAll('[data-kanban-board]')\r\n staleBoards.forEach(el => el.remove())\r\n\r\n const p = this.prefix\r\n this.boardEl = createElement('div', `${p}-board`)\r\n this.boardEl.setAttribute('data-kanban-board', '')\r\n\r\n // 列容器\r\n const columnsContainer = createElement('div', `${p}-columns`)\r\n\r\n for (const column of columns) {\r\n const colEl = this.renderColumn(column, hiddenCardIds)\r\n columnsContainer.appendChild(colEl)\r\n }\r\n\r\n // 添加列按钮\r\n if (this.options.showAddColumn !== false) {\r\n const addColBtn = createElement('div', `${p}-add-column`)\r\n addColBtn.innerHTML = `<button class=\"${p}-add-column-btn\">+ 添加列</button>`\r\n addColBtn\r\n .querySelector<HTMLButtonElement>('button')\r\n ?.addEventListener('click', () => {\r\n this.events.emit('ui:add-column')\r\n })\r\n columnsContainer.appendChild(addColBtn)\r\n }\r\n\r\n this.boardEl.appendChild(columnsContainer)\r\n this.container.appendChild(this.boardEl)\r\n }\r\n\r\n /**\r\n * 渲染单个列\r\n */\r\n private renderColumn(\r\n column: Column,\r\n hiddenCardIds?: Set<string>\r\n ): HTMLElement {\r\n const p = this.prefix\r\n const colEl = createElement('div', `${p}-column`, {\r\n 'data-column-id': column.id,\r\n })\r\n if (column.collapsed) colEl.classList.add(`${p}-column--collapsed`)\r\n\r\n // 列头部\r\n const header = this.renderColumnHeader(column)\r\n colEl.appendChild(header)\r\n\r\n // 列内容\r\n const body = createElement('div', `${p}-column-body`)\r\n body.dataset.columnId = column.id\r\n\r\n if (!column.collapsed) {\r\n const visibleCards = column.cards\r\n .filter(card => !hiddenCardIds || !hiddenCardIds.has(card.id))\r\n .sort((a, b) => a.order - b.order)\r\n\r\n for (const card of visibleCards) {\r\n const cardEl = this.renderCard(card, column.id)\r\n body.appendChild(cardEl)\r\n }\r\n\r\n // 添加卡片按钮\r\n if (this.options.showAddCard !== false) {\r\n const addBtn = createElement('div', `${p}-add-card`)\r\n addBtn.innerHTML = `<button class=\"${p}-add-card-btn\">+ 添加卡片</button>`\r\n addBtn\r\n .querySelector<HTMLButtonElement>('button')\r\n ?.addEventListener('click', () => {\r\n this.events.emit('ui:add-card', { columnId: column.id })\r\n })\r\n body.appendChild(addBtn)\r\n }\r\n\r\n // 启用列内拖拽放置\r\n if (this.options.draggable !== false) {\r\n this.dragController.enableColumnDrop(body, column.id)\r\n }\r\n }\r\n\r\n colEl.appendChild(body)\r\n\r\n // 列拖拽\r\n const boardEl = this.boardEl\r\n if (this.options.columnDraggable !== false && boardEl) {\r\n const dragHandle = header.querySelector(\r\n `.${p}-column-drag-handle`\r\n ) as HTMLElement\r\n if (dragHandle) {\r\n this.dragController.enableColumnDrag(\r\n colEl,\r\n dragHandle,\r\n column.id,\r\n boardEl\r\n )\r\n }\r\n }\r\n\r\n this.columnElements.set(column.id, colEl)\r\n this.columnBodyElements.set(column.id, body)\r\n\r\n return colEl\r\n }\r\n\r\n /**\r\n * 渲染列头部\r\n */\r\n private renderColumnHeader(column: Column): HTMLElement {\r\n const p = this.prefix\r\n const header = createElement('div', `${p}-column-header`)\r\n\r\n if (this.options.columnHeaderRenderer) {\r\n this.options.columnHeaderRenderer(column, header)\r\n return header\r\n }\r\n\r\n // 拖拽手柄\r\n if (this.options.columnDraggable !== false) {\r\n const handle = createElement('span', `${p}-column-drag-handle`)\r\n handle.innerHTML = '⋮⋮'\r\n handle.title = '拖拽排序'\r\n header.appendChild(handle)\r\n }\r\n\r\n // 颜色指示器\r\n if (column.color) {\r\n const indicator = createElement('span', `${p}-column-color`)\r\n indicator.style.backgroundColor = column.color\r\n header.appendChild(indicator)\r\n }\r\n\r\n // 标题\r\n const titleEl = createElement('span', `${p}-column-title`)\r\n titleEl.textContent = column.title\r\n header.appendChild(titleEl)\r\n\r\n // 卡片计数\r\n if (this.options.showCardCount !== false) {\r\n const count = createElement('span', `${p}-column-count`)\r\n const wipText = column.wipLimit ? `/${column.wipLimit}` : ''\r\n count.textContent = `${column.cards.length}${wipText}`\r\n if (column.wipLimit && column.cards.length >= column.wipLimit) {\r\n count.classList.add(`${p}-column-count--limit`)\r\n }\r\n header.appendChild(count)\r\n }\r\n\r\n // 折叠按钮\r\n const collapseBtn = createElement('button', `${p}-column-collapse-btn`)\r\n collapseBtn.innerHTML = column.collapsed ? '▶' : '▼'\r\n collapseBtn.title = column.collapsed ? '展开' : '折叠'\r\n collapseBtn.addEventListener('click', () => {\r\n this.events.emit('ui:toggle-collapse', { columnId: column.id })\r\n })\r\n header.appendChild(collapseBtn)\r\n\r\n // 操作菜单\r\n if (this.options.showColumnActions !== false) {\r\n const actions = createElement('button', `${p}-column-actions-btn`)\r\n actions.innerHTML = '⋯'\r\n actions.title = '更多操作'\r\n actions.addEventListener('click', e => {\r\n e.stopPropagation()\r\n this.events.emit('ui:column-actions', { columnId: column.id, event: e })\r\n })\r\n header.appendChild(actions)\r\n }\r\n\r\n return header\r\n }\r\n\r\n /**\r\n * 渲染单张卡片\r\n */\r\n private renderCard(card: Card, columnId: string): HTMLElement {\r\n const p = this.prefix\r\n const cardEl = createElement('div', `${p}-card`, {\r\n 'data-card-id': card.id,\r\n })\r\n\r\n if (this.options.cardRenderer) {\r\n this.options.cardRenderer(card, cardEl)\r\n } else {\r\n this.renderDefaultCard(card, cardEl)\r\n }\r\n\r\n // 启用卡片拖拽\r\n if (this.options.draggable !== false) {\r\n this.dragController.enableCardDrag(cardEl, card.id, columnId)\r\n }\r\n\r\n // 点击事件\r\n cardEl.addEventListener('click', () => {\r\n this.events.emit('card:click', { card })\r\n })\r\n\r\n this.cardElements.set(card.id, cardEl)\r\n return cardEl\r\n }\r\n\r\n /**\r\n * 默认卡片渲染\r\n */\r\n private renderDefaultCard(card: Card, cardEl: HTMLElement): void {\r\n const p = this.prefix\r\n\r\n // 优先级指示器\r\n if (card.priority) {\r\n const priorityEl = createElement(\r\n 'div',\r\n `${p}-card-priority ${p}-card-priority--${card.priority}`\r\n )\r\n cardEl.appendChild(priorityEl)\r\n }\r\n\r\n // 标签\r\n if (card.labels?.length) {\r\n const labelsEl = createElement('div', `${p}-card-labels`)\r\n for (const label of card.labels) {\r\n const labelEl = createElement('span', `${p}-card-label`)\r\n labelEl.style.backgroundColor = label.color\r\n labelEl.textContent = label.name\r\n labelsEl.appendChild(labelEl)\r\n }\r\n cardEl.appendChild(labelsEl)\r\n }\r\n\r\n // 标题\r\n const titleEl = createElement('div', `${p}-card-title`)\r\n titleEl.textContent = card.title\r\n cardEl.appendChild(titleEl)\r\n\r\n // 描述\r\n if (card.description) {\r\n const descEl = createElement('div', `${p}-card-desc`)\r\n descEl.textContent = card.description\r\n cardEl.appendChild(descEl)\r\n }\r\n\r\n // 底部信息栏\r\n const hasFooter = card.assignees?.length || card.dueDate\r\n if (hasFooter) {\r\n const footer = createElement('div', `${p}-card-footer`)\r\n\r\n if (card.assignees?.length) {\r\n const assigneesEl = createElement('div', `${p}-card-assignees`)\r\n for (const assignee of card.assignees.slice(0, 3)) {\r\n const avatar = createElement('span', `${p}-card-avatar`)\r\n avatar.textContent = assignee.charAt(0).toUpperCase()\r\n avatar.title = assignee\r\n assigneesEl.appendChild(avatar)\r\n }\r\n if (card.assignees.length > 3) {\r\n const more = createElement('span', `${p}-card-avatar-more`)\r\n more.textContent = `+${card.assignees.length - 3}`\r\n assigneesEl.appendChild(more)\r\n }\r\n footer.appendChild(assigneesEl)\r\n }\r\n\r\n if (card.dueDate) {\r\n const dueEl = createElement('span', `${p}-card-due`)\r\n const date = new Date(card.dueDate)\r\n if (Number.isNaN(date.getTime())) {\r\n dueEl.textContent = 'Invalid date'\r\n } else {\r\n dueEl.textContent = `${date.getMonth() + 1}/${date.getDate()}`\r\n if (date < new Date()) dueEl.classList.add(`${p}-card-due--overdue`)\r\n }\r\n footer.appendChild(dueEl)\r\n }\r\n\r\n cardEl.appendChild(footer)\r\n }\r\n }\r\n\r\n /**\r\n * 获取列元素\r\n */\r\n getColumnElement(columnId: string): HTMLElement | undefined {\r\n return this.columnElements.get(columnId)\r\n }\r\n\r\n /**\r\n * 获取卡片元素\r\n */\r\n getCardElement(cardId: string): HTMLElement | undefined {\r\n return this.cardElements.get(cardId)\r\n }\r\n\r\n /**\r\n * 获取看板根元素\r\n */\r\n getBoardElement(): HTMLElement | null {\r\n return this.boardEl\r\n }\r\n\r\n /**\r\n * 清理 DOM\r\n */\r\n private cleanup(): void {\r\n this.columnElements.clear()\r\n this.columnBodyElements.clear()\r\n this.cardElements.clear()\r\n if (this.boardEl) {\r\n this.boardEl.remove()\r\n this.boardEl = null\r\n }\r\n }\r\n\r\n /**\r\n * 销毁\r\n */\r\n destroy(): void {\r\n this.cleanup()\r\n }\r\n}\r\n","import type {\r\n BoardData,\r\n Card,\r\n Column,\r\n FilterCriteria,\r\n KanbanOptions,\r\n Label,\r\n} from '../types'\r\nimport type { EventHandler } from './EventEmitter'\r\nimport { resolveElement } from '../utils/dom'\r\nimport { VERSION } from '../version'\r\nimport { ColumnManager } from './ColumnManager'\r\nimport { DragController } from './DragController'\r\nimport { EventEmitter } from './EventEmitter'\r\nimport { FilterEngine } from './FilterEngine'\r\nimport { Renderer } from './Renderer'\r\n\r\ninterface CardDropPayload {\r\n cardId: string\r\n fromColumnId: string | null\r\n toColumnId: string\r\n toIndex: number\r\n}\r\n\r\ninterface ColumnDropPayload {\r\n fromColumnId: string\r\n toColumnId: string\r\n toIndex: number\r\n}\r\n\r\nfunction isRecord(value: unknown): value is Record<string, unknown> {\r\n return typeof value === 'object' && value !== null\r\n}\r\n\r\nfunction isCard(value: unknown): value is Card {\r\n return (\r\n isRecord(value) &&\r\n typeof value.id === 'string' &&\r\n typeof value.title === 'string' &&\r\n typeof value.order === 'number' &&\r\n typeof value.columnId === 'string'\r\n )\r\n}\r\n\r\nfunction isColumn(value: unknown): value is Column {\r\n return (\r\n isRecord(value) &&\r\n typeof value.id === 'string' &&\r\n typeof value.title === 'string' &&\r\n Array.isArray(value.cards) &&\r\n typeof value.order === 'number'\r\n )\r\n}\r\n\r\nfunction isCardDropPayload(value: unknown): value is CardDropPayload {\r\n return (\r\n isRecord(value) &&\r\n typeof value.cardId === 'string' &&\r\n (value.fromColumnId === null || typeof value.fromColumnId === 'string') &&\r\n typeof value.toColumnId === 'string' &&\r\n typeof value.toIndex === 'number'\r\n )\r\n}\r\n\r\nfunction isColumnDropPayload(value: unknown): value is ColumnDropPayload {\r\n return (\r\n isRecord(value) &&\r\n typeof value.fromColumnId === 'string' &&\r\n typeof value.toColumnId === 'string' &&\r\n typeof value.toIndex === 'number'\r\n )\r\n}\r\n\r\n/**\r\n * KanbanBoard - 看板视图库,支持拖拽卡片与列管理\r\n */\r\nexport class KanbanBoard {\r\n private container: HTMLElement\r\n private options: KanbanOptions\r\n private destroyed = false\r\n\r\n readonly events: EventEmitter\r\n private columnManager: ColumnManager\r\n private dragController: DragController\r\n private filterEngine: FilterEngine\r\n private renderer: Renderer\r\n private labels: Label[] = []\r\n\r\n constructor(options: KanbanOptions) {\r\n this.options = {\r\n draggable: true,\r\n columnDraggable: true,\r\n crossColumnDrag: true,\r\n searchable: true,\r\n showAddCard: true,\r\n showAddColumn: true,\r\n showColumnActions: true,\r\n showCardCount: true,\r\n classPrefix: 'kanban',\r\n ...options,\r\n }\r\n\r\n const el = resolveElement(options.container)\r\n if (!el) {\r\n throw new Error('[KanbanBoard] Container element not found')\r\n }\r\n this.container = el\r\n\r\n // 初始化子系统\r\n this.events = new EventEmitter()\r\n this.columnManager = new ColumnManager(this.events)\r\n this.dragController = new DragController(\r\n this.events,\r\n this.options.classPrefix || 'kanban'\r\n )\r\n this.filterEngine = new FilterEngine(this.events)\r\n this.renderer = new Renderer(\r\n this.container,\r\n this.events,\r\n this.dragController,\r\n this.options\r\n )\r\n\r\n // 初始化标签\r\n this.labels = options.labels || []\r\n\r\n this.init()\r\n }\r\n\r\n private init(): void {\r\n // 初始化列数据\r\n if (this.options.columns?.length) {\r\n this.columnManager.init(this.options.columns as Partial<Column>[])\r\n }\r\n\r\n // 绑定内部事件\r\n this.bindInternalEvents()\r\n\r\n // 首次渲染\r\n this.render()\r\n\r\n // 触发 ready\r\n this.events.emit('ready', { instance: this })\r\n this.options.onReady?.(this)\r\n\r\n if (this.options.debug) {\r\n console.debug('[KanbanBoard] Initialized', {\r\n columns: this.columnManager.getColumns().length,\r\n cards: this.columnManager.getCardCount(),\r\n })\r\n }\r\n }\r\n\r\n /**\r\n * 绑定内部事件\r\n */\r\n private bindInternalEvents(): void {\r\n // 卡片拖拽放置\r\n this.events.on('card:drop', (payload: unknown) => {\r\n if (!isCardDropPayload(payload)) return\r\n const card = this.columnManager.getCard(payload.cardId)\r\n this.columnManager.moveCard(\r\n payload.cardId,\r\n payload.toColumnId,\r\n payload.toIndex\r\n )\r\n if (card && card.columnId === payload.toColumnId) {\r\n this.options.onCardMove?.(\r\n card,\r\n payload.fromColumnId ?? '',\r\n payload.toColumnId,\r\n card.order\r\n )\r\n }\r\n // 延迟渲染,等待浏览器完成拖拽操作(dragend 事件触发后再重建 DOM)\r\n this.scheduleRender()\r\n })\r\n\r\n // 列拖拽放置\r\n this.events.on('column:drop', (payload: unknown) => {\r\n if (!isColumnDropPayload(payload)) return\r\n const columns = this.columnManager.getColumns()\r\n if (\r\n payload.fromColumnId === payload.toColumnId ||\r\n !columns.some(column => column.id === payload.fromColumnId) ||\r\n !columns.some(column => column.id === payload.toColumnId)\r\n ) {\r\n return\r\n }\r\n const fromIndex = columns.findIndex(c => c.id === payload.fromColumnId)\r\n this.columnManager.moveColumn(payload.fromColumnId, payload.toIndex)\r\n const col = this.columnManager.getColumn(payload.fromColumnId)\r\n if (col) this.options.onColumnMove?.(col, fromIndex, col.order)\r\n this.scheduleRender()\r\n })\r\n\r\n // UI 事件 - 折叠列\r\n this.events.on('ui:toggle-collapse', (payload: unknown) => {\r\n if (!isRecord(payload) || typeof payload.columnId !== 'string') return\r\n this.columnManager.toggleCollapse(payload.columnId)\r\n const col = this.columnManager.getColumn(payload.columnId)\r\n if (col) this.options.onColumnCollapse?.(col, col.collapsed ?? false)\r\n this.render()\r\n })\r\n\r\n // 回调转发\r\n this.events.on('card:add', (p: unknown) => {\r\n if (!isRecord(p) || !isCard(p.card) || typeof p.columnId !== 'string')\r\n return\r\n this.options.onCardAdd?.(p.card, p.columnId)\r\n })\r\n this.events.on('card:remove', (p: unknown) => {\r\n if (!isRecord(p) || !isCard(p.card) || typeof p.columnId !== 'string')\r\n return\r\n this.options.onCardRemove?.(p.card, p.columnId)\r\n })\r\n this.events.on('card:click', (p: unknown) => {\r\n if (!isRecord(p) || !isCard(p.card)) return\r\n this.options.onCardClick?.(p.card)\r\n })\r\n this.events.on('card:update', (p: unknown) => {\r\n if (!isRecord(p) || !isCard(p.card)) return\r\n this.options.onCardUpdate?.(p.card)\r\n })\r\n this.events.on('column:add', (p: unknown) => {\r\n if (!isRecord(p) || !isColumn(p.column)) return\r\n this.options.onColumnAdd?.(p.column)\r\n })\r\n this.events.on('column:remove', (p: unknown) => {\r\n if (!isRecord(p) || !isColumn(p.column)) return\r\n this.options.onColumnRemove?.(p.column)\r\n })\r\n this.events.on('error', (p: unknown) => {\r\n if (!isRecord(p) || !(p.error instanceof Error)) return\r\n this.options.onError?.(p.error)\r\n })\r\n }\r\n\r\n // ============================================================\r\n // Column API\r\n // ============================================================\r\n\r\n /**\r\n * 添加列\r\n */\r\n addColumn(partial: Partial<Column>): Column {\r\n const column = this.columnManager.addColumn(partial)\r\n this.render()\r\n return column\r\n }\r\n\r\n /**\r\n * 移除列\r\n */\r\n removeColumn(id: string): Column | undefined {\r\n const column = this.columnManager.removeColumn(id)\r\n if (column) this.render()\r\n return column\r\n }\r\n\r\n /**\r\n * 更新列\r\n */\r\n updateColumn(id: string, changes: Partial<Column>): Column | undefined {\r\n const column = this.columnManager.updateColumn(id, changes)\r\n if (column) this.render()\r\n return column\r\n }\r\n\r\n /**\r\n * 移动列\r\n */\r\n moveColumn(id: string, toIndex: number): void {\r\n this.columnManager.moveColumn(id, toIndex)\r\n this.render()\r\n }\r\n\r\n /**\r\n * 折叠/展开列\r\n */\r\n toggleColumnCollapse(id: string): void {\r\n this.columnManager.toggleCollapse(id)\r\n this.render()\r\n }\r\n\r\n /**\r\n * 获取所有列\r\n */\r\n getColumns(): Column[] {\r\n return this.columnManager.getColumns()\r\n }\r\n\r\n /**\r\n * 获取单列\r\n */\r\n getColumn(id: string): Column | undefined {\r\n return this.columnManager.getColumn(id)\r\n }\r\n\r\n // ============================================================\r\n // Card API\r\n // ============================================================\r\n\r\n /**\r\n * 添加卡片\r\n */\r\n addCard(columnId: string, partial: Partial<Card>): Card | undefined {\r\n const card = this.columnManager.addCard(columnId, partial)\r\n if (card) this.render()\r\n return card\r\n }\r\n\r\n /**\r\n * 移除卡片\r\n */\r\n removeCard(cardId: string): Card | undefined {\r\n const card = this.columnManager.removeCard(cardId)\r\n if (card) this.render()\r\n return card\r\n }\r\n\r\n /**\r\n * 更新卡片\r\n */\r\n updateCard(cardId: string, changes: Partial<Card>): Card | undefined {\r\n const card = this.columnManager.updateCard(cardId, changes)\r\n if (card) this.render()\r\n return card\r\n }\r\n\r\n /**\r\n * 移动卡片\r\n */\r\n moveCard(cardId: string, toColumnId: string, toIndex: number): void {\r\n this.columnManager.moveCard(cardId, toColumnId, toIndex)\r\n this.render()\r\n }\r\n\r\n /**\r\n * 获取单张卡片\r\n */\r\n getCard(cardId: string): Card | undefined {\r\n return this.columnManager.getCard(cardId)\r\n }\r\n\r\n /**\r\n * 获取所有卡片\r\n */\r\n getAllCards(): Card[] {\r\n return this.columnManager.getAllCards()\r\n }\r\n\r\n /**\r\n * 获取卡片总数\r\n */\r\n getCardCount(): number {\r\n return this.columnManager.getCardCount()\r\n }\r\n\r\n // ============================================================\r\n // Filter / Search API\r\n // ============================================================\r\n\r\n /**\r\n * 筛选卡片\r\n */\r\n filter(criteria: FilterCriteria): void {\r\n this.filterEngine.filter(criteria, this.columnManager.getColumns())\r\n this.render()\r\n }\r\n\r\n /**\r\n * 搜索卡片\r\n */\r\n search(keyword: string): Card[] {\r\n const result = this.filterEngine.search(\r\n keyword,\r\n this.columnManager.getColumns()\r\n )\r\n this.render()\r\n return result\r\n }\r\n\r\n /**\r\n * 清除筛选\r\n */\r\n clearFilter(): void {\r\n this.filterEngine.clearFilter()\r\n this.render()\r\n }\r\n\r\n // ============================================================\r\n // Import / Export API\r\n // ============================================================\r\n\r\n /**\r\n * 导出看板数据\r\n */\r\n exportData(): BoardData {\r\n const data: BoardData = {\r\n version: VERSION,\r\n title: this.options.title || 'Kanban Board',\r\n columns: this.columnManager.getColumns(),\r\n labels: this.labels,\r\n exportedAt: new Date().toISOString(),\r\n }\r\n this.events.emit('data:export', { board: data })\r\n return data\r\n }\r\n\r\n /**\r\n * 导入看板数据\r\n */\r\n importData(data: BoardData): void {\r\n if (!data || !Array.isArray(data.columns)) {\r\n this.events.emit('error', {\r\n error: new Error(\r\n '[KanbanBoard] Invalid board data: columns must be an array'\r\n ),\r\n })\r\n return\r\n }\r\n this.columnManager.setColumns(data.columns)\r\n this.labels = Array.isArray(data.labels) ? [...data.labels] : []\r\n this.filterEngine.clearFilter()\r\n this.events.emit('data:import', { board: data })\r\n this.render()\r\n }\r\n\r\n // ============================================================\r\n // Event API\r\n // ============================================================\r\n\r\n /**\r\n * 监听事件\r\n */\r\n on(event: string, handler: EventHandler): () => void {\r\n return this.events.on(event, handler)\r\n }\r\n\r\n /**\r\n * 监听一次性事件\r\n */\r\n once(event: string, handler: EventHandler): () => void {\r\n return this.events.once(event, handler)\r\n }\r\n\r\n /**\r\n * 移除事件监听\r\n */\r\n off(event: string, handler: EventHandler): void {\r\n this.events.off(event, handler)\r\n }\r\n\r\n // ============================================================\r\n // Label API\r\n // ============================================================\r\n\r\n /**\r\n * 获取所有标签\r\n */\r\n getLabels(): Label[] {\r\n return [...this.labels]\r\n }\r\n\r\n /**\r\n * 添加标签\r\n */\r\n addLabel(label: Label): void {\r\n this.labels.push(label)\r\n }\r\n\r\n /**\r\n * 移除标签\r\n */\r\n removeLabel(id: string): void {\r\n this.labels = this.labels.filter(l => l.id !== id)\r\n }\r\n\r\n // ============================================================\r\n // Render\r\n // ============================================================\r\n\r\n private renderTimer: ReturnType<typeof setTimeout> | null = null\r\n\r\n /**\r\n * 延迟渲染(合并多次调用,等待浏览器拖拽操作完成)\r\n */\r\n private scheduleRender(): void {\r\n if (this.renderTimer !== null) return\r\n this.renderTimer = setTimeout(() => {\r\n this.renderTimer = null\r\n this.render()\r\n }, 0)\r\n }\r\n\r\n /**\r\n * 重新渲染\r\n */\r\n render(): void {\r\n if (this.destroyed) return\r\n this.dragController.destroy()\r\n this.dragController = new DragController(\r\n this.events,\r\n this.options.classPrefix || 'kanban'\r\n )\r\n this.renderer = new Renderer(\r\n this.container,\r\n this.events,\r\n this.dragController,\r\n this.options\r\n )\r\n this.renderer.render(\r\n this.columnManager.getColumns(),\r\n this.filterEngine.getHiddenCardIds()\r\n )\r\n }\r\n\r\n /**\r\n * 获取看板根元素\r\n */\r\n getBoardElement(): HTMLElement | null {\r\n return this.renderer.getBoardElement()\r\n }\r\n\r\n /**\r\n * 获取配置\r\n */\r\n getOptions(): Readonly<KanbanOptions> {\r\n return { ...this.options }\r\n }\r\n\r\n // ============================================================\r\n // Lifecycle\r\n // ============================================================\r\n\r\n /**\r\n * 销毁实例\r\n */\r\n destroy(): void {\r\n if (this.destroyed) return\r\n this.destroyed = true\r\n\r\n if (this.renderTimer !== null) {\r\n clearTimeout(this.renderTimer)\r\n this.renderTimer = null\r\n }\r\n\r\n this.dragController.destroy()\r\n this.filterEngine.destroy()\r\n this.renderer.destroy()\r\n this.columnManager.clear()\r\n\r\n this.events.emit('destroy', undefined)\r\n this.options.onDestroy?.()\r\n this.events.removeAll()\r\n\r\n if (this.options.debug) {\r\n console.debug('[KanbanBoard] Destroyed')\r\n }\r\n }\r\n\r\n /**\r\n * 是否已销毁\r\n */\r\n isDestroyed(): boolean {\r\n return this.destroyed\r\n }\r\n}\r\n\r\n/**\r\n * 创建看板实例(工厂函数)\r\n */\r\nexport function createKanbanBoard(options: KanbanOptions): KanbanBoard {\r\n return new KanbanBoard(options)\r\n}\r\n","/**\r\n * @file index.ts\r\n * @description index 模块\r\n */\r\n\r\n/**\r\n * Utility functions for @composy/kanban-core\r\n */\r\n\r\nexport {\r\n clearElement,\r\n createElement,\r\n insertAt,\r\n removeElement,\r\n resolveElement,\r\n} from './dom'\r\nexport { generateId, resetIdCounter } from './id'\r\n\r\n/**\r\n * Get element from selector or element\r\n * @deprecated Use resolveElement instead\r\n */\r\n/**\r\n * getElement 函数\r\n * @param target - 参数\r\n * @returns 返回值\r\n */\r\n/**\r\n * getElement - get Element function\r\n * @param target - 参数说明\r\n * @returns 返回值说明\r\n */\r\nexport function getElement(target: HTMLElement | string): HTMLElement | null {\r\n if (typeof target === 'string') {\r\n return document.querySelector(target)\r\n }\r\n return target\r\n}\r\n"],"mappings":"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"}
|
package/dist/index.min.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.kanban-board{width:100%;min-height:
|
|
1
|
+
.kanban-board{width:100%;min-height:var(--ld-px-400);overflow-x:auto;overflow-y:hidden;max-width:100%}.kanban-columns{display:flex;gap:var(--ld-px-16);padding:var(--ld-px-8);min-height:100%;align-items:flex-start}.kanban-column{flex:0 0 var(--ld-px-280);max-width:var(--ld-px-280);background:var(--ld-bg-surface);border-radius:var(--ld-px-8);display:flex;flex-direction:column;max-height:calc(100vh - var(--ld-px-200));transition:opacity .2s,box-shadow .2s}.kanban-column--collapsed{flex:0 0 var(--ld-px-48);max-width:var(--ld-px-48);min-height:var(--ld-px-200)}.kanban-column--dragging{opacity:.5}.kanban-column--drag-over{box-shadow:0 0 0 var(--ld-px-2) var(--ld-primary-500)}.kanban-column-header{display:flex;align-items:center;gap:var(--ld-px-6);padding:var(--ld-px-10) var(--ld-px-12);border-bottom:var(--ld-px-1) solid var(--ld-border);-webkit-user-select:none;-moz-user-select:none;user-select:none}.kanban-column-drag-handle{cursor:grab;color:var(--ld-text-secondary);font-size:var(--ld-px-12);letter-spacing:calc(-1 * var(--ld-px-3));line-height:1;padding:var(--ld-px-2) 0}.kanban-column-drag-handle:active{cursor:grabbing}.kanban-column-color{width:var(--ld-px-12);height:var(--ld-px-12);border-radius:var(--ld-px-3);flex-shrink:0}.kanban-column-title{font-size:var(--ld-px-14);font-weight:600;color:var(--ld-text-primary);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kanban-column-count{font-size:var(--ld-px-12);color:var(--ld-text-secondary);background:var(--ld-bg-hover);border-radius:var(--ld-px-10);padding:var(--ld-px-1) var(--ld-px-8);flex-shrink:0}.kanban-column-count--limit{background:var(--ld-danger-50);color:var(--ld-danger-700)}.kanban-column-actions-btn,.kanban-column-collapse-btn{background:0 0;border:none;cursor:pointer;color:var(--ld-text-secondary);font-size:var(--ld-px-12);padding:var(--ld-px-2) var(--ld-px-4);border-radius:var(--ld-px-3);line-height:1}.kanban-column-actions-btn:hover,.kanban-column-collapse-btn:hover{background:var(--ld-bg-hover);color:var(--ld-text-primary)}.kanban-column-body{flex:1;overflow-y:auto;padding:var(--ld-px-8);min-height:var(--ld-px-40)}.kanban-column-body--drag-over{background:var(--ld-primary-50);border-radius:0 0 var(--ld-px-8) var(--ld-px-8)}.kanban-placeholder{background:var(--ld-primary-50);border:var(--ld-px-2) dashed var(--ld-primary-300);border-radius:var(--ld-px-6);margin-bottom:var(--ld-px-8);min-height:var(--ld-px-40);transition:height .15s}.kanban-card{background:var(--ld-bg-container);border-radius:var(--ld-px-6);padding:var(--ld-px-10) var(--ld-px-12);margin-bottom:var(--ld-px-8);cursor:pointer;box-shadow:var(--ld-shadow-1);transition:box-shadow .2s,transform .15s,opacity .2s;border:var(--ld-px-1) solid transparent;position:relative}.kanban-card:hover{box-shadow:var(--ld-shadow-2);border-color:var(--ld-border)}.kanban-card--dragging{opacity:.4;transform:rotate(2deg)}.kanban-card-priority{position:absolute;left:0;top:0;bottom:0;width:var(--ld-px-3);border-radius:var(--ld-px-6) 0 0 var(--ld-px-6)}.kanban-card-priority--low{background:var(--ld-success-500)}.kanban-card-priority--medium{background:var(--ld-warning-500)}.kanban-card-priority--high{background:var(--ld-danger-500)}.kanban-card-priority--urgent{background:var(--ld-danger-700)}.kanban-card-labels{display:flex;flex-wrap:wrap;gap:var(--ld-px-4);margin-bottom:var(--ld-px-6)}.kanban-card-label{display:inline-block;padding:var(--ld-px-1) var(--ld-px-8);border-radius:var(--ld-px-3);font-size:var(--ld-px-11);color:var(--ld-text-inverse);font-weight:500;line-height:1.6}.kanban-card-title{font-size:var(--ld-px-14);font-weight:500;color:var(--ld-text-primary);line-height:1.4;word-break:break-word}.kanban-card-desc{font-size:var(--ld-px-12);color:var(--ld-text-secondary);margin-top:var(--ld-px-4);line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.kanban-card-footer{display:flex;align-items:center;justify-content:space-between;margin-top:var(--ld-px-8);gap:var(--ld-px-8)}.kanban-card-assignees{display:flex;gap:calc(-1 * var(--ld-px-4))}.kanban-card-avatar{display:inline-flex;align-items:center;justify-content:center;width:var(--ld-px-24);height:var(--ld-px-24);border-radius:50%;background:var(--ld-bg-hover);color:var(--ld-text-secondary);font-size:var(--ld-px-11);font-weight:600;border:var(--ld-px-2) solid var(--ld-text-inverse);margin-left:calc(-1 * var(--ld-px-4))}.kanban-card-avatar:first-child{margin-left:0}.kanban-card-avatar-more{display:inline-flex;align-items:center;justify-content:center;width:var(--ld-px-24);height:var(--ld-px-24);border-radius:50%;background:var(--ld-gray-400);color:var(--ld-text-secondary);font-size:var(--ld-px-10);font-weight:600;border:var(--ld-px-2) solid var(--ld-text-inverse);margin-left:calc(-1 * var(--ld-px-4))}.kanban-card-due{font-size:var(--ld-px-12);color:var(--ld-text-secondary);display:flex;align-items:center;gap:var(--ld-px-4)}.kanban-card-due--overdue{color:var(--ld-danger-500);font-weight:600}.kanban-add-card{padding:0 var(--ld-px-4)}.kanban-add-card-btn{width:100%;padding:var(--ld-px-6) var(--ld-px-8);background:0 0;border:none;border-radius:var(--ld-px-6);color:var(--ld-text-secondary);font-size:var(--ld-px-13);cursor:pointer;text-align:left;transition:background .15s,color .15s}.kanban-add-card-btn:hover{background:var(--ld-bg-hover);color:var(--ld-text-primary)}.kanban-add-column{flex:0 0 var(--ld-px-280)}.kanban-add-column-btn{width:100%;padding:var(--ld-px-10);background:var(--ld-bg-surface-soft);border:var(--ld-px-2) dashed var(--ld-gray-300);border-radius:var(--ld-px-8);color:var(--ld-text-secondary);font-size:var(--ld-px-14);cursor:pointer;transition:background .15s,border-color .15s,color .15s}.kanban-add-column-btn:hover{background:var(--ld-bg-hover);border-color:var(--ld-gray-500);color:var(--ld-text-primary)}.kanban-column-body::-webkit-scrollbar{width:var(--ld-px-6)}.kanban-column-body::-webkit-scrollbar-track{background:0 0}.kanban-column-body::-webkit-scrollbar-thumb{background:var(--ld-gray-400);border-radius:var(--ld-px-3)}.kanban-column-body::-webkit-scrollbar-thumb:hover{background:var(--ld-gray-500)}
|