@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.
Files changed (147) hide show
  1. package/README.md +171 -37
  2. package/dist/index.css +114 -114
  3. package/dist/index.js +221 -126
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.min.css +1 -1
  6. package/dist/index.min.js +758 -1
  7. package/dist/index.min.js.map +1 -0
  8. package/es/.dts-output-manifest.json +1 -0
  9. package/es/.dts.tsbuildinfo +1 -0
  10. package/es/core/ColumnManager.d.ts +4 -3
  11. package/es/core/ColumnManager.js +43 -18
  12. package/es/core/ColumnManager.js.map +1 -1
  13. package/es/core/DragController.d.ts +1 -2
  14. package/es/core/DragController.js +11 -1
  15. package/es/core/DragController.js.map +1 -1
  16. package/es/core/EventEmitter.d.ts +0 -1
  17. package/es/core/EventEmitter.js +8 -3
  18. package/es/core/EventEmitter.js.map +1 -1
  19. package/es/core/FilterEngine.d.ts +1 -2
  20. package/es/core/FilterEngine.js +10 -5
  21. package/es/core/FilterEngine.js.map +1 -1
  22. package/es/core/KanbanBoard.d.ts +3 -3
  23. package/es/core/KanbanBoard.js +61 -15
  24. package/es/core/KanbanBoard.js.map +1 -1
  25. package/es/core/Renderer.d.ts +2 -3
  26. package/es/core/Renderer.js +11 -7
  27. package/es/core/Renderer.js.map +1 -1
  28. package/es/core/index.d.ts +2 -3
  29. package/es/core/index.js +1 -1
  30. package/es/index.d.ts +3 -4
  31. package/es/index.js +2 -2
  32. package/es/styles/kanban.css +114 -114
  33. package/es/types/index.d.ts +3 -4
  34. package/es/types/index.js +1 -1
  35. package/es/utils/dom.d.ts +0 -1
  36. package/es/utils/dom.js +1 -1
  37. package/es/utils/dom.js.map +1 -1
  38. package/es/utils/id.d.ts +0 -1
  39. package/es/utils/id.js +1 -1
  40. package/es/utils/id.js.map +1 -1
  41. package/es/utils/index.d.ts +1 -2
  42. package/es/utils/index.js +1 -1
  43. package/es/utils/index.js.map +1 -1
  44. package/es/version.d.ts +0 -1
  45. package/es/version.js +1 -1
  46. package/es/version.js.map +1 -1
  47. package/esm/core/ColumnManager.js +43 -18
  48. package/esm/core/ColumnManager.js.map +1 -1
  49. package/esm/core/DragController.js +11 -1
  50. package/esm/core/DragController.js.map +1 -1
  51. package/esm/core/EventEmitter.js +8 -3
  52. package/esm/core/EventEmitter.js.map +1 -1
  53. package/esm/core/FilterEngine.js +10 -5
  54. package/esm/core/FilterEngine.js.map +1 -1
  55. package/esm/core/KanbanBoard.js +63 -17
  56. package/esm/core/KanbanBoard.js.map +1 -1
  57. package/esm/core/Renderer.js +11 -7
  58. package/esm/core/Renderer.js.map +1 -1
  59. package/esm/index.js +4 -4
  60. package/esm/styles/kanban.less +357 -339
  61. package/esm/utils/dom.js +1 -1
  62. package/esm/utils/dom.js.map +1 -1
  63. package/esm/utils/id.js +1 -1
  64. package/esm/utils/id.js.map +1 -1
  65. package/esm/utils/index.js +2 -2
  66. package/esm/utils/index.js.map +1 -1
  67. package/esm/version.js +1 -1
  68. package/esm/version.js.map +1 -1
  69. package/lib/core/ColumnManager.cjs +43 -18
  70. package/lib/core/ColumnManager.cjs.map +1 -1
  71. package/{esm/core/ColumnManager.d.ts → lib/core/ColumnManager.d.cts} +4 -3
  72. package/lib/core/DragController.cjs +11 -1
  73. package/lib/core/DragController.cjs.map +1 -1
  74. package/{esm/core/DragController.d.ts → lib/core/DragController.d.cts} +1 -2
  75. package/lib/core/EventEmitter.cjs +8 -3
  76. package/lib/core/EventEmitter.cjs.map +1 -1
  77. package/lib/core/{EventEmitter.d.ts → EventEmitter.d.cts} +0 -1
  78. package/lib/core/FilterEngine.cjs +10 -5
  79. package/lib/core/FilterEngine.cjs.map +1 -1
  80. package/{esm/core/FilterEngine.d.ts → lib/core/FilterEngine.d.cts} +1 -2
  81. package/lib/core/KanbanBoard.cjs +61 -15
  82. package/lib/core/KanbanBoard.cjs.map +1 -1
  83. package/{esm/core/KanbanBoard.d.ts → lib/core/KanbanBoard.d.cts} +3 -3
  84. package/lib/core/Renderer.cjs +11 -7
  85. package/lib/core/Renderer.cjs.map +1 -1
  86. package/{esm/core/Renderer.d.ts → lib/core/Renderer.d.cts} +2 -3
  87. package/lib/core/index.cjs +1 -1
  88. package/{esm/core/index.d.ts → lib/core/index.d.cts} +2 -3
  89. package/lib/index.cjs +2 -2
  90. package/lib/{index.d.ts → index.d.cts} +3 -4
  91. package/lib/styles/kanban.css +114 -114
  92. package/lib/types/index.cjs +1 -1
  93. package/{esm/types/index.d.ts → lib/types/index.d.cts} +3 -4
  94. package/lib/utils/dom.cjs +1 -1
  95. package/lib/utils/dom.cjs.map +1 -1
  96. package/lib/utils/{dom.d.ts → dom.d.cts} +0 -1
  97. package/lib/utils/id.cjs +1 -1
  98. package/lib/utils/id.cjs.map +1 -1
  99. package/{esm/utils/id.d.ts → lib/utils/id.d.cts} +0 -1
  100. package/lib/utils/index.cjs +1 -1
  101. package/lib/utils/index.cjs.map +1 -1
  102. package/lib/utils/{index.d.ts → index.d.cts} +1 -2
  103. package/lib/version.cjs +1 -1
  104. package/lib/version.cjs.map +1 -1
  105. package/{esm/version.d.ts → lib/version.d.cts} +0 -1
  106. package/package.json +23 -21
  107. package/es/core/ColumnManager.d.ts.map +0 -1
  108. package/es/core/DragController.d.ts.map +0 -1
  109. package/es/core/EventEmitter.d.ts.map +0 -1
  110. package/es/core/FilterEngine.d.ts.map +0 -1
  111. package/es/core/KanbanBoard.d.ts.map +0 -1
  112. package/es/core/Renderer.d.ts.map +0 -1
  113. package/es/core/index.d.ts.map +0 -1
  114. package/es/index.d.ts.map +0 -1
  115. package/es/types/index.d.ts.map +0 -1
  116. package/es/utils/dom.d.ts.map +0 -1
  117. package/es/utils/id.d.ts.map +0 -1
  118. package/es/utils/index.d.ts.map +0 -1
  119. package/es/version.d.ts.map +0 -1
  120. package/esm/core/ColumnManager.d.ts.map +0 -1
  121. package/esm/core/DragController.d.ts.map +0 -1
  122. package/esm/core/EventEmitter.d.ts +0 -35
  123. package/esm/core/EventEmitter.d.ts.map +0 -1
  124. package/esm/core/FilterEngine.d.ts.map +0 -1
  125. package/esm/core/KanbanBoard.d.ts.map +0 -1
  126. package/esm/core/Renderer.d.ts.map +0 -1
  127. package/esm/core/index.d.ts.map +0 -1
  128. package/esm/core/index.js +0 -17
  129. package/esm/index.d.ts +0 -15
  130. package/esm/index.d.ts.map +0 -1
  131. package/esm/types/index.d.ts.map +0 -1
  132. package/esm/types/index.js +0 -10
  133. package/esm/utils/dom.d.ts +0 -24
  134. package/esm/utils/dom.d.ts.map +0 -1
  135. package/esm/utils/id.d.ts.map +0 -1
  136. package/esm/utils/index.d.ts +0 -25
  137. package/esm/utils/index.d.ts.map +0 -1
  138. package/esm/version.d.ts.map +0 -1
  139. package/lib/core/ColumnManager.d.ts +0 -99
  140. package/lib/core/DragController.d.ts +0 -55
  141. package/lib/core/FilterEngine.d.ts +0 -45
  142. package/lib/core/KanbanBoard.d.ts +0 -152
  143. package/lib/core/Renderer.d.ts +0 -59
  144. package/lib/core/index.d.ts +0 -11
  145. package/lib/types/index.d.ts +0 -209
  146. package/lib/utils/id.d.ts +0 -9
  147. package/lib/version.d.ts +0 -6
