@expcat/tigercat-react 1.0.4 → 1.0.7

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.
@@ -1,286 +0,0 @@
1
- import { useControlledState } from './chunk-UQMPEMY7.mjs';
2
- import React, { useRef, useMemo, useState, useCallback } from 'react';
3
- import { filterColumns, setDragData, createCardDragData, createColumnDragData, getDropIndex, getColumnDropIndex, parseDragData, moveCard, reorderColumns, classNames, getKanbanContainerClasses, isWipExceeded, getColumnCardCount, kanbanCardCountClasses, taskBoardWipExceededClasses, taskBoardColumnHeaderClasses, taskBoardColumnBodyClasses, taskBoardEmptyClasses, taskBoardDropIndicatorClasses, taskBoardCardClasses, taskBoardCardDraggingClasses, kanbanAddCardClasses, taskBoardColumnClasses, taskBoardColumnDropTargetClasses, taskBoardColumnDraggingClasses, kanbanAddColumnClasses } from '@expcat/tigercat-core';
4
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
-
6
- var Kanban = ({
7
- columns: controlledColumns,
8
- defaultColumns = [],
9
- draggable = true,
10
- columnDraggable = true,
11
- enforceWipLimit = false,
12
- beforeCardMove,
13
- beforeColumnMove,
14
- filterText = "",
15
- hiddenColumns,
16
- showCardCount = true,
17
- allowAddCard = true,
18
- allowAddColumn = false,
19
- onCardMove,
20
- onColumnMove,
21
- onColumnsChange,
22
- onCardAdd,
23
- onColumnAdd,
24
- renderCard,
25
- renderColumnHeader,
26
- className,
27
- ...restProps
28
- }) => {
29
- const boardRef = useRef(null);
30
- const [rawColumns, setInternalColumns, isControlled] = useControlledState(
31
- controlledColumns,
32
- defaultColumns
33
- );
34
- const visibleColumns = useMemo(
35
- () => filterColumns(rawColumns, filterText, hiddenColumns),
36
- [rawColumns, filterText, hiddenColumns]
37
- );
38
- const [dragState, setDragState] = useState(null);
39
- const [dropTargetCol, setDropTargetCol] = useState(null);
40
- const [dropTargetIdx, setDropTargetIdx] = useState(-1);
41
- function updateColumns(cols) {
42
- if (!isControlled) setInternalColumns(cols);
43
- onColumnsChange?.(cols);
44
- }
45
- function resetDrag() {
46
- setDragState(null);
47
- setDropTargetCol(null);
48
- setDropTargetIdx(-1);
49
- }
50
- const handleCardDragStart = useCallback(
51
- (e, card, colId, idx) => {
52
- if (!draggable) return;
53
- setDragData(e.nativeEvent.dataTransfer, createCardDragData(card.id, colId, idx));
54
- setDragState({ type: "card", id: card.id, fromColumnId: colId, fromIndex: idx });
55
- },
56
- [draggable]
57
- );
58
- const handleColumnDragStart = useCallback(
59
- (e, colId, idx) => {
60
- if (!columnDraggable) return;
61
- setDragData(e.nativeEvent.dataTransfer, createColumnDragData(colId, idx));
62
- setDragState({ type: "column", id: colId, fromIndex: idx });
63
- },
64
- [columnDraggable]
65
- );
66
- const handleDragOver = useCallback(
67
- (e, colId) => {
68
- e.preventDefault();
69
- if (!dragState) return;
70
- setDropTargetCol(colId);
71
- if (dragState.type === "card") {
72
- const colEl = e.currentTarget.querySelector("[data-kanban-body]");
73
- if (colEl) {
74
- const cards = Array.from(colEl.querySelectorAll("[data-kanban-card]"));
75
- const rects = cards.map((c) => c.getBoundingClientRect());
76
- setDropTargetIdx(getDropIndex(e.clientY, rects));
77
- }
78
- }
79
- },
80
- [dragState]
81
- );
82
- const handleColumnDragOver = useCallback(
83
- (e) => {
84
- e.preventDefault();
85
- if (!dragState || dragState.type !== "column") return;
86
- const boardEl = boardRef.current;
87
- if (!boardEl) return;
88
- const cols = Array.from(boardEl.querySelectorAll("[data-kanban-column]"));
89
- const rects = cols.map((c) => c.getBoundingClientRect());
90
- setDropTargetIdx(getColumnDropIndex(e.clientX, rects));
91
- },
92
- [dragState]
93
- );
94
- const handleDrop = useCallback(
95
- async (e) => {
96
- e.preventDefault();
97
- const data = parseDragData(e.nativeEvent.dataTransfer);
98
- if (!data || !dragState) {
99
- resetDrag();
100
- return;
101
- }
102
- if (data.type === "card" && dropTargetCol != null) {
103
- if (beforeCardMove) {
104
- const evt = {
105
- cardId: data.cardId,
106
- fromColumnId: data.columnId,
107
- toColumnId: dropTargetCol,
108
- fromIndex: data.index,
109
- toIndex: dropTargetIdx
110
- };
111
- const ok = await beforeCardMove(evt);
112
- if (!ok) {
113
- resetDrag();
114
- return;
115
- }
116
- }
117
- const result = moveCard(
118
- rawColumns,
119
- data.cardId,
120
- data.columnId,
121
- dropTargetCol,
122
- dropTargetIdx,
123
- { enforceWipLimit }
124
- );
125
- if (result) {
126
- updateColumns(result.columns);
127
- onCardMove?.(result.event);
128
- }
129
- } else if (data.type === "column") {
130
- if (beforeColumnMove) {
131
- const evt = {
132
- columnId: data.columnId,
133
- fromIndex: data.index,
134
- toIndex: dropTargetIdx
135
- };
136
- const ok = await beforeColumnMove(evt);
137
- if (!ok) {
138
- resetDrag();
139
- return;
140
- }
141
- }
142
- const result = reorderColumns(rawColumns, data.index, dropTargetIdx);
143
- if (result) {
144
- updateColumns(result.columns);
145
- onColumnMove?.(result.event);
146
- }
147
- }
148
- resetDrag();
149
- },
150
- [
151
- dragState,
152
- dropTargetCol,
153
- dropTargetIdx,
154
- rawColumns,
155
- enforceWipLimit,
156
- beforeCardMove,
157
- beforeColumnMove,
158
- onCardMove,
159
- onColumnMove
160
- ]
161
- );
162
- const containerClasses = useMemo(
163
- () => classNames(getKanbanContainerClasses(className)),
164
- [className]
165
- );
166
- return /* @__PURE__ */ jsxs(
167
- "div",
168
- {
169
- ref: boardRef,
170
- className: containerClasses,
171
- role: "region",
172
- "aria-label": "Kanban board",
173
- onDragOver: handleColumnDragOver,
174
- ...restProps,
175
- children: [
176
- visibleColumns.map((col, colIdx) => {
177
- const wipExceeded = isWipExceeded(col);
178
- const cardCount = getColumnCardCount(col);
179
- const isDragOverCol = dropTargetCol === col.id;
180
- const isColDragging = dragState?.type === "column" && dragState.id === col.id;
181
- return /* @__PURE__ */ jsxs(
182
- "div",
183
- {
184
- className: classNames(
185
- taskBoardColumnClasses,
186
- isDragOverCol && dragState?.type === "card" && taskBoardColumnDropTargetClasses,
187
- isColDragging && taskBoardColumnDraggingClasses
188
- ),
189
- "data-kanban-column": "",
190
- draggable: columnDraggable,
191
- onDragStart: (e) => handleColumnDragStart(e, col.id, colIdx),
192
- onDragOver: (e) => handleDragOver(e, col.id),
193
- onDrop: handleDrop,
194
- onDragEnd: resetDrag,
195
- children: [
196
- /* @__PURE__ */ jsxs(
197
- "div",
198
- {
199
- className: classNames(
200
- taskBoardColumnHeaderClasses,
201
- wipExceeded && taskBoardWipExceededClasses
202
- ),
203
- children: [
204
- renderColumnHeader ? renderColumnHeader(col) : /* @__PURE__ */ jsx("span", { children: col.title }),
205
- showCardCount && /* @__PURE__ */ jsx(
206
- "span",
207
- {
208
- className: classNames(
209
- kanbanCardCountClasses,
210
- wipExceeded && taskBoardWipExceededClasses
211
- ),
212
- children: cardCount.limit ? `${cardCount.count}/${cardCount.limit}` : `${cardCount.count}`
213
- }
214
- )
215
- ]
216
- }
217
- ),
218
- /* @__PURE__ */ jsxs("div", { className: taskBoardColumnBodyClasses, "data-kanban-body": "", children: [
219
- col.cards.length === 0 ? /* @__PURE__ */ jsx("div", { className: taskBoardEmptyClasses, children: "No cards" }) : col.cards.map((card, cardIdx) => {
220
- const isCardDragging = dragState?.type === "card" && dragState.id === card.id;
221
- return /* @__PURE__ */ jsxs(React.Fragment, { children: [
222
- isDragOverCol && dragState?.type === "card" && dropTargetIdx === cardIdx && /* @__PURE__ */ jsx("div", { className: taskBoardDropIndicatorClasses }),
223
- /* @__PURE__ */ jsx(
224
- "div",
225
- {
226
- className: classNames(
227
- taskBoardCardClasses,
228
- isCardDragging && taskBoardCardDraggingClasses
229
- ),
230
- draggable,
231
- "data-kanban-card": "",
232
- onDragStart: (e) => handleCardDragStart(e, card, col.id, cardIdx),
233
- children: renderCard ? renderCard(card, col.id) : /* @__PURE__ */ jsxs(Fragment, { children: [
234
- /* @__PURE__ */ jsx("div", { className: "font-medium text-sm", children: card.title }),
235
- card.description && /* @__PURE__ */ jsx("div", { className: "text-xs text-[var(--tiger-text-muted,#6b7280)] mt-1", children: card.description })
236
- ] })
237
- }
238
- )
239
- ] }, card.id);
240
- }),
241
- isDragOverCol && dragState?.type === "card" && dropTargetIdx >= col.cards.length && /* @__PURE__ */ jsx("div", { className: taskBoardDropIndicatorClasses })
242
- ] }),
243
- allowAddCard && /* @__PURE__ */ jsx(
244
- "div",
245
- {
246
- className: kanbanAddCardClasses,
247
- role: "button",
248
- tabIndex: 0,
249
- onClick: () => onCardAdd?.(col.id),
250
- onKeyDown: (e) => {
251
- if (e.key === "Enter" || e.key === " ") {
252
- e.preventDefault();
253
- onCardAdd?.(col.id);
254
- }
255
- },
256
- children: "+ Add card"
257
- }
258
- )
259
- ]
260
- },
261
- col.id
262
- );
263
- }),
264
- allowAddColumn && /* @__PURE__ */ jsx(
265
- "div",
266
- {
267
- className: kanbanAddColumnClasses,
268
- role: "button",
269
- tabIndex: 0,
270
- onClick: () => onColumnAdd?.(),
271
- onKeyDown: (e) => {
272
- if (e.key === "Enter" || e.key === " ") {
273
- e.preventDefault();
274
- onColumnAdd?.();
275
- }
276
- },
277
- children: "+ Add column"
278
- }
279
- )
280
- ]
281
- }
282
- );
283
- };
284
- var Kanban_default = Kanban;
285
-
286
- export { Kanban, Kanban_default };