@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
package/dist/index.min.js CHANGED
@@ -1 +1,758 @@
1
- (function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?factory(exports):typeof define==="function"&&define.amd?define(["exports"],factory):(global=typeof globalThis!=="undefined"?globalThis:global||self,factory(global.LDesignKanban={}));})(this,function(exports){Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function createElement(tag,className,attributes){const el=document.createElement(tag);if(className)el.className=className;if(attributes)Object.entries(attributes).forEach(([key,value])=>{el.setAttribute(key,value);});return el;}function resolveElement(target){if(typeof target==="string")return document.querySelector(target);return target;}function clearElement(el){el.innerHTML="";}function removeElement(el){el?.parentNode?.removeChild(el);}function insertAt(parent,child,index){const ref=parent.children[index];if(ref)parent.insertBefore(child,ref);else parent.appendChild(child);}var EventEmitter=class{constructor(){this.listeners=new Map();}on(event,handler){if(!this.listeners.has(event))this.listeners.set(event,new Set());this.listeners.get(event).add(handler);return()=>this.off(event,handler);}once(event,handler){const wrapper=(...args)=>{this.off(event,wrapper);handler(...args);};return this.on(event,wrapper);}off(event,handler){this.listeners.get(event)?.delete(handler);}emit(event,payload){const handlers=this.listeners.get(event);if(handlers)handlers.forEach((handler)=>{try{handler(payload);}catch(err){console.error(`[KanbanBoard]Error in event handler for "${event}":`,err);}});}removeAll(){this.listeners.clear();}listenerCount(event){return this.listeners.get(event)?.size??0;}};let counter=0;function generateId(prefix="kb"){counter++;return `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).substring(2,6)}_${counter}`;}function resetIdCounter(){counter=0;}var ColumnManager=class{constructor(events){this.columns=[];this.events=events;}init(columns){this.columns=columns.map((col,index)=>this.normalizeColumn(col,index));}normalizeColumn(partial,index){return{id:partial.id||generateId("col"),title:partial.title||`Column ${index+1}`,cards:(partial.cards||[]).map((card,cardIndex)=>this.normalizeCard(card,partial.id||"",cardIndex)),wipLimit:partial.wipLimit,collapsed:partial.collapsed??false,color:partial.color,order:partial.order??index};}normalizeCard(partial,columnId,index){return{id:partial.id||generateId("card"),title:partial.title||"",description:partial.description,labels:partial.labels||[],assignees:partial.assignees||[],dueDate:partial.dueDate,priority:partial.priority,order:partial.order??index,columnId:partial.columnId||columnId,data:partial.data,createdAt:partial.createdAt||(new Date()).toISOString(),updatedAt:partial.updatedAt};}getColumns(){return[...this.columns].sort((a,b)=>a.order-b.order);}getColumn(id){return this.columns.find((c)=>c.id===id);}addColumn(partial){const column=this.normalizeColumn(partial,this.columns.length);column.cards=column.cards.map((card)=>({...card,columnId:column.id}));this.columns.push(column);this.events.emit("column:add",{column});return column;}removeColumn(id){const index=this.columns.findIndex((c)=>c.id===id);if(index===-1)return void 0;const[column]=this.columns.splice(index,1);this.reorderColumns();this.events.emit("column:remove",{column});return column;}updateColumn(id,changes){const column=this.columns.find((c)=>c.id===id);if(!column)return void 0;Object.assign(column,changes,{id});this.events.emit("column:update",{column,changes});return column;}moveColumn(id,toIndex){const fromIndex=this.columns.findIndex((c)=>c.id===id);if(fromIndex===-1)return;const[column]=this.columns.splice(fromIndex,1);this.columns.splice(toIndex,0,column);this.reorderColumns();this.events.emit("column:move",{column,fromIndex,toIndex});}toggleCollapse(id){const column=this.columns.find((c)=>c.id===id);if(!column)return;column.collapsed=!column.collapsed;this.events.emit("column:collapse",{column,collapsed:column.collapsed});}getCards(columnId){const column=this.columns.find((c)=>c.id===columnId);return column?[...column.cards].sort((a,b)=>a.order-b.order):[];}addCard(columnId,partial){const column=this.columns.find((c)=>c.id===columnId);if(!column)return void 0;if(column.wipLimit&&column.cards.length>=column.wipLimit){this.events.emit("error",{error:new Error(`Column "${column.title}" reached WIP limit(${column.wipLimit})`)});return;}const card=this.normalizeCard({...partial,columnId},columnId,column.cards.length);column.cards.push(card);this.events.emit("card:add",{card,columnId});return card;}removeCard(cardId){for(const column of this.columns){const index=column.cards.findIndex((c)=>c.id===cardId);if(index!==-1){const[card]=column.cards.splice(index,1);this.reorderCards(column);this.events.emit("card:remove",{card,columnId:column.id});return card;}}}updateCard(cardId,changes){for(const column of this.columns){const card=column.cards.find((c)=>c.id===cardId);if(card){Object.assign(card,changes,{id:cardId,columnId:column.id});card.updatedAt=(new Date()).toISOString();this.events.emit("card:update",{card,changes});return card;}}}getCard(cardId){for(const column of this.columns){const card=column.cards.find((c)=>c.id===cardId);if(card)return card;}}moveCard(cardId,toColumnId,toIndex){let fromColumn;let cardIndex=-1;for(const column of this.columns){const idx=column.cards.findIndex((c)=>c.id===cardId);if(idx!==-1){fromColumn=column;cardIndex=idx;break;}}if(!fromColumn||cardIndex===-1)return;const toColumn=this.columns.find((c)=>c.id===toColumnId);if(!toColumn)return;if(fromColumn.id!==toColumnId&&toColumn.wipLimit&&toColumn.cards.length>=toColumn.wipLimit){this.events.emit("error",{error:new Error(`Column "${toColumn.title}" reached WIP limit(${toColumn.wipLimit})`)});return;}const[card]=fromColumn.cards.splice(cardIndex,1);card.columnId=toColumnId;toColumn.cards.splice(toIndex,0,card);this.reorderCards(fromColumn);this.reorderCards(toColumn);this.events.emit("card:move",{card,fromColumnId:fromColumn.id,toColumnId,toIndex});}getAllCards(){const cards=[];for(const column of this.columns)cards.push(...column.cards);return cards;}getCardCount(){return this.columns.reduce((sum,col)=>sum+col.cards.length,0);}reorderColumns(){this.columns.forEach((col,index)=>{col.order=index;});}reorderCards(column){column.cards.forEach((card,index)=>{card.order=index;});}setColumns(columns){this.columns=columns;}clear(){this.columns=[];}};var DragController=class{constructor(events,prefix){this.state={dragging:false,cardId:null,sourceColumnId:null,targetColumnId:null,targetIndex:0,placeholder:null};this.cleanupFns=[];this.events=events;this.prefix=prefix;}enableCardDrag(cardEl,cardId,columnId){cardEl.setAttribute("draggable","true");cardEl.dataset.cardId=cardId;cardEl.dataset.columnId=columnId;const onDragStart=(e)=>{if(!e.dataTransfer)return;e.dataTransfer.effectAllowed="move";e.dataTransfer.setData("text/plain",cardId);this.state.dragging=true;this.state.cardId=cardId;this.state.sourceColumnId=columnId;cardEl.classList.add(`${this.prefix}-card--dragging`);this.events.emit("card:drag-start",{cardId,columnId});this.createPlaceholder(cardEl);};const onDragEnd=()=>{cardEl.classList.remove(`${this.prefix}-card--dragging`);this.removePlaceholder();this.state.dragging=false;this.state.cardId=null;this.state.sourceColumnId=null;this.events.emit("card:drag-end",{cardId});};cardEl.addEventListener("dragstart",onDragStart);cardEl.addEventListener("dragend",onDragEnd);this.cleanupFns.push(()=>{cardEl.removeEventListener("dragstart",onDragStart);cardEl.removeEventListener("dragend",onDragEnd);});}enableColumnDrop(columnBodyEl,columnId){const onDragOver=(e)=>{e.preventDefault();if(!e.dataTransfer)return;e.dataTransfer.dropEffect="move";this.state.targetColumnId=columnId;const afterElement=this.getDragAfterElement(columnBodyEl,e.clientY);const placeholder=this.state.placeholder;if(placeholder)if(afterElement)columnBodyEl.insertBefore(placeholder,afterElement);else{const addBtn=columnBodyEl.querySelector(`.${this.prefix}-add-card`);if(addBtn)columnBodyEl.insertBefore(placeholder,addBtn);else columnBodyEl.appendChild(placeholder);}};const onDragEnter=(e)=>{e.preventDefault();columnBodyEl.classList.add(`${this.prefix}-column-body--drag-over`);};const onDragLeave=(e)=>{const rect=columnBodyEl.getBoundingClientRect();if(e.clientX<rect.left||e.clientX>rect.right||e.clientY<rect.top||e.clientY>rect.bottom)columnBodyEl.classList.remove(`${this.prefix}-column-body--drag-over`);};const onDrop=(e)=>{e.preventDefault();columnBodyEl.classList.remove(`${this.prefix}-column-body--drag-over`);const cardId=this.state.cardId;if(!cardId)return;const placeholder=this.state.placeholder;let dropIndex=0;if(placeholder&&placeholder.parentNode===columnBodyEl){const children=[...columnBodyEl.children];for(const child of children){if(child===placeholder)break;if(child.hasAttribute("data-card-id")&&!child.classList.contains(`${this.prefix}-card--dragging`))dropIndex++;}}else dropIndex=columnBodyEl.querySelectorAll(`[data-card-id]:not(.${this.prefix}-card--dragging)`).length;this.events.emit("card:drop",{cardId,fromColumnId:this.state.sourceColumnId,toColumnId:columnId,toIndex:dropIndex});this.removePlaceholder();};columnBodyEl.addEventListener("dragover",onDragOver);columnBodyEl.addEventListener("dragenter",onDragEnter);columnBodyEl.addEventListener("dragleave",onDragLeave);columnBodyEl.addEventListener("drop",onDrop);this.cleanupFns.push(()=>{columnBodyEl.removeEventListener("dragover",onDragOver);columnBodyEl.removeEventListener("dragenter",onDragEnter);columnBodyEl.removeEventListener("dragleave",onDragLeave);columnBodyEl.removeEventListener("drop",onDrop);});}enableColumnDrag(columnEl,handleEl,columnId,boardEl){handleEl.setAttribute("draggable","true");const onDragStart=(e)=>{if(!e.dataTransfer)return;e.dataTransfer.effectAllowed="move";e.dataTransfer.setData("application/kanban-column",columnId);columnEl.classList.add(`${this.prefix}-column--dragging`);};const onDragEnd=()=>{columnEl.classList.remove(`${this.prefix}-column--dragging`);boardEl.querySelectorAll(`.${this.prefix}-column--drag-over`).forEach((el)=>{el.classList.remove(`${this.prefix}-column--drag-over`);});};const onDragOver=(e)=>{if(!e.dataTransfer?.types.includes("application/kanban-column"))return;e.preventDefault();e.dataTransfer.dropEffect="move";columnEl.classList.add(`${this.prefix}-column--drag-over`);};const onDragLeave=()=>{columnEl.classList.remove(`${this.prefix}-column--drag-over`);};const onDrop=(e)=>{e.preventDefault();columnEl.classList.remove(`${this.prefix}-column--drag-over`);const fromColumnId=e.dataTransfer?.getData("application/kanban-column");if(!fromColumnId||fromColumnId===columnId)return;const toIndex=[...boardEl.querySelectorAll(`[data-column-id]`)].indexOf(columnEl);this.events.emit("column:drop",{fromColumnId,toColumnId:columnId,toIndex});};handleEl.addEventListener("dragstart",onDragStart);handleEl.addEventListener("dragend",onDragEnd);columnEl.addEventListener("dragover",onDragOver);columnEl.addEventListener("dragleave",onDragLeave);columnEl.addEventListener("drop",onDrop);this.cleanupFns.push(()=>{handleEl.removeEventListener("dragstart",onDragStart);handleEl.removeEventListener("dragend",onDragEnd);columnEl.removeEventListener("dragover",onDragOver);columnEl.removeEventListener("dragleave",onDragLeave);columnEl.removeEventListener("drop",onDrop);});}getDragAfterElement(container,y){const draggableElements=[...container.querySelectorAll(`[data-card-id]:not(.${this.prefix}-card--dragging):not(.${this.prefix}-placeholder)`)];let closestOffset=Number.NEGATIVE_INFINITY;let closestElement=null;draggableElements.forEach((child)=>{const box=child.getBoundingClientRect();const offset=y-box.top-box.height/2;if(offset<0&&offset>closestOffset){closestOffset=offset;closestElement=child;}});return closestElement;}createPlaceholder(cardEl){this.removePlaceholder();const placeholder=document.createElement("div");placeholder.className=`${this.prefix}-placeholder`;placeholder.style.height=`${cardEl.offsetHeight}px`;this.state.placeholder=placeholder;}removePlaceholder(){if(this.state.placeholder){this.state.placeholder.parentNode?.removeChild(this.state.placeholder);this.state.placeholder=null;}}getState(){return{...this.state};}destroy(){this.cleanupFns.forEach((fn)=>fn());this.cleanupFns=[];this.removePlaceholder();}};var FilterEngine=class{constructor(events){this.currentCriteria=null;this.hiddenCardIds=new Set();this.events=events;}filter(criteria,columns){this.currentCriteria=criteria;this.hiddenCardIds.clear();const allCards=columns.flatMap((col)=>col.cards);for(const card of allCards)if(!this.matchCriteria(card,criteria))this.hiddenCardIds.add(card.id);this.events.emit("filter:change",{criteria});return new Set(this.hiddenCardIds);}search(keyword,columns){this.events.emit("search:change",{keyword});if(!keyword.trim()){this.clearFilter();return columns.flatMap((col)=>col.cards);}const lowerKeyword=keyword.toLowerCase();const allCards=columns.flatMap((col)=>col.cards);const matched=[];this.hiddenCardIds.clear();for(const card of allCards){const titleMatch=card.title.toLowerCase().includes(lowerKeyword);const descMatch=card.description?.toLowerCase().includes(lowerKeyword)??false;const labelMatch=card.labels?.some((l)=>l.name.toLowerCase().includes(lowerKeyword))??false;const assigneeMatch=card.assignees?.some((a)=>a.toLowerCase().includes(lowerKeyword))??false;if(titleMatch||descMatch||labelMatch||assigneeMatch)matched.push(card);else this.hiddenCardIds.add(card.id);}return matched;}clearFilter(){this.currentCriteria=null;this.hiddenCardIds.clear();this.events.emit("filter:clear",void 0);}isCardVisible(cardId){return!this.hiddenCardIds.has(cardId);}getHiddenCardIds(){return new Set(this.hiddenCardIds);}getCurrentCriteria(){return this.currentCriteria;}matchCriteria(card,criteria){if(criteria.keyword){const kw=criteria.keyword.toLowerCase();const titleMatch=card.title.toLowerCase().includes(kw);const descMatch=card.description?.toLowerCase().includes(kw)??false;if(!titleMatch&&!descMatch)return false;}if(criteria.labelIds?.length){const cardLabelIds=card.labels?.map((l)=>l.id)??[];if(!criteria.labelIds.some((id)=>cardLabelIds.includes(id)))return false;}if(criteria.assignees?.length){if(!criteria.assignees.some((a)=>card.assignees?.includes(a)))return false;}if(criteria.priorities?.length){if(!card.priority||!criteria.priorities.includes(card.priority))return false;}if(criteria.columnIds?.length){if(!criteria.columnIds.includes(card.columnId))return false;}if(criteria.dueDateRange){if(!card.dueDate)return false;const dueDate=new Date(card.dueDate).getTime();if(criteria.dueDateRange.start){if(dueDate<new Date(criteria.dueDateRange.start).getTime())return false;}if(criteria.dueDateRange.end){if(dueDate>new Date(criteria.dueDateRange.end).getTime())return false;}}if(criteria.custom){if(!criteria.custom(card))return false;}return true;}destroy(){this.hiddenCardIds.clear();this.currentCriteria=null;}};var Renderer=class{constructor(container,events,dragController,options){this.boardEl=null;this.columnElements=new Map();this.columnBodyElements=new Map();this.cardElements=new Map();this.container=container;this.events=events;this.dragController=dragController;this.options=options;this.prefix=options.classPrefix||"kanban";}render(columns,hiddenCardIds){this.cleanup();this.container.querySelectorAll("[data-kanban-board]").forEach((el)=>el.remove());const p=this.prefix;this.boardEl=createElement("div",`${p}-board`);this.boardEl.setAttribute("data-kanban-board","");const columnsContainer=createElement("div",`${p}-columns`);for(const column of columns){const colEl=this.renderColumn(column,hiddenCardIds);columnsContainer.appendChild(colEl);}if(this.options.showAddColumn!==false){const addColBtn=createElement("div",`${p}-add-column`);addColBtn.innerHTML=`<button class="${p}-add-column-btn">+\u6DFB\u52A0\u5217</button>`;addColBtn.querySelector("button").addEventListener("click",()=>{this.events.emit("ui:add-column");});columnsContainer.appendChild(addColBtn);}this.boardEl.appendChild(columnsContainer);this.container.appendChild(this.boardEl);}renderColumn(column,hiddenCardIds){const p=this.prefix;const colEl=createElement("div",`${p}-column`,{"data-column-id":column.id});if(column.collapsed)colEl.classList.add(`${p}-column--collapsed`);const header=this.renderColumnHeader(column);colEl.appendChild(header);const body=createElement("div",`${p}-column-body`);body.dataset.columnId=column.id;if(!column.collapsed){const visibleCards=column.cards.filter((card)=>!hiddenCardIds||!hiddenCardIds.has(card.id)).sort((a,b)=>a.order-b.order);for(const card of visibleCards){const cardEl=this.renderCard(card,column.id);body.appendChild(cardEl);}if(this.options.showAddCard!==false){const addBtn=createElement("div",`${p}-add-card`);addBtn.innerHTML=`<button class="${p}-add-card-btn">+\u6DFB\u52A0\u5361\u7247</button>`;addBtn.querySelector("button").addEventListener("click",()=>{this.events.emit("ui:add-card",{columnId:column.id});});body.appendChild(addBtn);}if(this.options.draggable!==false)this.dragController.enableColumnDrop(body,column.id);}colEl.appendChild(body);if(this.options.columnDraggable!==false&&this.boardEl){const dragHandle=header.querySelector(`.${p}-column-drag-handle`);if(dragHandle)this.dragController.enableColumnDrag(colEl,dragHandle,column.id,this.boardEl);}this.columnElements.set(column.id,colEl);this.columnBodyElements.set(column.id,body);return colEl;}renderColumnHeader(column){const p=this.prefix;const header=createElement("div",`${p}-column-header`);if(this.options.columnHeaderRenderer){this.options.columnHeaderRenderer(column,header);return header;}if(this.options.columnDraggable!==false){const handle=createElement("span",`${p}-column-drag-handle`);handle.innerHTML="&#8942;&#8942;";handle.title="拖拽排序";header.appendChild(handle);}if(column.color){const indicator=createElement("span",`${p}-column-color`);indicator.style.backgroundColor=column.color;header.appendChild(indicator);}const titleEl=createElement("span",`${p}-column-title`);titleEl.textContent=column.title;header.appendChild(titleEl);if(this.options.showCardCount!==false){const count=createElement("span",`${p}-column-count`);const wipText=column.wipLimit?`/${column.wipLimit}`:"";count.textContent=`${column.cards.length}${wipText}`;if(column.wipLimit&&column.cards.length>=column.wipLimit)count.classList.add(`${p}-column-count--limit`);header.appendChild(count);}const collapseBtn=createElement("button",`${p}-column-collapse-btn`);collapseBtn.innerHTML=column.collapsed?"&#9654;":"&#9660;";collapseBtn.title=column.collapsed?"展开":"折叠";collapseBtn.addEventListener("click",()=>{this.events.emit("ui:toggle-collapse",{columnId:column.id});});header.appendChild(collapseBtn);if(this.options.showColumnActions!==false){const actions=createElement("button",`${p}-column-actions-btn`);actions.innerHTML="&#8943;";actions.title="更多操作";actions.addEventListener("click",(e)=>{e.stopPropagation();this.events.emit("ui:column-actions",{columnId:column.id,event:e});});header.appendChild(actions);}return header;}renderCard(card,columnId){const p=this.prefix;const cardEl=createElement("div",`${p}-card`,{"data-card-id":card.id});if(this.options.cardRenderer)this.options.cardRenderer(card,cardEl);else this.renderDefaultCard(card,cardEl);if(this.options.draggable!==false)this.dragController.enableCardDrag(cardEl,card.id,columnId);cardEl.addEventListener("click",()=>{this.events.emit("card:click",{card});});this.cardElements.set(card.id,cardEl);return cardEl;}renderDefaultCard(card,cardEl){const p=this.prefix;if(card.priority){const priorityEl=createElement("div",`${p}-card-priority ${p}-card-priority--${card.priority}`);cardEl.appendChild(priorityEl);}if(card.labels?.length){const labelsEl=createElement("div",`${p}-card-labels`);for(const label of card.labels){const labelEl=createElement("span",`${p}-card-label`);labelEl.style.backgroundColor=label.color;labelEl.textContent=label.name;labelsEl.appendChild(labelEl);}cardEl.appendChild(labelsEl);}const titleEl=createElement("div",`${p}-card-title`);titleEl.textContent=card.title;cardEl.appendChild(titleEl);if(card.description){const descEl=createElement("div",`${p}-card-desc`);descEl.textContent=card.description;cardEl.appendChild(descEl);}if(card.assignees?.length||card.dueDate){const footer=createElement("div",`${p}-card-footer`);if(card.assignees?.length){const assigneesEl=createElement("div",`${p}-card-assignees`);for(const assignee of card.assignees.slice(0,3)){const avatar=createElement("span",`${p}-card-avatar`);avatar.textContent=assignee.charAt(0).toUpperCase();avatar.title=assignee;assigneesEl.appendChild(avatar);}if(card.assignees.length>3){const more=createElement("span",`${p}-card-avatar-more`);more.textContent=`+${card.assignees.length-3}`;assigneesEl.appendChild(more);}footer.appendChild(assigneesEl);}if(card.dueDate){const dueEl=createElement("span",`${p}-card-due`);const date=new Date(card.dueDate);dueEl.textContent=`${date.getMonth()+1}/${date.getDate()}`;if(date<new Date())dueEl.classList.add(`${p}-card-due--overdue`);footer.appendChild(dueEl);}cardEl.appendChild(footer);}}getColumnElement(columnId){return this.columnElements.get(columnId);}getCardElement(cardId){return this.cardElements.get(cardId);}getBoardElement(){return this.boardEl;}cleanup(){this.columnElements.clear();this.columnBodyElements.clear();this.cardElements.clear();if(this.boardEl){this.boardEl.remove();this.boardEl=null;}}destroy(){this.cleanup();}};const VERSION="0.1.0";var KanbanBoard=class{constructor(options){this.destroyed=false;this.labels=[];this.renderTimer=null;this.options={draggable:true,columnDraggable:true,crossColumnDrag:true,searchable:true,showAddCard:true,showAddColumn:true,showColumnActions:true,showCardCount:true,classPrefix:"kanban",...options};const el=resolveElement(options.container);if(!el)throw new Error("[KanbanBoard]Container element not found");this.container=el;this.events=new EventEmitter();this.columnManager=new ColumnManager(this.events);this.dragController=new DragController(this.events,this.options.classPrefix||"kanban");this.filterEngine=new FilterEngine(this.events);this.renderer=new Renderer(this.container,this.events,this.dragController,this.options);this.labels=options.labels||[];this.init();}init(){if(this.options.columns?.length)this.columnManager.init(this.options.columns);this.bindInternalEvents();this.render();this.events.emit("ready",{instance:this});this.options.onReady?.(this);if(this.options.debug)console.log("[KanbanBoard]Initialized",{columns:this.columnManager.getColumns().length,cards:this.columnManager.getCardCount()});}bindInternalEvents(){this.events.on("card:drop",(payload)=>{this.columnManager.moveCard(payload.cardId,payload.toColumnId,payload.toIndex);this.options.onCardMove?.(this.columnManager.getCard(payload.cardId),payload.fromColumnId,payload.toColumnId,payload.toIndex);this.scheduleRender();});this.events.on("column:drop",(payload)=>{const fromIndex=this.columnManager.getColumns().findIndex((c)=>c.id===payload.fromColumnId);this.columnManager.moveColumn(payload.fromColumnId,payload.toIndex);const col=this.columnManager.getColumn(payload.fromColumnId);if(col)this.options.onColumnMove?.(col,fromIndex,payload.toIndex);this.scheduleRender();});this.events.on("ui:toggle-collapse",(payload)=>{this.columnManager.toggleCollapse(payload.columnId);const col=this.columnManager.getColumn(payload.columnId);if(col)this.options.onColumnCollapse?.(col,col.collapsed??false);this.render();});this.events.on("card:add",(p)=>this.options.onCardAdd?.(p.card,p.columnId));this.events.on("card:remove",(p)=>this.options.onCardRemove?.(p.card,p.columnId));this.events.on("card:click",(p)=>this.options.onCardClick?.(p.card));this.events.on("card:update",(p)=>this.options.onCardUpdate?.(p.card));this.events.on("column:add",(p)=>this.options.onColumnAdd?.(p.column));this.events.on("column:remove",(p)=>this.options.onColumnRemove?.(p.column));this.events.on("error",(p)=>this.options.onError?.(p.error));}addColumn(partial){const column=this.columnManager.addColumn(partial);this.render();return column;}removeColumn(id){const column=this.columnManager.removeColumn(id);if(column)this.render();return column;}updateColumn(id,changes){const column=this.columnManager.updateColumn(id,changes);if(column)this.render();return column;}moveColumn(id,toIndex){this.columnManager.moveColumn(id,toIndex);this.render();}toggleColumnCollapse(id){this.columnManager.toggleCollapse(id);this.render();}getColumns(){return this.columnManager.getColumns();}getColumn(id){return this.columnManager.getColumn(id);}addCard(columnId,partial){const card=this.columnManager.addCard(columnId,partial);if(card)this.render();return card;}removeCard(cardId){const card=this.columnManager.removeCard(cardId);if(card)this.render();return card;}updateCard(cardId,changes){const card=this.columnManager.updateCard(cardId,changes);if(card)this.render();return card;}moveCard(cardId,toColumnId,toIndex){this.columnManager.moveCard(cardId,toColumnId,toIndex);this.render();}getCard(cardId){return this.columnManager.getCard(cardId);}getAllCards(){return this.columnManager.getAllCards();}getCardCount(){return this.columnManager.getCardCount();}filter(criteria){this.filterEngine.filter(criteria,this.columnManager.getColumns());this.render();}search(keyword){const result=this.filterEngine.search(keyword,this.columnManager.getColumns());this.render();return result;}clearFilter(){this.filterEngine.clearFilter();this.render();}exportData(){const data={version:VERSION,title:this.options.title||"Kanban Board",columns:this.columnManager.getColumns(),labels:this.labels,exportedAt:(new Date()).toISOString()};this.events.emit("data:export",{board:data});return data;}importData(data){this.columnManager.setColumns(data.columns);this.labels=data.labels||[];this.filterEngine.clearFilter();this.events.emit("data:import",{board:data});this.render();}on(event,handler){return this.events.on(event,handler);}once(event,handler){return this.events.once(event,handler);}off(event,handler){this.events.off(event,handler);}getLabels(){return[...this.labels];}addLabel(label){this.labels.push(label);}removeLabel(id){this.labels=this.labels.filter((l)=>l.id!==id);}scheduleRender(){if(this.renderTimer!==null)return;this.renderTimer=setTimeout(()=>{this.renderTimer=null;this.render();},0);}render(){if(this.destroyed)return;this.dragController.destroy();this.dragController=new DragController(this.events,this.options.classPrefix||"kanban");this.renderer=new Renderer(this.container,this.events,this.dragController,this.options);this.renderer.render(this.columnManager.getColumns(),this.filterEngine.getHiddenCardIds());}getBoardElement(){return this.renderer.getBoardElement();}getOptions(){return{...this.options};}destroy(){if(this.destroyed)return;this.destroyed=true;if(this.renderTimer!==null){clearTimeout(this.renderTimer);this.renderTimer=null;}this.dragController.destroy();this.filterEngine.destroy();this.renderer.destroy();this.columnManager.clear();this.events.emit("destroy",void 0);this.options.onDestroy?.();this.events.removeAll();if(this.options.debug)console.log("[KanbanBoard]Destroyed");}isDestroyed(){return this.destroyed;}};function createKanbanBoard(options){return new KanbanBoard(options);}function getElement(target){if(typeof target==="string")return document.querySelector(target);return target;}exports.ColumnManager=ColumnManager;exports.DragController=DragController;exports.EventEmitter=EventEmitter;exports.FilterEngine=FilterEngine;exports.KanbanBoard=KanbanBoard;exports.Renderer=Renderer;exports.VERSION=VERSION;exports.clearElement=clearElement;exports.createElement=createElement;exports.createKanbanBoard=createKanbanBoard;exports.generateId=generateId;exports.getElement=getElement;exports.insertAt=insertAt;exports.removeElement=removeElement;exports.resetIdCounter=resetIdCounter;exports.resolveElement=resolveElement;});
1
+ /*!
2
+ * ***********************************
3
+ * @composy/kanban-core v0.0.1 *
4
+ * Built with rollup *
5
+ * Build time: 2024-10-12 17:29:01 *
6
+ * Build mode: production *
7
+ * Minified: No *
8
+ * ***********************************
9
+ */
10
+ (function(e, t) {
11
+ "object" == typeof exports && "undefined" != typeof module ? t(exports) : "function" == typeof define && define.amd ? define(["exports"], t) : t((e = "undefined" != typeof globalThis ? globalThis : e || self).LDesignKanbanCore = {});
12
+ })(this, function(exports) {
13
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
14
+ let e = 0;
15
+ function t(t = "kb") {
16
+ return e++, `${t}_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 6)}_${e}`;
17
+ }
18
+ var n = class {
19
+ constructor(e) {
20
+ this.columns = [], this.events = e;
21
+ }
22
+ init(e) {
23
+ this.columns = e.map((e, t) => this.normalizeColumn(e, t)), this.sortColumns();
24
+ }
25
+ normalizeColumn(e, n) {
26
+ const r = e.id || t("col"), s = (e.cards ?? []).map((e, t) => this.normalizeCard({
27
+ ...e,
28
+ columnId: r
29
+ }, r, t));
30
+ return s.sort((e, t) => e.order - t.order), s.forEach((e, t) => {
31
+ e.order = t;
32
+ }), {
33
+ id: r,
34
+ title: e.title ?? `Column ${n + 1}`,
35
+ cards: s,
36
+ wipLimit: e.wipLimit,
37
+ collapsed: e.collapsed ?? !1,
38
+ color: e.color,
39
+ order: e.order ?? n
40
+ };
41
+ }
42
+ normalizeCard(e, n, r) {
43
+ return {
44
+ id: e.id || t("card"),
45
+ title: e.title ?? "",
46
+ description: e.description,
47
+ labels: e.labels?.map((e) => ({ ...e })) ?? [],
48
+ assignees: e.assignees ? [...e.assignees] : [],
49
+ dueDate: e.dueDate,
50
+ priority: e.priority,
51
+ order: e.order ?? r,
52
+ columnId: e.columnId ?? n,
53
+ data: e.data,
54
+ createdAt: e.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
55
+ updatedAt: e.updatedAt
56
+ };
57
+ }
58
+ getColumns() {
59
+ return [...this.columns].sort((e, t) => e.order - t.order);
60
+ }
61
+ getColumn(e) {
62
+ return this.columns.find((t) => t.id === e);
63
+ }
64
+ addColumn(e) {
65
+ const t = this.normalizeColumn(e, this.columns.length);
66
+ return this.columns.push(t), this.sortColumns(), this.events.emit("column:add", { column: t }), t;
67
+ }
68
+ removeColumn(e) {
69
+ const t = this.columns.findIndex((t) => t.id === e);
70
+ if (-1 === t) return;
71
+ const [n] = this.columns.splice(t, 1);
72
+ return this.reorderColumns(), this.events.emit("column:remove", { column: n }), n;
73
+ }
74
+ updateColumn(e, t) {
75
+ const n = this.columns.find((t) => t.id === e);
76
+ if (n) return Object.assign(n, t, { id: e }), t.cards && (n.cards = t.cards.map((t, n) => this.normalizeCard(t, e, n)), n.cards.sort((e, t) => e.order - t.order), this.reorderCards(n)), void 0 !== t.order && this.sortColumns(), this.events.emit("column:update", {
77
+ column: n,
78
+ changes: t
79
+ }), n;
80
+ }
81
+ moveColumn(e, t) {
82
+ this.sortColumns();
83
+ const n = this.columns.findIndex((t) => t.id === e);
84
+ if (-1 === n) return;
85
+ const [r] = this.columns.splice(n, 1), s = this.clampIndex(t, this.columns.length);
86
+ this.columns.splice(s, 0, r), this.reorderColumns(), this.events.emit("column:move", {
87
+ column: r,
88
+ fromIndex: n,
89
+ toIndex: s
90
+ });
91
+ }
92
+ toggleCollapse(e) {
93
+ const t = this.columns.find((t) => t.id === e);
94
+ t && (t.collapsed = !t.collapsed, this.events.emit("column:collapse", {
95
+ column: t,
96
+ collapsed: t.collapsed
97
+ }));
98
+ }
99
+ getCards(e) {
100
+ const t = this.columns.find((t) => t.id === e);
101
+ return t ? [...t.cards].sort((e, t) => e.order - t.order) : [];
102
+ }
103
+ addCard(e, t) {
104
+ const n = this.columns.find((t) => t.id === e);
105
+ if (!n) return;
106
+ if (n.wipLimit && n.cards.length >= n.wipLimit) return void this.events.emit("error", { error: /* @__PURE__ */ new Error(`Column "${n.title}" reached WIP limit (${n.wipLimit})`) });
107
+ const r = this.normalizeCard({
108
+ ...t,
109
+ columnId: e
110
+ }, e, n.cards.length);
111
+ return n.cards.push(r), this.events.emit("card:add", {
112
+ card: r,
113
+ columnId: e
114
+ }), r;
115
+ }
116
+ removeCard(e) {
117
+ for (const t of this.columns) {
118
+ const n = t.cards.findIndex((t) => t.id === e);
119
+ if (-1 !== n) {
120
+ const [e] = t.cards.splice(n, 1);
121
+ return this.reorderCards(t), this.events.emit("card:remove", {
122
+ card: e,
123
+ columnId: t.id
124
+ }), e;
125
+ }
126
+ }
127
+ }
128
+ updateCard(e, t) {
129
+ for (const n of this.columns) {
130
+ const r = n.cards.find((t) => t.id === e);
131
+ if (r) return Object.assign(r, t, {
132
+ id: e,
133
+ columnId: n.id
134
+ }), r.updatedAt = (/* @__PURE__ */ new Date()).toISOString(), this.events.emit("card:update", {
135
+ card: r,
136
+ changes: t
137
+ }), r;
138
+ }
139
+ }
140
+ getCard(e) {
141
+ for (const t of this.columns) {
142
+ const n = t.cards.find((t) => t.id === e);
143
+ if (n) return n;
144
+ }
145
+ }
146
+ moveCard(e, t, n) {
147
+ let r, s = -1;
148
+ for (const t of this.columns) {
149
+ const n = t.cards.findIndex((t) => t.id === e);
150
+ if (-1 !== n) {
151
+ r = t, s = n;
152
+ break;
153
+ }
154
+ }
155
+ if (!r || -1 === s) return;
156
+ const o = this.columns.find((e) => e.id === t);
157
+ if (!o) return;
158
+ if (r.id !== t && o.wipLimit && o.cards.length >= o.wipLimit) return void this.events.emit("error", { error: /* @__PURE__ */ new Error(`Column "${o.title}" reached WIP limit (${o.wipLimit})`) });
159
+ const [i] = r.cards.splice(s, 1);
160
+ i.columnId = t;
161
+ const a = this.clampIndex(n, o.cards.length);
162
+ o.cards.splice(a, 0, i), this.reorderCards(r), this.reorderCards(o), this.events.emit("card:move", {
163
+ card: i,
164
+ fromColumnId: r.id,
165
+ toColumnId: t,
166
+ toIndex: a
167
+ });
168
+ }
169
+ getAllCards() {
170
+ const e = [];
171
+ for (const t of this.columns) e.push(...t.cards);
172
+ return e;
173
+ }
174
+ getCardCount() {
175
+ return this.columns.reduce((e, t) => e + t.cards.length, 0);
176
+ }
177
+ reorderColumns() {
178
+ this.columns.forEach((e, t) => {
179
+ e.order = t;
180
+ });
181
+ }
182
+ reorderCards(e) {
183
+ e.cards.forEach((e, t) => {
184
+ e.order = t;
185
+ });
186
+ }
187
+ setColumns(e) {
188
+ this.columns = e.map((e, t) => this.normalizeColumn(e, t)), this.sortColumns();
189
+ }
190
+ clear() {
191
+ this.columns = [];
192
+ }
193
+ clampIndex(e, t) {
194
+ return Number.isFinite(e) ? Math.min(Math.max(Math.trunc(e), 0), t) : t;
195
+ }
196
+ sortColumns() {
197
+ this.columns.sort((e, t) => e.order - t.order), this.reorderColumns();
198
+ }
199
+ }, r = class {
200
+ constructor(e, t) {
201
+ this.state = {
202
+ dragging: !1,
203
+ cardId: null,
204
+ sourceColumnId: null,
205
+ targetColumnId: null,
206
+ targetIndex: 0,
207
+ placeholder: null
208
+ }, this.cleanupFns = [], this.events = e, this.prefix = t;
209
+ }
210
+ enableCardDrag(e, t, n) {
211
+ e.setAttribute("draggable", "true"), e.dataset.cardId = t, e.dataset.columnId = n;
212
+ const r = (r) => {
213
+ r.dataTransfer && (r.dataTransfer.effectAllowed = "move", r.dataTransfer.setData("text/plain", t), this.state.dragging = !0, this.state.cardId = t, this.state.sourceColumnId = n, this.state.targetColumnId = n, this.state.targetIndex = 0, e.classList.add(`${this.prefix}-card--dragging`), this.events.emit("card:drag-start", {
214
+ cardId: t,
215
+ columnId: n
216
+ }), this.createPlaceholder(e));
217
+ }, s = () => {
218
+ e.classList.remove(`${this.prefix}-card--dragging`), this.removePlaceholder(), this.state.dragging = !1, this.state.cardId = null, this.state.sourceColumnId = null, this.state.targetColumnId = null, this.state.targetIndex = 0, this.events.emit("card:drag-end", { cardId: t });
219
+ };
220
+ e.addEventListener("dragstart", r), e.addEventListener("dragend", s), this.cleanupFns.push(() => {
221
+ e.removeEventListener("dragstart", r), e.removeEventListener("dragend", s);
222
+ });
223
+ }
224
+ enableColumnDrop(e, t) {
225
+ const n = (n) => {
226
+ if (n.preventDefault(), !n.dataTransfer) return;
227
+ n.dataTransfer.dropEffect = "move", this.state.targetColumnId = t;
228
+ const r = this.getDragAfterElement(e, n.clientY), s = this.state.placeholder;
229
+ if (s) if (r) e.insertBefore(s, r);
230
+ else {
231
+ const t = e.querySelector(`.${this.prefix}-add-card`);
232
+ t ? e.insertBefore(s, t) : e.appendChild(s);
233
+ }
234
+ }, r = (t) => {
235
+ t.preventDefault(), e.classList.add(`${this.prefix}-column-body--drag-over`);
236
+ }, s = (t) => {
237
+ const n = e.getBoundingClientRect();
238
+ (t.clientX < n.left || t.clientX > n.right || t.clientY < n.top || t.clientY > n.bottom) && e.classList.remove(`${this.prefix}-column-body--drag-over`);
239
+ }, o = (n) => {
240
+ n.preventDefault(), e.classList.remove(`${this.prefix}-column-body--drag-over`);
241
+ const r = this.state.cardId;
242
+ if (!r) return;
243
+ const s = this.state.placeholder;
244
+ let o = 0;
245
+ if (s && s.parentNode === e) {
246
+ const t = [...e.children];
247
+ for (const e of t) {
248
+ if (e === s) break;
249
+ e.hasAttribute("data-card-id") && !e.classList.contains(`${this.prefix}-card--dragging`) && o++;
250
+ }
251
+ } else o = e.querySelectorAll(`[data-card-id]:not(.${this.prefix}-card--dragging)`).length;
252
+ this.state.targetIndex = o, this.events.emit("card:drop", {
253
+ cardId: r,
254
+ fromColumnId: this.state.sourceColumnId,
255
+ toColumnId: t,
256
+ toIndex: o
257
+ }), this.removePlaceholder();
258
+ };
259
+ e.addEventListener("dragover", n), e.addEventListener("dragenter", r), e.addEventListener("dragleave", s), e.addEventListener("drop", o), this.cleanupFns.push(() => {
260
+ e.removeEventListener("dragover", n), e.removeEventListener("dragenter", r), e.removeEventListener("dragleave", s), e.removeEventListener("drop", o);
261
+ });
262
+ }
263
+ enableColumnDrag(e, t, n, r) {
264
+ t.setAttribute("draggable", "true");
265
+ const s = (t) => {
266
+ t.dataTransfer && (t.dataTransfer.effectAllowed = "move", t.dataTransfer.setData("application/kanban-column", n), e.classList.add(`${this.prefix}-column--dragging`));
267
+ }, o = () => {
268
+ e.classList.remove(`${this.prefix}-column--dragging`), r.querySelectorAll(`.${this.prefix}-column--drag-over`).forEach((e) => {
269
+ e.classList.remove(`${this.prefix}-column--drag-over`);
270
+ });
271
+ }, i = (t) => {
272
+ t.dataTransfer?.types.includes("application/kanban-column") && (t.preventDefault(), t.dataTransfer.dropEffect = "move", e.classList.add(`${this.prefix}-column--drag-over`));
273
+ }, a = () => {
274
+ e.classList.remove(`${this.prefix}-column--drag-over`);
275
+ }, d = (t) => {
276
+ t.preventDefault(), e.classList.remove(`${this.prefix}-column--drag-over`);
277
+ const s = t.dataTransfer?.getData("application/kanban-column");
278
+ if (!s || s === n) return;
279
+ const o = [...r.querySelectorAll("[data-column-id]")].indexOf(e);
280
+ this.events.emit("column:drop", {
281
+ fromColumnId: s,
282
+ toColumnId: n,
283
+ toIndex: o
284
+ });
285
+ };
286
+ t.addEventListener("dragstart", s), t.addEventListener("dragend", o), e.addEventListener("dragover", i), e.addEventListener("dragleave", a), e.addEventListener("drop", d), this.cleanupFns.push(() => {
287
+ t.removeEventListener("dragstart", s), t.removeEventListener("dragend", o), e.removeEventListener("dragover", i), e.removeEventListener("dragleave", a), e.removeEventListener("drop", d);
288
+ });
289
+ }
290
+ getDragAfterElement(e, t) {
291
+ const n = [...e.querySelectorAll(`[data-card-id]:not(.${this.prefix}-card--dragging):not(.${this.prefix}-placeholder)`)];
292
+ let r = Number.NEGATIVE_INFINITY, s = null;
293
+ return n.forEach((e) => {
294
+ const n = e.getBoundingClientRect(), o = t - n.top - n.height / 2;
295
+ o < 0 && o > r && (r = o, s = e);
296
+ }), s;
297
+ }
298
+ createPlaceholder(e) {
299
+ this.removePlaceholder();
300
+ const t = document.createElement("div");
301
+ t.className = `${this.prefix}-placeholder`, t.style.height = `${e.offsetHeight}px`, this.state.placeholder = t;
302
+ }
303
+ removePlaceholder() {
304
+ this.state.placeholder && (this.state.placeholder.parentNode?.removeChild(this.state.placeholder), this.state.placeholder = null);
305
+ }
306
+ getState() {
307
+ return { ...this.state };
308
+ }
309
+ destroy() {
310
+ this.cleanupFns.forEach((e) => e()), this.cleanupFns = [], this.removePlaceholder(), this.state.dragging = !1, this.state.cardId = null, this.state.sourceColumnId = null, this.state.targetColumnId = null, this.state.targetIndex = 0;
311
+ }
312
+ }, s = class {
313
+ constructor() {
314
+ this.listeners = /* @__PURE__ */ new Map();
315
+ }
316
+ on(e, t) {
317
+ this.listeners.has(e) || this.listeners.set(e, /* @__PURE__ */ new Set());
318
+ const n = this.listeners.get(e);
319
+ return n ? (n.add(t), () => this.off(e, t)) : () => this.off(e, t);
320
+ }
321
+ once(e, t) {
322
+ const n = (...r) => {
323
+ this.off(e, n), t(...r);
324
+ };
325
+ return this.on(e, n);
326
+ }
327
+ off(e, t) {
328
+ const n = this.listeners.get(e);
329
+ n && (n.delete(t), 0 === n.size && this.listeners.delete(e));
330
+ }
331
+ emit(e, t) {
332
+ const n = this.listeners.get(e);
333
+ n && n.forEach((n) => {
334
+ try {
335
+ n(t);
336
+ } catch (t) {
337
+ console.error(`[KanbanBoard] Error in event handler for "${e}":`, t);
338
+ }
339
+ });
340
+ }
341
+ removeAll() {
342
+ this.listeners.clear();
343
+ }
344
+ listenerCount(e) {
345
+ return this.listeners.get(e)?.size ?? 0;
346
+ }
347
+ }, o = class {
348
+ constructor(e) {
349
+ this.currentCriteria = null, this.hiddenCardIds = /* @__PURE__ */ new Set(), this.events = e;
350
+ }
351
+ filter(e, t) {
352
+ this.currentCriteria = e, this.hiddenCardIds.clear();
353
+ const n = t.flatMap((e) => e.cards);
354
+ for (const t of n) this.matchCriteria(t, e) || this.hiddenCardIds.add(t.id);
355
+ return this.events.emit("filter:change", { criteria: e }), new Set(this.hiddenCardIds);
356
+ }
357
+ search(e, t) {
358
+ this.events.emit("search:change", { keyword: e });
359
+ const n = e.trim();
360
+ if (this.currentCriteria = n ? { keyword: n } : null, !n) return this.clearFilter(), t.flatMap((e) => e.cards);
361
+ const r = n.toLowerCase(), s = t.flatMap((e) => e.cards), o = [];
362
+ this.hiddenCardIds.clear();
363
+ for (const e of s) {
364
+ const t = e.title.toLowerCase().includes(r), n = e.description?.toLowerCase().includes(r) ?? !1, s = e.labels?.some((e) => e.name.toLowerCase().includes(r)) ?? !1, i = e.assignees?.some((e) => e.toLowerCase().includes(r)) ?? !1;
365
+ t || n || s || i ? o.push(e) : this.hiddenCardIds.add(e.id);
366
+ }
367
+ return o;
368
+ }
369
+ clearFilter() {
370
+ this.currentCriteria = null, this.hiddenCardIds.clear(), this.events.emit("filter:clear", void 0);
371
+ }
372
+ isCardVisible(e) {
373
+ return !this.hiddenCardIds.has(e);
374
+ }
375
+ getHiddenCardIds() {
376
+ return new Set(this.hiddenCardIds);
377
+ }
378
+ getCurrentCriteria() {
379
+ return this.currentCriteria;
380
+ }
381
+ matchCriteria(e, t) {
382
+ if (t.keyword) {
383
+ const n = t.keyword.toLowerCase(), r = e.title.toLowerCase().includes(n), s = e.description?.toLowerCase().includes(n) ?? !1;
384
+ if (!r && !s) return !1;
385
+ }
386
+ if (t.labelIds?.length) {
387
+ const n = e.labels?.map((e) => e.id) ?? [];
388
+ if (!t.labelIds.some((e) => n.includes(e))) return !1;
389
+ }
390
+ if (t.assignees?.length && !t.assignees.some((t) => e.assignees?.includes(t))) return !1;
391
+ if (t.priorities?.length && (!e.priority || !t.priorities.includes(e.priority))) return !1;
392
+ if (t.columnIds?.length && !t.columnIds.includes(e.columnId)) return !1;
393
+ if (t.dueDateRange) {
394
+ if (!e.dueDate) return !1;
395
+ const n = new Date(e.dueDate).getTime();
396
+ if (Number.isNaN(n)) return !1;
397
+ if (t.dueDateRange.start) {
398
+ const e = new Date(t.dueDateRange.start).getTime();
399
+ if (Number.isNaN(e) || n < e) return !1;
400
+ }
401
+ if (t.dueDateRange.end) {
402
+ const e = new Date(t.dueDateRange.end).getTime();
403
+ if (Number.isNaN(e) || n > e) return !1;
404
+ }
405
+ }
406
+ return !(t.custom && !t.custom(e));
407
+ }
408
+ destroy() {
409
+ this.hiddenCardIds.clear(), this.currentCriteria = null;
410
+ }
411
+ };
412
+ function i(e, t, n) {
413
+ const r = document.createElement(e);
414
+ return t && (r.className = t), n && Object.entries(n).forEach(([e, t]) => {
415
+ r.setAttribute(e, t);
416
+ }), r;
417
+ }
418
+ function a(e) {
419
+ return "string" == typeof e ? document.querySelector(e) : e;
420
+ }
421
+ const d = "0.1.0";
422
+ var l = class {
423
+ constructor(e, t, n, r) {
424
+ this.boardEl = null, this.columnElements = /* @__PURE__ */ new Map(), this.columnBodyElements = /* @__PURE__ */ new Map(), this.cardElements = /* @__PURE__ */ new Map(), this.container = e, this.events = t, this.dragController = n, this.options = r, this.prefix = r.classPrefix || "kanban";
425
+ }
426
+ render(e, t) {
427
+ this.cleanup(), this.container.querySelectorAll("[data-kanban-board]").forEach((e) => e.remove());
428
+ const n = this.prefix;
429
+ this.boardEl = i("div", `${n}-board`), this.boardEl.setAttribute("data-kanban-board", "");
430
+ const r = i("div", `${n}-columns`);
431
+ for (const n of e) {
432
+ const e = this.renderColumn(n, t);
433
+ r.appendChild(e);
434
+ }
435
+ if (!1 !== this.options.showAddColumn) {
436
+ const e = i("div", `${n}-add-column`);
437
+ e.innerHTML = `<button class="${n}-add-column-btn">+ 添加列</button>`, e.querySelector("button")?.addEventListener("click", () => {
438
+ this.events.emit("ui:add-column");
439
+ }), r.appendChild(e);
440
+ }
441
+ this.boardEl.appendChild(r), this.container.appendChild(this.boardEl);
442
+ }
443
+ renderColumn(e, t) {
444
+ const n = this.prefix, r = i("div", `${n}-column`, { "data-column-id": e.id });
445
+ e.collapsed && r.classList.add(`${n}-column--collapsed`);
446
+ const s = this.renderColumnHeader(e);
447
+ r.appendChild(s);
448
+ const o = i("div", `${n}-column-body`);
449
+ if (o.dataset.columnId = e.id, !e.collapsed) {
450
+ const r = e.cards.filter((e) => !t || !t.has(e.id)).sort((e, t) => e.order - t.order);
451
+ for (const t of r) {
452
+ const n = this.renderCard(t, e.id);
453
+ o.appendChild(n);
454
+ }
455
+ if (!1 !== this.options.showAddCard) {
456
+ const t = i("div", `${n}-add-card`);
457
+ t.innerHTML = `<button class="${n}-add-card-btn">+ 添加卡片</button>`, t.querySelector("button")?.addEventListener("click", () => {
458
+ this.events.emit("ui:add-card", { columnId: e.id });
459
+ }), o.appendChild(t);
460
+ }
461
+ !1 !== this.options.draggable && this.dragController.enableColumnDrop(o, e.id);
462
+ }
463
+ r.appendChild(o);
464
+ const a = this.boardEl;
465
+ if (!1 !== this.options.columnDraggable && a) {
466
+ const t = s.querySelector(`.${n}-column-drag-handle`);
467
+ t && this.dragController.enableColumnDrag(r, t, e.id, a);
468
+ }
469
+ return this.columnElements.set(e.id, r), this.columnBodyElements.set(e.id, o), r;
470
+ }
471
+ renderColumnHeader(e) {
472
+ const t = this.prefix, n = i("div", `${t}-column-header`);
473
+ if (this.options.columnHeaderRenderer) return this.options.columnHeaderRenderer(e, n), n;
474
+ if (!1 !== this.options.columnDraggable) {
475
+ const e = i("span", `${t}-column-drag-handle`);
476
+ e.innerHTML = "&#8942;&#8942;", e.title = "拖拽排序", n.appendChild(e);
477
+ }
478
+ if (e.color) {
479
+ const r = i("span", `${t}-column-color`);
480
+ r.style.backgroundColor = e.color, n.appendChild(r);
481
+ }
482
+ const r = i("span", `${t}-column-title`);
483
+ if (r.textContent = e.title, n.appendChild(r), !1 !== this.options.showCardCount) {
484
+ const r = i("span", `${t}-column-count`), s = e.wipLimit ? `/${e.wipLimit}` : "";
485
+ r.textContent = `${e.cards.length}${s}`, e.wipLimit && e.cards.length >= e.wipLimit && r.classList.add(`${t}-column-count--limit`), n.appendChild(r);
486
+ }
487
+ const s = i("button", `${t}-column-collapse-btn`);
488
+ if (s.innerHTML = e.collapsed ? "&#9654;" : "&#9660;", s.title = e.collapsed ? "展开" : "折叠", s.addEventListener("click", () => {
489
+ this.events.emit("ui:toggle-collapse", { columnId: e.id });
490
+ }), n.appendChild(s), !1 !== this.options.showColumnActions) {
491
+ const r = i("button", `${t}-column-actions-btn`);
492
+ r.innerHTML = "&#8943;", r.title = "更多操作", r.addEventListener("click", (t) => {
493
+ t.stopPropagation(), this.events.emit("ui:column-actions", {
494
+ columnId: e.id,
495
+ event: t
496
+ });
497
+ }), n.appendChild(r);
498
+ }
499
+ return n;
500
+ }
501
+ renderCard(e, t) {
502
+ const n = i("div", `${this.prefix}-card`, { "data-card-id": e.id });
503
+ return this.options.cardRenderer ? this.options.cardRenderer(e, n) : this.renderDefaultCard(e, n), !1 !== this.options.draggable && this.dragController.enableCardDrag(n, e.id, t), n.addEventListener("click", () => {
504
+ this.events.emit("card:click", { card: e });
505
+ }), this.cardElements.set(e.id, n), n;
506
+ }
507
+ renderDefaultCard(e, t) {
508
+ const n = this.prefix;
509
+ if (e.priority) {
510
+ const r = i("div", `${n}-card-priority ${n}-card-priority--${e.priority}`);
511
+ t.appendChild(r);
512
+ }
513
+ if (e.labels?.length) {
514
+ const r = i("div", `${n}-card-labels`);
515
+ for (const t of e.labels) {
516
+ const e = i("span", `${n}-card-label`);
517
+ e.style.backgroundColor = t.color, e.textContent = t.name, r.appendChild(e);
518
+ }
519
+ t.appendChild(r);
520
+ }
521
+ const r = i("div", `${n}-card-title`);
522
+ if (r.textContent = e.title, t.appendChild(r), e.description) {
523
+ const r = i("div", `${n}-card-desc`);
524
+ r.textContent = e.description, t.appendChild(r);
525
+ }
526
+ if (e.assignees?.length || e.dueDate) {
527
+ const r = i("div", `${n}-card-footer`);
528
+ if (e.assignees?.length) {
529
+ const t = i("div", `${n}-card-assignees`);
530
+ for (const r of e.assignees.slice(0, 3)) {
531
+ const e = i("span", `${n}-card-avatar`);
532
+ e.textContent = r.charAt(0).toUpperCase(), e.title = r, t.appendChild(e);
533
+ }
534
+ if (e.assignees.length > 3) {
535
+ const r = i("span", `${n}-card-avatar-more`);
536
+ r.textContent = "+" + (e.assignees.length - 3), t.appendChild(r);
537
+ }
538
+ r.appendChild(t);
539
+ }
540
+ if (e.dueDate) {
541
+ const t = i("span", `${n}-card-due`), s = new Date(e.dueDate);
542
+ Number.isNaN(s.getTime()) ? t.textContent = "Invalid date" : (t.textContent = `${s.getMonth() + 1}/${s.getDate()}`, s < /* @__PURE__ */ new Date() && t.classList.add(`${n}-card-due--overdue`)), r.appendChild(t);
543
+ }
544
+ t.appendChild(r);
545
+ }
546
+ }
547
+ getColumnElement(e) {
548
+ return this.columnElements.get(e);
549
+ }
550
+ getCardElement(e) {
551
+ return this.cardElements.get(e);
552
+ }
553
+ getBoardElement() {
554
+ return this.boardEl;
555
+ }
556
+ cleanup() {
557
+ this.columnElements.clear(), this.columnBodyElements.clear(), this.cardElements.clear(), this.boardEl && (this.boardEl.remove(), this.boardEl = null);
558
+ }
559
+ destroy() {
560
+ this.cleanup();
561
+ }
562
+ };
563
+ function c(e) {
564
+ return "object" == typeof e && null !== e;
565
+ }
566
+ function u(e) {
567
+ return c(e) && "string" == typeof e.id && "string" == typeof e.title && "number" == typeof e.order && "string" == typeof e.columnId;
568
+ }
569
+ function h(e) {
570
+ return c(e) && "string" == typeof e.id && "string" == typeof e.title && Array.isArray(e.cards) && "number" == typeof e.order;
571
+ }
572
+ var m = class {
573
+ constructor(e) {
574
+ this.destroyed = !1, this.labels = [], this.renderTimer = null, this.options = {
575
+ draggable: !0,
576
+ columnDraggable: !0,
577
+ crossColumnDrag: !0,
578
+ searchable: !0,
579
+ showAddCard: !0,
580
+ showAddColumn: !0,
581
+ showColumnActions: !0,
582
+ showCardCount: !0,
583
+ classPrefix: "kanban",
584
+ ...e
585
+ };
586
+ const t = a(e.container);
587
+ if (!t) throw new Error("[KanbanBoard] Container element not found");
588
+ this.container = t, this.events = new s(), this.columnManager = new n(this.events), this.dragController = new r(this.events, this.options.classPrefix || "kanban"), this.filterEngine = new o(this.events), this.renderer = new l(this.container, this.events, this.dragController, this.options), this.labels = e.labels || [], this.init();
589
+ }
590
+ init() {
591
+ this.options.columns?.length && this.columnManager.init(this.options.columns), this.bindInternalEvents(), this.render(), this.events.emit("ready", { instance: this }), this.options.onReady?.(this), this.options.debug && console.debug("[KanbanBoard] Initialized", {
592
+ columns: this.columnManager.getColumns().length,
593
+ cards: this.columnManager.getCardCount()
594
+ });
595
+ }
596
+ bindInternalEvents() {
597
+ this.events.on("card:drop", (e) => {
598
+ if (!c(t = e) || "string" != typeof t.cardId || null !== t.fromColumnId && "string" != typeof t.fromColumnId || "string" != typeof t.toColumnId || "number" != typeof t.toIndex) return;
599
+ var t;
600
+ const n = this.columnManager.getCard(e.cardId);
601
+ this.columnManager.moveCard(e.cardId, e.toColumnId, e.toIndex), n && n.columnId === e.toColumnId && this.options.onCardMove?.(n, e.fromColumnId ?? "", e.toColumnId, n.order), this.scheduleRender();
602
+ }), this.events.on("column:drop", (e) => {
603
+ if (!c(t = e) || "string" != typeof t.fromColumnId || "string" != typeof t.toColumnId || "number" != typeof t.toIndex) return;
604
+ var t;
605
+ const n = this.columnManager.getColumns();
606
+ if (e.fromColumnId === e.toColumnId || !n.some((t) => t.id === e.fromColumnId) || !n.some((t) => t.id === e.toColumnId)) return;
607
+ const r = n.findIndex((t) => t.id === e.fromColumnId);
608
+ this.columnManager.moveColumn(e.fromColumnId, e.toIndex);
609
+ const s = this.columnManager.getColumn(e.fromColumnId);
610
+ s && this.options.onColumnMove?.(s, r, s.order), this.scheduleRender();
611
+ }), this.events.on("ui:toggle-collapse", (e) => {
612
+ if (!c(e) || "string" != typeof e.columnId) return;
613
+ this.columnManager.toggleCollapse(e.columnId);
614
+ const t = this.columnManager.getColumn(e.columnId);
615
+ t && this.options.onColumnCollapse?.(t, t.collapsed ?? !1), this.render();
616
+ }), this.events.on("card:add", (e) => {
617
+ c(e) && u(e.card) && "string" == typeof e.columnId && this.options.onCardAdd?.(e.card, e.columnId);
618
+ }), this.events.on("card:remove", (e) => {
619
+ c(e) && u(e.card) && "string" == typeof e.columnId && this.options.onCardRemove?.(e.card, e.columnId);
620
+ }), this.events.on("card:click", (e) => {
621
+ c(e) && u(e.card) && this.options.onCardClick?.(e.card);
622
+ }), this.events.on("card:update", (e) => {
623
+ c(e) && u(e.card) && this.options.onCardUpdate?.(e.card);
624
+ }), this.events.on("column:add", (e) => {
625
+ c(e) && h(e.column) && this.options.onColumnAdd?.(e.column);
626
+ }), this.events.on("column:remove", (e) => {
627
+ c(e) && h(e.column) && this.options.onColumnRemove?.(e.column);
628
+ }), this.events.on("error", (e) => {
629
+ c(e) && e.error instanceof Error && this.options.onError?.(e.error);
630
+ });
631
+ }
632
+ addColumn(e) {
633
+ const t = this.columnManager.addColumn(e);
634
+ return this.render(), t;
635
+ }
636
+ removeColumn(e) {
637
+ const t = this.columnManager.removeColumn(e);
638
+ return t && this.render(), t;
639
+ }
640
+ updateColumn(e, t) {
641
+ const n = this.columnManager.updateColumn(e, t);
642
+ return n && this.render(), n;
643
+ }
644
+ moveColumn(e, t) {
645
+ this.columnManager.moveColumn(e, t), this.render();
646
+ }
647
+ toggleColumnCollapse(e) {
648
+ this.columnManager.toggleCollapse(e), this.render();
649
+ }
650
+ getColumns() {
651
+ return this.columnManager.getColumns();
652
+ }
653
+ getColumn(e) {
654
+ return this.columnManager.getColumn(e);
655
+ }
656
+ addCard(e, t) {
657
+ const n = this.columnManager.addCard(e, t);
658
+ return n && this.render(), n;
659
+ }
660
+ removeCard(e) {
661
+ const t = this.columnManager.removeCard(e);
662
+ return t && this.render(), t;
663
+ }
664
+ updateCard(e, t) {
665
+ const n = this.columnManager.updateCard(e, t);
666
+ return n && this.render(), n;
667
+ }
668
+ moveCard(e, t, n) {
669
+ this.columnManager.moveCard(e, t, n), this.render();
670
+ }
671
+ getCard(e) {
672
+ return this.columnManager.getCard(e);
673
+ }
674
+ getAllCards() {
675
+ return this.columnManager.getAllCards();
676
+ }
677
+ getCardCount() {
678
+ return this.columnManager.getCardCount();
679
+ }
680
+ filter(e) {
681
+ this.filterEngine.filter(e, this.columnManager.getColumns()), this.render();
682
+ }
683
+ search(e) {
684
+ const t = this.filterEngine.search(e, this.columnManager.getColumns());
685
+ return this.render(), t;
686
+ }
687
+ clearFilter() {
688
+ this.filterEngine.clearFilter(), this.render();
689
+ }
690
+ exportData() {
691
+ const e = {
692
+ version: d,
693
+ title: this.options.title || "Kanban Board",
694
+ columns: this.columnManager.getColumns(),
695
+ labels: this.labels,
696
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString()
697
+ };
698
+ return this.events.emit("data:export", { board: e }), e;
699
+ }
700
+ importData(e) {
701
+ e && Array.isArray(e.columns) ? (this.columnManager.setColumns(e.columns), this.labels = Array.isArray(e.labels) ? [...e.labels] : [], this.filterEngine.clearFilter(), this.events.emit("data:import", { board: e }), this.render()) : this.events.emit("error", { error: /* @__PURE__ */ new Error("[KanbanBoard] Invalid board data: columns must be an array") });
702
+ }
703
+ on(e, t) {
704
+ return this.events.on(e, t);
705
+ }
706
+ once(e, t) {
707
+ return this.events.once(e, t);
708
+ }
709
+ off(e, t) {
710
+ this.events.off(e, t);
711
+ }
712
+ getLabels() {
713
+ return [...this.labels];
714
+ }
715
+ addLabel(e) {
716
+ this.labels.push(e);
717
+ }
718
+ removeLabel(e) {
719
+ this.labels = this.labels.filter((t) => t.id !== e);
720
+ }
721
+ scheduleRender() {
722
+ null === this.renderTimer && (this.renderTimer = setTimeout(() => {
723
+ this.renderTimer = null, this.render();
724
+ }, 0));
725
+ }
726
+ render() {
727
+ this.destroyed || (this.dragController.destroy(), this.dragController = new r(this.events, this.options.classPrefix || "kanban"), this.renderer = new l(this.container, this.events, this.dragController, this.options), this.renderer.render(this.columnManager.getColumns(), this.filterEngine.getHiddenCardIds()));
728
+ }
729
+ getBoardElement() {
730
+ return this.renderer.getBoardElement();
731
+ }
732
+ getOptions() {
733
+ return { ...this.options };
734
+ }
735
+ destroy() {
736
+ this.destroyed || (this.destroyed = !0, null !== this.renderTimer && (clearTimeout(this.renderTimer), this.renderTimer = null), this.dragController.destroy(), this.filterEngine.destroy(), this.renderer.destroy(), this.columnManager.clear(), this.events.emit("destroy", void 0), this.options.onDestroy?.(), this.events.removeAll(), this.options.debug && console.debug("[KanbanBoard] Destroyed"));
737
+ }
738
+ isDestroyed() {
739
+ return this.destroyed;
740
+ }
741
+ };
742
+ exports.ColumnManager = n, exports.DragController = r, exports.EventEmitter = s, exports.FilterEngine = o, exports.KanbanBoard = m, exports.Renderer = l, exports.VERSION = d, exports.clearElement = function(e) {
743
+ e.innerHTML = "";
744
+ }, exports.createElement = i, exports.createKanbanBoard = function(e) {
745
+ return new m(e);
746
+ }, exports.generateId = t, exports.getElement = function(e) {
747
+ return "string" == typeof e ? document.querySelector(e) : e;
748
+ }, exports.insertAt = function(e, t, n) {
749
+ const r = e.children[n];
750
+ r ? e.insertBefore(t, r) : e.appendChild(t);
751
+ }, exports.removeElement = function(e) {
752
+ e?.parentNode?.removeChild(e);
753
+ }, exports.resetIdCounter = function() {
754
+ e = 0;
755
+ }, exports.resolveElement = a;
756
+ });
757
+ /*! End of @composy/kanban-core | Powered by @composy/builder */
758
+ //# sourceMappingURL=index.min.js.map