@@ -1 +1 @@
1
- {"version":3,"file":"Renderer.js","names":[],"sources":["../../src/core/Renderer.ts"],"sourcesContent":["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 = '&#8942;&#8942;';\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 ? '&#9654;' : '&#9660;';\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 = '&#8943;';\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"],"mappings":"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"}
1
+ {"version":3,"file":"Renderer.js","names":[],"sources":["../../src/core/Renderer.ts"],"sourcesContent":["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 = '&#8942;&#8942;'\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 ? '&#9654;' : '&#9660;'\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 = '&#8943;'\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"],"mappings":"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"}
@@ -2,10 +2,9 @@
2
2
  * @file index.ts
3
3
  * @description index 模块
4
4
  */
5
- export { KanbanBoard, createKanbanBoard } from './KanbanBoard';
6
- export { EventEmitter, type EventHandler } from './EventEmitter';
7
5
  export { ColumnManager } from './ColumnManager';
8
6
  export { DragController, type DragState } from './DragController';
7
+ export { EventEmitter, type EventHandler } from './EventEmitter';
9
8
  export { FilterEngine } from './FilterEngine';
9
+ export { createKanbanBoard, KanbanBoard } from './KanbanBoard';
10
10
  export { Renderer } from './Renderer';
11
- //# sourceMappingURL=index.d.ts.map
package/es/core/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * ***********************************
3
3
  * @composy/kanban-core v0.0.1 *
4
4
  * Built with rollup *
5
- * Build time: 2024-08-17 11:33:25 *
5
+ * Build time: 2024-10-12 17:29:00 *
6
6
  * Build mode: production *
7
7
  * Minified: No *
8
8
  * ***********************************
package/es/index.d.ts CHANGED
@@ -3,13 +3,12 @@
3
3
  * 看板视图库,支持拖拽卡片与列管理
4
4
  */
5
5
  import './styles/kanban.less';
6
- export type { Label, Card, Column, Board, KanbanOptions, KanbanEventMap, FilterCriteria, BoardData, } from './types';
7
- export { KanbanBoard, createKanbanBoard } from './core/KanbanBoard';
8
- export { EventEmitter, type EventHandler } from './core/EventEmitter';
9
6
  export { ColumnManager } from './core/ColumnManager';
10
7
  export { DragController, type DragState } from './core/DragController';
8
+ export { EventEmitter, type EventHandler } from './core/EventEmitter';
11
9
  export { FilterEngine } from './core/FilterEngine';
10
+ export { createKanbanBoard, KanbanBoard } from './core/KanbanBoard';
12
11
  export { Renderer } from './core/Renderer';
12
+ export type { Board, BoardData, Card, Column, FilterCriteria, KanbanEventMap, KanbanOptions, Label, } from './types';
13
13
  export * from './utils';
14
14
  export { VERSION } from './version';
15
- //# sourceMappingURL=index.d.ts.map
package/es/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * ***********************************
3
3
  * @composy/kanban-core v0.0.1 *
4
4
  * Built with rollup *
5
- * Build time: 2024-08-17 11:33:25 *
5
+ * Build time: 2024-10-12 17:29:00 *
6
6
  * Build mode: production *
7
7
  * Minified: No *
8
8
  * ***********************************
@@ -13,8 +13,8 @@ import { DragController } from "./core/DragController.js";
13
13
  import { EventEmitter } from "./core/EventEmitter.js";
14
14
  import { FilterEngine } from "./core/FilterEngine.js";
15
15
  import { clearElement, createElement, insertAt, removeElement, resolveElement } from "./utils/dom.js";
16
- import { Renderer } from "./core/Renderer.js";
17
16
  import { VERSION } from "./version.js";
17
+ import { Renderer } from "./core/Renderer.js";
18
18
  import { KanbanBoard, createKanbanBoard } from "./core/KanbanBoard.js";
19
19
  import { getElement } from "./utils/index.js";
20
20
  export { ColumnManager, DragController, EventEmitter, FilterEngine, KanbanBoard, Renderer, VERSION, clearElement, createElement, createKanbanBoard, generateId, getElement, insertAt, removeElement, resetIdCounter, resolveElement };
@@ -1,140 +1,140 @@
1
1
  /* @composy/kanban-core - Default Styles */
2
2
  .kanban-board {
3
3
  width: 100%;
4
- min-height: 400px;
4
+ min-height: var(--ld-px-400);
5
5
  overflow-x: auto;
6
6
  overflow-y: hidden;
7
7
  max-width: 100%;
8
8
  }
9
9
  .kanban-columns {
10
10
  display: flex;
11
- gap: 16px;
12
- padding: 8px;
11
+ gap: var(--ld-px-16);
12
+ padding: var(--ld-px-8);
13
13
  min-height: 100%;
14
14
  align-items: flex-start;
15
15
  }
16
16
  /* Column */
17
17
  .kanban-column {
18
- flex: 0 0 280px;
19
- max-width: 280px;
20
- background: #f4f5f7;
21
- border-radius: 8px;
18
+ flex: 0 0 var(--ld-px-280);
19
+ max-width: var(--ld-px-280);
20
+ background: var(--ld-bg-surface);
21
+ border-radius: var(--ld-px-8);
22
22
  display: flex;
23
23
  flex-direction: column;
24
- max-height: calc(100vh - 200px);
24
+ max-height: calc(100vh - var(--ld-px-200));
25
25
  transition: opacity 0.2s, box-shadow 0.2s;
26
26
  }
27
27
  .kanban-column--collapsed {
28
- flex: 0 0 48px;
29
- max-width: 48px;
30
- min-height: 200px;
28
+ flex: 0 0 var(--ld-px-48);
29
+ max-width: var(--ld-px-48);
30
+ min-height: var(--ld-px-200);
31
31
  }
32
32
  .kanban-column--dragging {
33
33
  opacity: 0.5;
34
34
  }
35
35
  .kanban-column--drag-over {
36
- box-shadow: 0 0 0 2px #4c9aff;
36
+ box-shadow: 0 0 0 var(--ld-px-2) var(--ld-primary-500);
37
37
  }
38
38
  /* Column Header */
39
39
  .kanban-column-header {
40
40
  display: flex;
41
41
  align-items: center;
42
- gap: 6px;
43
- padding: 10px 12px;
44
- border-bottom: 1px solid #e1e4e8;
42
+ gap: var(--ld-px-6);
43
+ padding: var(--ld-px-10) var(--ld-px-12);
44
+ border-bottom: var(--ld-px-1) solid var(--ld-border);
45
45
  -webkit-user-select: none;
46
46
  -moz-user-select: none;
47
47
  user-select: none;
48
48
  }
49
49
  .kanban-column-drag-handle {
50
50
  cursor: grab;
51
- color: #a0a0a0;
52
- font-size: 12px;
53
- letter-spacing: -3px;
51
+ color: var(--ld-text-secondary);
52
+ font-size: var(--ld-px-12);
53
+ letter-spacing: calc(-1 * var(--ld-px-3));
54
54
  line-height: 1;
55
- padding: 2px 0;
55
+ padding: var(--ld-px-2) 0;
56
56
  }
57
57
  .kanban-column-drag-handle:active {
58
58
  cursor: grabbing;
59
59
  }
60
60
  .kanban-column-color {
61
- width: 12px;
62
- height: 12px;
63
- border-radius: 3px;
61
+ width: var(--ld-px-12);
62
+ height: var(--ld-px-12);
63
+ border-radius: var(--ld-px-3);
64
64
  flex-shrink: 0;
65
65
  }
66
66
  .kanban-column-title {
67
- font-size: 14px;
67
+ font-size: var(--ld-px-14);
68
68
  font-weight: 600;
69
- color: #172b4d;
69
+ color: var(--ld-text-primary);
70
70
  flex: 1;
71
71
  overflow: hidden;
72
72
  text-overflow: ellipsis;
73
73
  white-space: nowrap;
74
74
  }
75
75
  .kanban-column-count {
76
- font-size: 12px;
77
- color: #6b778c;
78
- background: #dfe1e6;
79
- border-radius: 10px;
80
- padding: 1px 8px;
76
+ font-size: var(--ld-px-12);
77
+ color: var(--ld-text-secondary);
78
+ background: var(--ld-bg-hover);
79
+ border-radius: var(--ld-px-10);
80
+ padding: var(--ld-px-1) var(--ld-px-8);
81
81
  flex-shrink: 0;
82
82
  }
83
83
  .kanban-column-count--limit {
84
- background: #ffebe6;
85
- color: #bf2600;
84
+ background: var(--ld-danger-50);
85
+ color: var(--ld-danger-700);
86
86
  }
87
87
  .kanban-column-collapse-btn,
88
88
  .kanban-column-actions-btn {
89
89
  background: none;
90
90
  border: none;
91
91
  cursor: pointer;
92
- color: #6b778c;
93
- font-size: 12px;
94
- padding: 2px 4px;
95
- border-radius: 3px;
92
+ color: var(--ld-text-secondary);
93
+ font-size: var(--ld-px-12);
94
+ padding: var(--ld-px-2) var(--ld-px-4);
95
+ border-radius: var(--ld-px-3);
96
96
  line-height: 1;
97
97
  }
98
98
  .kanban-column-collapse-btn:hover,
99
99
  .kanban-column-actions-btn:hover {
100
- background: #dfe1e6;
101
- color: #172b4d;
100
+ background: var(--ld-bg-hover);
101
+ color: var(--ld-text-primary);
102
102
  }
103
103
  /* Column Body */
104
104
  .kanban-column-body {
105
105
  flex: 1;
106
106
  overflow-y: auto;
107
- padding: 8px;
108
- min-height: 40px;
107
+ padding: var(--ld-px-8);
108
+ min-height: var(--ld-px-40);
109
109
  }
110
110
  .kanban-column-body--drag-over {
111
- background: #e3f2fd;
112
- border-radius: 0 0 8px 8px;
111
+ background: var(--ld-primary-50);
112
+ border-radius: 0 0 var(--ld-px-8) var(--ld-px-8);
113
113
  }
114
114
  /* Placeholder */
115
115
  .kanban-placeholder {
116
- background: #e3f2fd;
117
- border: 2px dashed #90caf9;
118
- border-radius: 6px;
119
- margin-bottom: 8px;
120
- min-height: 40px;
116
+ background: var(--ld-primary-50);
117
+ border: var(--ld-px-2) dashed var(--ld-primary-300);
118
+ border-radius: var(--ld-px-6);
119
+ margin-bottom: var(--ld-px-8);
120
+ min-height: var(--ld-px-40);
121
121
  transition: height 0.15s ease;
122
122
  }
123
123
  /* Card */
124
124
  .kanban-card {
125
- background: #fff;
126
- border-radius: 6px;
127
- padding: 10px 12px;
128
- margin-bottom: 8px;
125
+ background: var(--ld-bg-container);
126
+ border-radius: var(--ld-px-6);
127
+ padding: var(--ld-px-10) var(--ld-px-12);
128
+ margin-bottom: var(--ld-px-8);
129
129
  cursor: pointer;
130
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
130
+ box-shadow: var(--ld-shadow-1);
131
131
  transition: box-shadow 0.2s, transform 0.15s, opacity 0.2s;
132
- border: 1px solid transparent;
132
+ border: var(--ld-px-1) solid transparent;
133
133
  position: relative;
134
134
  }
135
135
  .kanban-card:hover {
136
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
137
- border-color: #e1e4e8;
136
+ box-shadow: var(--ld-shadow-2);
137
+ border-color: var(--ld-border);
138
138
  }
139
139
  .kanban-card--dragging {
140
140
  opacity: 0.4;
@@ -146,50 +146,50 @@
146
146
  left: 0;
147
147
  top: 0;
148
148
  bottom: 0;
149
- width: 3px;
150
- border-radius: 6px 0 0 6px;
149
+ width: var(--ld-px-3);
150
+ border-radius: var(--ld-px-6) 0 0 var(--ld-px-6);
151
151
  }
152
152
  .kanban-card-priority--low {
153
- background: #36b37e;
153
+ background: var(--ld-success-500);
154
154
  }
155
155
  .kanban-card-priority--medium {
156
- background: #ffab00;
156
+ background: var(--ld-warning-500);
157
157
  }
158
158
  .kanban-card-priority--high {
159
- background: #ff5630;
159
+ background: var(--ld-danger-500);
160
160
  }
161
161
  .kanban-card-priority--urgent {
162
- background: #bf2600;
162
+ background: var(--ld-danger-700);
163
163
  }
164
164
  /* Card Labels */
165
165
  .kanban-card-labels {
166
166
  display: flex;
167
167
  flex-wrap: wrap;
168
- gap: 4px;
169
- margin-bottom: 6px;
168
+ gap: var(--ld-px-4);
169
+ margin-bottom: var(--ld-px-6);
170
170
  }
171
171
  .kanban-card-label {
172
172
  display: inline-block;
173
- padding: 1px 8px;
174
- border-radius: 3px;
175
- font-size: 11px;
176
- color: #fff;
173
+ padding: var(--ld-px-1) var(--ld-px-8);
174
+ border-radius: var(--ld-px-3);
175
+ font-size: var(--ld-px-11);
176
+ color: var(--ld-text-inverse);
177
177
  font-weight: 500;
178
178
  line-height: 1.6;
179
179
  }
180
180
  /* Card Title */
181
181
  .kanban-card-title {
182
- font-size: 14px;
182
+ font-size: var(--ld-px-14);
183
183
  font-weight: 500;
184
- color: #172b4d;
184
+ color: var(--ld-text-primary);
185
185
  line-height: 1.4;
186
186
  word-break: break-word;
187
187
  }
188
188
  /* Card Description */
189
189
  .kanban-card-desc {
190
- font-size: 12px;
191
- color: #6b778c;
192
- margin-top: 4px;
190
+ font-size: var(--ld-px-12);
191
+ color: var(--ld-text-secondary);
192
+ margin-top: var(--ld-px-4);
193
193
  line-height: 1.4;
194
194
  display: -webkit-box;
195
195
  -webkit-line-clamp: 2;
@@ -201,26 +201,26 @@
201
201
  display: flex;
202
202
  align-items: center;
203
203
  justify-content: space-between;
204
- margin-top: 8px;
205
- gap: 8px;
204
+ margin-top: var(--ld-px-8);
205
+ gap: var(--ld-px-8);
206
206
  }
207
207
  .kanban-card-assignees {
208
208
  display: flex;
209
- gap: -4px;
209
+ gap: calc(-1 * var(--ld-px-4));
210
210
  }
211
211
  .kanban-card-avatar {
212
212
  display: inline-flex;
213
213
  align-items: center;
214
214
  justify-content: center;
215
- width: 24px;
216
- height: 24px;
215
+ width: var(--ld-px-24);
216
+ height: var(--ld-px-24);
217
217
  border-radius: 50%;
218
- background: #dfe1e6;
219
- color: #42526e;
220
- font-size: 11px;
218
+ background: var(--ld-bg-hover);
219
+ color: var(--ld-text-secondary);
220
+ font-size: var(--ld-px-11);
221
221
  font-weight: 600;
222
- border: 2px solid #fff;
223
- margin-left: -4px;
222
+ border: var(--ld-px-2) solid var(--ld-text-inverse);
223
+ margin-left: calc(-1 * var(--ld-px-4));
224
224
  }
225
225
  .kanban-card-avatar:first-child {
226
226
  margin-left: 0;
@@ -229,78 +229,78 @@
229
229
  display: inline-flex;
230
230
  align-items: center;
231
231
  justify-content: center;
232
- width: 24px;
233
- height: 24px;
232
+ width: var(--ld-px-24);
233
+ height: var(--ld-px-24);
234
234
  border-radius: 50%;
235
- background: #c1c7d0;
236
- color: #42526e;
237
- font-size: 10px;
235
+ background: var(--ld-gray-400);
236
+ color: var(--ld-text-secondary);
237
+ font-size: var(--ld-px-10);
238
238
  font-weight: 600;
239
- border: 2px solid #fff;
240
- margin-left: -4px;
239
+ border: var(--ld-px-2) solid var(--ld-text-inverse);
240
+ margin-left: calc(-1 * var(--ld-px-4));
241
241
  }
242
242
  .kanban-card-due {
243
- font-size: 12px;
244
- color: #6b778c;
243
+ font-size: var(--ld-px-12);
244
+ color: var(--ld-text-secondary);
245
245
  display: flex;
246
246
  align-items: center;
247
- gap: 4px;
247
+ gap: var(--ld-px-4);
248
248
  }
249
249
  .kanban-card-due--overdue {
250
- color: #ff5630;
250
+ color: var(--ld-danger-500);
251
251
  font-weight: 600;
252
252
  }
253
253
  /* Add Buttons */
254
254
  .kanban-add-card {
255
- padding: 0 4px;
255
+ padding: 0 var(--ld-px-4);
256
256
  }
257
257
  .kanban-add-card-btn {
258
258
  width: 100%;
259
- padding: 6px 8px;
259
+ padding: var(--ld-px-6) var(--ld-px-8);
260
260
  background: none;
261
261
  border: none;
262
- border-radius: 6px;
263
- color: #6b778c;
264
- font-size: 13px;
262
+ border-radius: var(--ld-px-6);
263
+ color: var(--ld-text-secondary);
264
+ font-size: var(--ld-px-13);
265
265
  cursor: pointer;
266
266
  text-align: left;
267
267
  transition: background 0.15s, color 0.15s;
268
268
  }
269
269
  .kanban-add-card-btn:hover {
270
- background: #dfe1e6;
271
- color: #172b4d;
270
+ background: var(--ld-bg-hover);
271
+ color: var(--ld-text-primary);
272
272
  }
273
273
  .kanban-add-column {
274
- flex: 0 0 280px;
274
+ flex: 0 0 var(--ld-px-280);
275
275
  }
276
276
  .kanban-add-column-btn {
277
277
  width: 100%;
278
- padding: 10px;
279
- background: rgba(0, 0, 0, 0.04);
280
- border: 2px dashed #d0d4d9;
281
- border-radius: 8px;
282
- color: #6b778c;
283
- font-size: 14px;
278
+ padding: var(--ld-px-10);
279
+ background: var(--ld-bg-surface-soft);
280
+ border: var(--ld-px-2) dashed var(--ld-gray-300);
281
+ border-radius: var(--ld-px-8);
282
+ color: var(--ld-text-secondary);
283
+ font-size: var(--ld-px-14);
284
284
  cursor: pointer;
285
285
  transition: background 0.15s, border-color 0.15s, color 0.15s;
286
286
  }
287
287
  .kanban-add-column-btn:hover {
288
- background: rgba(0, 0, 0, 0.08);
289
- border-color: #a5adba;
290
- color: #172b4d;
288
+ background: var(--ld-bg-hover);
289
+ border-color: var(--ld-gray-500);
290
+ color: var(--ld-text-primary);
291
291
  }
292
292
  /* Scrollbar */
293
293
  .kanban-column-body::-webkit-scrollbar {
294
- width: 6px;
294
+ width: var(--ld-px-6);
295
295
  }
296
296
  .kanban-column-body::-webkit-scrollbar-track {
297
297
  background: transparent;
298
298
  }
299
299
  .kanban-column-body::-webkit-scrollbar-thumb {
300
- background: #c1c7d0;
301
- border-radius: 3px;
300
+ background: var(--ld-gray-400);
301
+ border-radius: var(--ld-px-3);
302
302
  }
303
303
  .kanban-column-body::-webkit-scrollbar-thumb:hover {
304
- background: #a5adba;
304
+ background: var(--ld-gray-500);
305
305
  }
306
- /*# sourceMappingURL=src/styles/kanban.less.map */
306
+ /*# sourceMappingURL=src\styles\kanban.less.map */
@@ -107,11 +107,11 @@ export interface KanbanOptions {
107
107
  * 看板事件映射
108
108
  */
109
109
  export interface KanbanEventMap {
110
- 'ready': {
110
+ ready: {
111
111
  instance: unknown;
112
112
  };
113
- 'destroy': void;
114
- 'error': {
113
+ destroy: void;
114
+ error: {
115
115
  error: Error;
116
116
  };
117
117
  'card:add': {
@@ -206,4 +206,3 @@ export interface BoardData {
206
206
  labels: Label[];
207
207
  exportedAt: string;
208
208
  }
209
- //# sourceMappingURL=index.d.ts.map
package/es/types/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * ***********************************
3
3
  * @composy/kanban-core v0.0.1 *
4
4
  * Built with rollup *
5
- * Build time: 2024-08-17 11:33:25 *
5
+ * Build time: 2024-10-12 17:29:00 *
6
6
  * Build mode: production *
7
7
  * Minified: No *
8
8
  * ***********************************
package/es/utils/dom.d.ts CHANGED
@@ -21,4 +21,3 @@ export declare function removeElement(el: HTMLElement | null): void;
21
21
  * 插入元素到指定位置
22
22
  */
23
23
  export declare function insertAt(parent: HTMLElement, child: HTMLElement, index: number): void;
24
- //# sourceMappingURL=dom.d.ts.map
package/es/utils/dom.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * ***********************************
3
3
  * @composy/kanban-core v0.0.1 *
4
4
  * Built with rollup *
5
- * Build time: 2024-08-17 11:33:25 *
5
+ * Build time: 2024-10-12 17:29:00 *
6
6
  * Build mode: production *
7
7
  * Minified: No *
8
8
  * ***********************************
@@ -1 +1 @@
1
- {"version":3,"file":"dom.js","names":[],"sources":["../../src/utils/dom.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"],"mappings":";;;;;;;;;;AAOO,SAAS,cACd,KACA,WACA,YAC0B;CAC1B,MAAM,KAAK,SAAS,cAAc,GAAG;CACrC,IAAI,WAAW,GAAG,YAAY;CAC9B,IAAI,YACF,OAAO,QAAQ,UAAU,CAAA,CAAE,SAAS,CAAC,KAAK,WAAW;EACnD,GAAG,aAAa,KAAK,KAAK;CAC5B,CAAC;CAEH,OAAO;AACT;AAKO,SAAS,eAAe,QAAkD;CAC/E,IAAI,OAAO,WAAW,UACpB,OAAO,SAAS,cAAc,MAAM;CAEtC,OAAO;AACT;AAKO,SAAS,aAAa,IAAuB;CAClD,GAAG,YAAY;AACjB;AAKO,SAAS,cAAc,IAA8B;CAC1D,IAAI,YAAY,YAAY,EAAE;AAChC;AAKO,SAAS,SAAS,QAAqB,OAAoB,OAAqB;CACrF,MAAM,MAAM,OAAO,SAAS;CAC5B,IAAI,KACF,OAAO,aAAa,OAAO,GAAG;MAE9B,OAAO,YAAY,KAAK;AAE5B"}
1
+ {"version":3,"file":"dom.js","names":[],"sources":["../../src/utils/dom.ts"],"sourcesContent":["/**\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"],"mappings":";;;;;;;;;;AAOO,SAAS,cACd,KACA,WACA,YAC0B;CAC1B,MAAM,KAAK,SAAS,cAAc,GAAG;CACrC,IAAI,WAAW,GAAG,YAAY;CAC9B,IAAI,YACF,OAAO,QAAQ,UAAU,CAAA,CAAE,SAAS,CAAC,KAAK,WAAW;EACnD,GAAG,aAAa,KAAK,KAAK;CAC5B,CAAC;CAEH,OAAO;AACT;AAKO,SAAS,eACd,QACoB;CACpB,IAAI,OAAO,WAAW,UACpB,OAAO,SAAS,cAAc,MAAM;CAEtC,OAAO;AACT;AAKO,SAAS,aAAa,IAAuB;CAClD,GAAG,YAAY;AACjB;AAKO,SAAS,cAAc,IAA8B;CAC1D,IAAI,YAAY,YAAY,EAAE;AAChC;AAKO,SAAS,SACd,QACA,OACA,OACM;CACN,MAAM,MAAM,OAAO,SAAS;CAC5B,IAAI,KACF,OAAO,aAAa,OAAO,GAAG;MAE9B,OAAO,YAAY,KAAK;AAE5B"}
package/es/utils/id.d.ts CHANGED
@@ -6,4 +6,3 @@ export declare function generateId(prefix?: string): string;
6
6
  * 重置计数器(仅测试用)
7
7
  */
8
8
  export declare function resetIdCounter(): void;
9
- //# sourceMappingURL=id.d.ts.map
package/es/utils/id.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * ***********************************
3
3
  * @composy/kanban-core v0.0.1 *
4
4
  * Built with rollup *
5
- * Build time: 2024-08-17 11:33:25 *
5
+ * Build time: 2024-10-12 17:29:00 *
6
6
  * Build mode: production *
7
7
  * Minified: No *
8
8
  * ***********************************
@@ -1 +1 @@
1
- {"version":3,"file":"id.js","names":[],"sources":["../../src/utils/id.ts"],"sourcesContent":["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"],"mappings":";;;;;;;;;;AAAA,IAAI,UAAU;AAKP,SAAS,WAAW,SAAS,MAAc;CAChD;CAGA,OAAO,GAAG,OAAM,GAFE,KAAK,IAAI,CAAA,CAAE,SAAS,EAElB,EAAS,GADd,KAAK,OAAO,CAAA,CAAE,SAAS,EAAE,CAAA,CAAE,UAAU,GAAG,CACtB,EAAM,GAAI;AAC7C;AAKO,SAAS,iBAAuB;CACrC,UAAU;AACZ"}
1
+ {"version":3,"file":"id.js","names":[],"sources":["../../src/utils/id.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"],"mappings":";;;;;;;;;;AAAA,IAAI,UAAU;AAKP,SAAS,WAAW,SAAS,MAAc;CAChD;CAGA,OAAO,GAAG,OAAM,GAFE,KAAK,IAAI,CAAA,CAAE,SAAS,EAElB,EAAS,GADd,KAAK,OAAO,CAAA,CAAE,SAAS,EAAE,CAAA,CAAE,UAAU,GAAG,CACtB,EAAM,GAAI;AAC7C;AAKO,SAAS,iBAAuB;CACrC,UAAU;AACZ"}
@@ -5,8 +5,8 @@
5
5
  /**
6
6
  * Utility functions for @composy/kanban-core
7
7
  */
8
+ export { clearElement, createElement, insertAt, removeElement, resolveElement, } from './dom';
8
9
  export { generateId, resetIdCounter } from './id';
9
- export { createElement, resolveElement, clearElement, removeElement, insertAt } from './dom';
10
10
  /**
11
11
  * Get element from selector or element
12
12
  * @deprecated Use resolveElement instead
@@ -22,4 +22,3 @@ export { createElement, resolveElement, clearElement, removeElement, insertAt }
22
22
  * @returns 返回值说明
23
23
  */
24
24
  export declare function getElement(target: HTMLElement | string): HTMLElement | null;
25
- //# sourceMappingURL=index.d.ts.map