@expcat/tigercat-react 0.3.69 → 0.4.0

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 (45) hide show
  1. package/dist/chunk-2EOXY2LP.mjs +353 -0
  2. package/dist/chunk-5CLXOFRZ.mjs +248 -0
  3. package/dist/chunk-6W6CRBBG.mjs +169 -0
  4. package/dist/chunk-EHYSER2Z.js +144 -0
  5. package/dist/chunk-GNMOOYHG.js +250 -0
  6. package/dist/chunk-JWFEJ4XG.js +543 -0
  7. package/dist/chunk-NV3JUZ3N.js +57 -0
  8. package/dist/chunk-PJCY45UP.mjs +536 -0
  9. package/dist/chunk-QFYS5QIZ.mjs +142 -0
  10. package/dist/chunk-QIJG42YQ.mjs +54 -0
  11. package/dist/chunk-U3JOBIDU.js +355 -0
  12. package/dist/chunk-Z7SXK2KO.js +171 -0
  13. package/dist/components/ActivityFeed.js +4 -4
  14. package/dist/components/ActivityFeed.mjs +2 -2
  15. package/dist/components/CropUpload.d.mts +52 -0
  16. package/dist/components/CropUpload.d.ts +52 -0
  17. package/dist/components/CropUpload.js +14 -0
  18. package/dist/components/CropUpload.mjs +5 -0
  19. package/dist/components/Image.d.mts +20 -0
  20. package/dist/components/Image.d.ts +20 -0
  21. package/dist/components/Image.js +13 -0
  22. package/dist/components/Image.mjs +4 -0
  23. package/dist/components/ImageCropper.d.mts +21 -0
  24. package/dist/components/ImageCropper.d.ts +21 -0
  25. package/dist/components/ImageCropper.js +10 -0
  26. package/dist/components/ImageCropper.mjs +1 -0
  27. package/dist/components/ImageGroup.d.mts +30 -0
  28. package/dist/components/ImageGroup.d.ts +30 -0
  29. package/dist/components/ImageGroup.js +16 -0
  30. package/dist/components/ImageGroup.mjs +3 -0
  31. package/dist/components/ImagePreview.d.mts +20 -0
  32. package/dist/components/ImagePreview.d.ts +20 -0
  33. package/dist/components/ImagePreview.js +11 -0
  34. package/dist/components/ImagePreview.mjs +2 -0
  35. package/dist/components/TaskBoard.d.mts +13 -0
  36. package/dist/components/TaskBoard.d.ts +13 -0
  37. package/dist/components/TaskBoard.js +17 -0
  38. package/dist/components/TaskBoard.mjs +2 -0
  39. package/dist/index.d.mts +6 -0
  40. package/dist/index.d.ts +6 -0
  41. package/dist/index.js +108 -74
  42. package/dist/index.mjs +23 -17
  43. package/package.json +2 -2
  44. package/dist/{chunk-MTL2QUM3.mjs → chunk-FTY2W4L2.mjs} +1 -1
  45. package/dist/{chunk-J3HKED4B.js → chunk-IOM7DWWQ.js} +1 -1
@@ -0,0 +1,536 @@
1
+ import { useTigerConfig } from './chunk-VEGBO77D.mjs';
2
+ import React, { useMemo, useState, useEffect, useRef, useCallback } from 'react';
3
+ import { classNames, taskBoardCardClasses, taskBoardCardDraggingClasses, isWipExceeded, taskBoardColumnClasses, taskBoardColumnDropTargetClasses, taskBoardColumnDraggingClasses, taskBoardDropIndicatorClasses, resolveLocaleText, taskBoardEmptyClasses, taskBoardColumnHeaderClasses, taskBoardWipExceededClasses, taskBoardColumnBodyClasses, taskBoardAddCardClasses, mergeTigerLocale, getTaskBoardLabels, createTouchDragTracker, moveCard, reorderColumns, setDragData, createCardDragData, getDropIndex, parseDragData, createColumnDragData, getColumnDropIndex, findColumnFromPoint, taskBoardBaseClasses } from '@expcat/tigercat-core';
4
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
+
6
+ var CardItem = React.memo(
7
+ ({
8
+ card,
9
+ column,
10
+ isDragging,
11
+ isKbGrabbed,
12
+ draggable,
13
+ dragHintText,
14
+ renderCard,
15
+ onDragStart,
16
+ onDragEnd,
17
+ onTouchStart,
18
+ onTouchMove,
19
+ onTouchEnd,
20
+ onKeyDown
21
+ }) => {
22
+ const cardClasses = classNames(
23
+ taskBoardCardClasses,
24
+ isDragging && taskBoardCardDraggingClasses,
25
+ isKbGrabbed && "ring-2 ring-[var(--tiger-primary,#2563eb)]"
26
+ );
27
+ return /* @__PURE__ */ jsx(
28
+ "div",
29
+ {
30
+ className: cardClasses,
31
+ draggable,
32
+ tabIndex: 0,
33
+ role: "listitem",
34
+ "aria-roledescription": dragHintText,
35
+ "aria-grabbed": isKbGrabbed ? "true" : void 0,
36
+ "data-tiger-taskboard-card": "",
37
+ "data-tiger-taskboard-card-id": String(card.id),
38
+ onDragStart: (e) => onDragStart(e, card, column),
39
+ onDragEnd,
40
+ onTouchStart: (e) => onTouchStart(e, card, column),
41
+ onTouchMove,
42
+ onTouchEnd,
43
+ onKeyDown: (e) => onKeyDown(e, card, column),
44
+ children: renderCard ? renderCard(card, column.id) : /* @__PURE__ */ jsxs(Fragment, { children: [
45
+ /* @__PURE__ */ jsx("div", { className: "font-medium text-sm text-[var(--tiger-text,#1f2937)]", children: card.title }),
46
+ card.description && /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-[var(--tiger-text-muted,#6b7280)] line-clamp-2", children: card.description })
47
+ ] })
48
+ }
49
+ );
50
+ },
51
+ (prev, next) => prev.card.id === next.card.id && prev.isDragging === next.isDragging && prev.isKbGrabbed === next.isKbGrabbed && prev.draggable === next.draggable && prev.card === next.card
52
+ );
53
+ CardItem.displayName = "TaskBoardCardItem";
54
+ var ColumnItem = React.memo(
55
+ ({
56
+ column,
57
+ colIndex,
58
+ isDropTarget,
59
+ isColDragging,
60
+ dropIdx,
61
+ draggable,
62
+ columnDraggable,
63
+ labels,
64
+ renderCardProp,
65
+ renderColumnHeader,
66
+ renderColumnFooter,
67
+ renderEmptyColumn,
68
+ onCardAdd,
69
+ dragType,
70
+ onCardDragStart,
71
+ onCardDragOver,
72
+ onCardDrop,
73
+ onDragEnd,
74
+ onDragLeave,
75
+ onColumnDragStart,
76
+ onColumnDragOver,
77
+ onColumnDrop,
78
+ onCardTouchStart,
79
+ onCardTouchMove,
80
+ onCardTouchEnd,
81
+ onColumnTouchStart,
82
+ onColumnTouchMove,
83
+ onColumnTouchEnd,
84
+ onCardKeyDown,
85
+ dragStateId,
86
+ kbDragStateId
87
+ }) => {
88
+ const wipOver = isWipExceeded(column);
89
+ const colClasses = classNames(
90
+ taskBoardColumnClasses,
91
+ isDropTarget && taskBoardColumnDropTargetClasses,
92
+ isColDragging && taskBoardColumnDraggingClasses
93
+ );
94
+ let cardsContent;
95
+ if (column.cards.length > 0) {
96
+ const nodes = [];
97
+ column.cards.forEach((card, i) => {
98
+ if (isDropTarget && dropIdx === i) {
99
+ nodes.push(/* @__PURE__ */ jsx("div", { className: taskBoardDropIndicatorClasses }, `drop-${i}`));
100
+ }
101
+ const isDragging = dragStateId === card.id;
102
+ const isKbGrabbed = kbDragStateId === card.id;
103
+ nodes.push(
104
+ /* @__PURE__ */ jsx(
105
+ CardItem,
106
+ {
107
+ card,
108
+ column,
109
+ isDragging,
110
+ isKbGrabbed,
111
+ draggable,
112
+ dragHintText: labels.dragHintText,
113
+ renderCard: renderCardProp,
114
+ onDragStart: onCardDragStart,
115
+ onDragEnd,
116
+ onTouchStart: onCardTouchStart,
117
+ onTouchMove: onCardTouchMove,
118
+ onTouchEnd: onCardTouchEnd,
119
+ onKeyDown: onCardKeyDown
120
+ },
121
+ String(card.id)
122
+ )
123
+ );
124
+ });
125
+ if (isDropTarget && dropIdx >= column.cards.length) {
126
+ nodes.push(/* @__PURE__ */ jsx("div", { className: taskBoardDropIndicatorClasses }, "drop-end"));
127
+ }
128
+ cardsContent = nodes;
129
+ } else {
130
+ cardsContent = isDropTarget ? /* @__PURE__ */ jsx("div", { className: taskBoardDropIndicatorClasses }, "drop-empty") : renderEmptyColumn ? renderEmptyColumn(column) : /* @__PURE__ */ jsx("div", { className: taskBoardEmptyClasses, children: resolveLocaleText(labels.emptyColumnText) });
131
+ }
132
+ const wipTitle = column.wipLimit != null ? resolveLocaleText(labels.wipLimitText.replace("{limit}", String(column.wipLimit))) : void 0;
133
+ return /* @__PURE__ */ jsxs(
134
+ "div",
135
+ {
136
+ className: colClasses,
137
+ "data-tiger-taskboard-column": "",
138
+ "data-tiger-taskboard-column-id": String(column.id),
139
+ onDragOver: dragType === "column" ? onColumnDragOver : void 0,
140
+ onDrop: dragType === "column" ? onColumnDrop : void 0,
141
+ children: [
142
+ /* @__PURE__ */ jsx(
143
+ "div",
144
+ {
145
+ className: taskBoardColumnHeaderClasses,
146
+ draggable: columnDraggable,
147
+ onDragStart: (e) => onColumnDragStart(e, column, colIndex),
148
+ onDragEnd,
149
+ onTouchStart: (e) => onColumnTouchStart(e, column, colIndex),
150
+ onTouchMove: onColumnTouchMove,
151
+ onTouchEnd: onColumnTouchEnd,
152
+ style: columnDraggable ? { cursor: "grab" } : void 0,
153
+ children: renderColumnHeader ? renderColumnHeader(column) : /* @__PURE__ */ jsxs(Fragment, { children: [
154
+ /* @__PURE__ */ jsxs("span", { className: wipOver ? taskBoardWipExceededClasses : void 0, children: [
155
+ column.title,
156
+ column.wipLimit != null ? /* @__PURE__ */ jsxs("span", { className: "ml-2 text-xs font-normal opacity-70", title: wipTitle, children: [
157
+ "(",
158
+ column.cards.length,
159
+ "/",
160
+ column.wipLimit,
161
+ ")"
162
+ ] }) : /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs font-normal opacity-50", children: column.cards.length })
163
+ ] }),
164
+ column.description && /* @__PURE__ */ jsx("span", { className: "text-xs font-normal text-[var(--tiger-text-muted,#6b7280)] truncate max-w-[120px]", children: column.description })
165
+ ] })
166
+ }
167
+ ),
168
+ /* @__PURE__ */ jsx(
169
+ "div",
170
+ {
171
+ className: taskBoardColumnBodyClasses,
172
+ role: "list",
173
+ "aria-label": column.title,
174
+ onDragOver: (e) => onCardDragOver(e, column),
175
+ onDrop: (e) => onCardDrop(e, column),
176
+ onDragLeave,
177
+ children: cardsContent
178
+ }
179
+ ),
180
+ renderColumnFooter ? renderColumnFooter(column) : onCardAdd ? /* @__PURE__ */ jsxs(
181
+ "div",
182
+ {
183
+ className: classNames(
184
+ "border-t border-[var(--tiger-border,#e5e7eb)]",
185
+ taskBoardAddCardClasses
186
+ ),
187
+ onClick: () => onCardAdd(column.id),
188
+ children: [
189
+ /* @__PURE__ */ jsx("span", { children: "+" }),
190
+ /* @__PURE__ */ jsx("span", { children: resolveLocaleText(labels.addCardText) })
191
+ ]
192
+ }
193
+ ) : null
194
+ ]
195
+ }
196
+ );
197
+ },
198
+ (prev, next) => prev.column === next.column && prev.colIndex === next.colIndex && prev.isDropTarget === next.isDropTarget && prev.isColDragging === next.isColDragging && prev.dropIdx === next.dropIdx && prev.draggable === next.draggable && prev.columnDraggable === next.columnDraggable && prev.dragType === next.dragType && prev.dragStateId === next.dragStateId && prev.kbDragStateId === next.kbDragStateId && prev.onCardAdd === next.onCardAdd
199
+ );
200
+ ColumnItem.displayName = "TaskBoardColumnItem";
201
+ var TaskBoard = ({
202
+ columns: controlledColumns,
203
+ defaultColumns = [],
204
+ draggable = true,
205
+ columnDraggable = true,
206
+ enforceWipLimit = false,
207
+ beforeCardMove,
208
+ beforeColumnMove,
209
+ onCardMove,
210
+ onColumnMove,
211
+ onColumnsChange,
212
+ onCardAdd,
213
+ renderCard: renderCardProp,
214
+ renderColumnHeader,
215
+ renderColumnFooter,
216
+ renderEmptyColumn,
217
+ locale,
218
+ className,
219
+ style,
220
+ ...rest
221
+ }) => {
222
+ const config = useTigerConfig();
223
+ const mergedLocale = useMemo(
224
+ () => mergeTigerLocale(config.locale, locale),
225
+ [config.locale, locale]
226
+ );
227
+ const labels = useMemo(() => getTaskBoardLabels(mergedLocale), [mergedLocale]);
228
+ const [innerColumns, setInnerColumns] = useState(defaultColumns);
229
+ useEffect(() => {
230
+ if (controlledColumns !== void 0) setInnerColumns(controlledColumns);
231
+ }, [controlledColumns]);
232
+ const currentColumns = controlledColumns ?? innerColumns;
233
+ const columnsRef = useRef(currentColumns);
234
+ columnsRef.current = currentColumns;
235
+ const updateColumns = useCallback(
236
+ (next) => {
237
+ setInnerColumns(next);
238
+ onColumnsChange?.(next);
239
+ },
240
+ [onColumnsChange]
241
+ );
242
+ const [dragState, setDragState] = useState(null);
243
+ const [dropTargetColumnId, setDropTargetColumnId] = useState(null);
244
+ const [dropIdx, setDropIdx] = useState(-1);
245
+ const [kbDragState, setKbDragState] = useState(null);
246
+ const boardRef = useRef(null);
247
+ const touchTrackerRef = useRef(null);
248
+ const touchRafRef = useRef(0);
249
+ const beforeCardMoveRef = useRef(beforeCardMove);
250
+ beforeCardMoveRef.current = beforeCardMove;
251
+ const beforeColumnMoveRef = useRef(beforeColumnMove);
252
+ beforeColumnMoveRef.current = beforeColumnMove;
253
+ const onCardMoveRef = useRef(onCardMove);
254
+ onCardMoveRef.current = onCardMove;
255
+ const onColumnMoveRef = useRef(onColumnMove);
256
+ onColumnMoveRef.current = onColumnMove;
257
+ const enforceWipLimitRef = useRef(enforceWipLimit);
258
+ enforceWipLimitRef.current = enforceWipLimit;
259
+ useEffect(() => {
260
+ if (typeof window !== "undefined" && ("ontouchstart" in window || navigator.maxTouchPoints > 0)) {
261
+ touchTrackerRef.current = createTouchDragTracker();
262
+ }
263
+ return () => cancelAnimationFrame(touchRafRef.current);
264
+ }, []);
265
+ const resetDrag = useCallback(() => {
266
+ setDragState(null);
267
+ setDropTargetColumnId(null);
268
+ setDropIdx(-1);
269
+ }, []);
270
+ const applyCardMove = useCallback(
271
+ async (cardId, fromColumnId, toColumnId, toIdx) => {
272
+ const result = moveCard(columnsRef.current, cardId, fromColumnId, toColumnId, toIdx, {
273
+ enforceWipLimit: enforceWipLimitRef.current
274
+ });
275
+ if (!result) return;
276
+ if (beforeCardMoveRef.current) {
277
+ const ok = await beforeCardMoveRef.current(result.event);
278
+ if (!ok) return;
279
+ }
280
+ updateColumns(result.columns);
281
+ onCardMoveRef.current?.(result.event);
282
+ },
283
+ [updateColumns]
284
+ );
285
+ const applyColumnMove = useCallback(
286
+ async (fromIdx, toIdx) => {
287
+ const cols = columnsRef.current;
288
+ const result = reorderColumns(cols, fromIdx, Math.min(toIdx, cols.length - 1));
289
+ if (!result) return;
290
+ if (beforeColumnMoveRef.current) {
291
+ const ok = await beforeColumnMoveRef.current(result.event);
292
+ if (!ok) return;
293
+ }
294
+ updateColumns(result.columns);
295
+ onColumnMoveRef.current?.(result.event);
296
+ },
297
+ [updateColumns]
298
+ );
299
+ const handleCardDragStart = useCallback(
300
+ (e, card, column) => {
301
+ if (!draggable) return;
302
+ const idx = column.cards.findIndex((c) => c.id === card.id);
303
+ setDragData(e.dataTransfer, createCardDragData(card.id, column.id, idx));
304
+ setDragState({ type: "card", id: card.id, fromColumnId: column.id, fromIndex: idx });
305
+ },
306
+ [draggable]
307
+ );
308
+ const handleCardDragOver = useCallback(
309
+ (e, column) => {
310
+ e.preventDefault();
311
+ if (!dragState || dragState.type !== "card") return;
312
+ setDropTargetColumnId(column.id);
313
+ const target = e.currentTarget;
314
+ const cardEls = target.querySelectorAll("[data-tiger-taskboard-card]");
315
+ const rects = [];
316
+ cardEls.forEach((el) => rects.push(el.getBoundingClientRect()));
317
+ setDropIdx(getDropIndex(e.clientY, rects));
318
+ },
319
+ [dragState]
320
+ );
321
+ const handleCardDrop = useCallback(
322
+ (e, column) => {
323
+ e.preventDefault();
324
+ const data = parseDragData(e.dataTransfer);
325
+ if (!data || data.type !== "card") return;
326
+ applyCardMove(
327
+ data.cardId,
328
+ data.columnId,
329
+ column.id,
330
+ dropIdx >= 0 ? dropIdx : column.cards.length
331
+ );
332
+ resetDrag();
333
+ },
334
+ [dropIdx, applyCardMove, resetDrag]
335
+ );
336
+ const handleColumnDragStart = useCallback(
337
+ (e, column, index) => {
338
+ if (!columnDraggable) return;
339
+ setDragData(e.dataTransfer, createColumnDragData(column.id, index));
340
+ setDragState({ type: "column", id: column.id, fromIndex: index });
341
+ },
342
+ [columnDraggable]
343
+ );
344
+ const handleColumnDragOver = useCallback(
345
+ (e) => {
346
+ if (!dragState || dragState.type !== "column") return;
347
+ e.preventDefault();
348
+ },
349
+ [dragState]
350
+ );
351
+ const handleColumnDrop = useCallback(
352
+ (e) => {
353
+ e.preventDefault();
354
+ const data = parseDragData(e.dataTransfer);
355
+ if (!data || data.type !== "column") return;
356
+ const colEls = boardRef.current?.querySelectorAll("[data-tiger-taskboard-column]");
357
+ if (!colEls) return;
358
+ const rects = [];
359
+ colEls.forEach((el) => rects.push(el.getBoundingClientRect()));
360
+ const toIdx = getColumnDropIndex(e.clientX, rects);
361
+ applyColumnMove(data.index, toIdx);
362
+ resetDrag();
363
+ },
364
+ [applyColumnMove, resetDrag]
365
+ );
366
+ const handleDragEnd = useCallback(() => resetDrag(), [resetDrag]);
367
+ const handleDragLeave = useCallback(
368
+ (e) => {
369
+ const related = e.relatedTarget;
370
+ if (!related || !e.currentTarget.contains(related)) {
371
+ if (dragState?.type === "card") {
372
+ setDropTargetColumnId(null);
373
+ setDropIdx(-1);
374
+ }
375
+ }
376
+ },
377
+ [dragState]
378
+ );
379
+ const handleTouchStart = useCallback(
380
+ (e, card, column) => {
381
+ if (!draggable || !touchTrackerRef.current) return;
382
+ const idx = column.cards.findIndex((c) => c.id === card.id);
383
+ touchTrackerRef.current.onTouchStart(e.nativeEvent, e.currentTarget);
384
+ setDragState({ type: "card", id: card.id, fromColumnId: column.id, fromIndex: idx });
385
+ },
386
+ [draggable]
387
+ );
388
+ const handleTouchMove = useCallback(
389
+ (e) => {
390
+ if (!touchTrackerRef.current || !dragState) return;
391
+ touchTrackerRef.current.onTouchMove(e.nativeEvent);
392
+ cancelAnimationFrame(touchRafRef.current);
393
+ touchRafRef.current = requestAnimationFrame(() => {
394
+ const st = touchTrackerRef.current.getState();
395
+ if (dragState?.type === "card") {
396
+ const colEl = findColumnFromPoint(st.currentX, st.currentY, boardRef.current);
397
+ if (colEl) {
398
+ const colId = colEl.getAttribute("data-tiger-taskboard-column-id");
399
+ setDropTargetColumnId(colId ?? null);
400
+ const cardEls = colEl.querySelectorAll("[data-tiger-taskboard-card]");
401
+ const rects = [];
402
+ cardEls.forEach((el) => rects.push(el.getBoundingClientRect()));
403
+ setDropIdx(getDropIndex(st.currentY, rects));
404
+ }
405
+ }
406
+ });
407
+ },
408
+ [dragState]
409
+ );
410
+ const handleTouchEnd = useCallback(() => {
411
+ if (!touchTrackerRef.current || !dragState) return;
412
+ touchTrackerRef.current.onTouchEnd();
413
+ if (dragState.type === "card" && dropTargetColumnId != null) {
414
+ applyCardMove(
415
+ dragState.id,
416
+ dragState.fromColumnId,
417
+ dropTargetColumnId,
418
+ dropIdx >= 0 ? dropIdx : 0
419
+ );
420
+ }
421
+ resetDrag();
422
+ }, [dragState, dropIdx, dropTargetColumnId, applyCardMove, resetDrag]);
423
+ const handleColumnTouchStart = useCallback(
424
+ (e, column, index) => {
425
+ if (!columnDraggable || !touchTrackerRef.current) return;
426
+ touchTrackerRef.current.onTouchStart(e.nativeEvent, e.currentTarget);
427
+ setDragState({ type: "column", id: column.id, fromIndex: index });
428
+ },
429
+ [columnDraggable]
430
+ );
431
+ const handleColumnTouchMove = useCallback(
432
+ (e) => {
433
+ if (!touchTrackerRef.current || !dragState || dragState.type !== "column") return;
434
+ touchTrackerRef.current.onTouchMove(e.nativeEvent);
435
+ },
436
+ [dragState]
437
+ );
438
+ const handleColumnTouchEnd = useCallback(() => {
439
+ if (!touchTrackerRef.current || !dragState || dragState.type !== "column") return;
440
+ const st = touchTrackerRef.current.onTouchEnd();
441
+ const colEls = boardRef.current?.querySelectorAll("[data-tiger-taskboard-column]");
442
+ if (!colEls) {
443
+ resetDrag();
444
+ return;
445
+ }
446
+ const rects = [];
447
+ colEls.forEach((el) => rects.push(el.getBoundingClientRect()));
448
+ const toIdx = getColumnDropIndex(st.currentX, rects);
449
+ applyColumnMove(dragState.fromIndex, Math.min(toIdx, columnsRef.current.length - 1));
450
+ resetDrag();
451
+ }, [dragState, applyColumnMove, resetDrag]);
452
+ const handleCardKeyDown = useCallback(
453
+ (e, card, column) => {
454
+ if (!draggable) return;
455
+ if (e.key === "Enter" || e.key === " ") {
456
+ e.preventDefault();
457
+ if (!kbDragState) {
458
+ const idx = column.cards.findIndex((c) => c.id === card.id);
459
+ setKbDragState({ type: "card", id: card.id, fromColumnId: column.id, fromIndex: idx });
460
+ } else {
461
+ const cardIdx = column.cards.findIndex((c) => c.id === card.id);
462
+ if (kbDragState.fromColumnId !== void 0) {
463
+ applyCardMove(kbDragState.id, kbDragState.fromColumnId, column.id, cardIdx);
464
+ }
465
+ setKbDragState(null);
466
+ }
467
+ return;
468
+ }
469
+ if (e.key === "Escape" && kbDragState) {
470
+ e.preventDefault();
471
+ setKbDragState(null);
472
+ }
473
+ },
474
+ [draggable, kbDragState, applyCardMove]
475
+ );
476
+ const wrapperClasses = useMemo(() => classNames(taskBoardBaseClasses, className), [className]);
477
+ const dragType = dragState?.type ?? null;
478
+ const dragStateId = dragState?.type === "card" ? dragState.id : null;
479
+ const kbDragStateId = kbDragState?.id ?? null;
480
+ return /* @__PURE__ */ jsx(
481
+ "div",
482
+ {
483
+ ref: boardRef,
484
+ className: wrapperClasses,
485
+ style,
486
+ role: "region",
487
+ "aria-label": resolveLocaleText(labels.boardAriaLabel),
488
+ "data-tiger-task-board": "",
489
+ ...rest,
490
+ children: currentColumns.map((col, i) => {
491
+ const isDropTarget = dragState?.type === "card" && dropTargetColumnId === col.id;
492
+ const isColDragging = dragState?.type === "column" && dragState.id === col.id;
493
+ return /* @__PURE__ */ jsx(
494
+ ColumnItem,
495
+ {
496
+ column: col,
497
+ colIndex: i,
498
+ isDropTarget,
499
+ isColDragging,
500
+ dropIdx: isDropTarget ? dropIdx : -1,
501
+ draggable,
502
+ columnDraggable,
503
+ labels,
504
+ renderCardProp,
505
+ renderColumnHeader,
506
+ renderColumnFooter,
507
+ renderEmptyColumn,
508
+ onCardAdd,
509
+ dragType,
510
+ onCardDragStart: handleCardDragStart,
511
+ onCardDragOver: handleCardDragOver,
512
+ onCardDrop: handleCardDrop,
513
+ onDragEnd: handleDragEnd,
514
+ onDragLeave: handleDragLeave,
515
+ onColumnDragStart: handleColumnDragStart,
516
+ onColumnDragOver: handleColumnDragOver,
517
+ onColumnDrop: handleColumnDrop,
518
+ onCardTouchStart: handleTouchStart,
519
+ onCardTouchMove: handleTouchMove,
520
+ onCardTouchEnd: handleTouchEnd,
521
+ onColumnTouchStart: handleColumnTouchStart,
522
+ onColumnTouchMove: handleColumnTouchMove,
523
+ onColumnTouchEnd: handleColumnTouchEnd,
524
+ onCardKeyDown: handleCardKeyDown,
525
+ dragStateId,
526
+ kbDragStateId
527
+ },
528
+ String(col.id)
529
+ );
530
+ })
531
+ }
532
+ );
533
+ };
534
+ var TaskBoard_default = TaskBoard;
535
+
536
+ export { TaskBoard, TaskBoard_default };
@@ -0,0 +1,142 @@
1
+ import { Modal } from './chunk-JNLX47UL.mjs';
2
+ import { ImageCropper } from './chunk-2EOXY2LP.mjs';
3
+ import { Button } from './chunk-ENSLMM3L.mjs';
4
+ import { useRef, useState, useCallback, useMemo } from 'react';
5
+ import { classNames, cropUploadTriggerDisabledClasses, cropUploadTriggerClasses, uploadPlusIconPath } from '@expcat/tigercat-core';
6
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
+
8
+ var CropUpload = ({
9
+ accept = "image/*",
10
+ disabled = false,
11
+ maxSize,
12
+ cropperProps,
13
+ modalTitle = "\u88C1\u526A\u56FE\u7247",
14
+ modalWidth = 520,
15
+ className,
16
+ children,
17
+ onCropComplete,
18
+ onError
19
+ }) => {
20
+ const fileInputRef = useRef(null);
21
+ const cropperRef = useRef(null);
22
+ const [modalVisible, setModalVisible] = useState(false);
23
+ const [imageSrc, setImageSrc] = useState("");
24
+ const [cropping, setCropping] = useState(false);
25
+ const handleTriggerClick = useCallback(() => {
26
+ if (disabled) return;
27
+ fileInputRef.current?.click();
28
+ }, [disabled]);
29
+ const handleFileChange = useCallback(
30
+ (e) => {
31
+ const file = e.target.files?.[0];
32
+ if (!file) return;
33
+ if (maxSize && file.size > maxSize) {
34
+ onError?.(new Error(`File size exceeds maximum of ${maxSize} bytes`));
35
+ e.target.value = "";
36
+ return;
37
+ }
38
+ const reader = new FileReader();
39
+ reader.onload = (ev) => {
40
+ setImageSrc(ev.target?.result);
41
+ setModalVisible(true);
42
+ };
43
+ reader.readAsDataURL(file);
44
+ e.target.value = "";
45
+ },
46
+ [maxSize, onError]
47
+ );
48
+ const handleConfirm = useCallback(async () => {
49
+ if (!cropperRef.current) return;
50
+ setCropping(true);
51
+ try {
52
+ const result = await cropperRef.current.getCropResult();
53
+ onCropComplete?.(result);
54
+ setModalVisible(false);
55
+ } catch (err) {
56
+ onError?.(err);
57
+ } finally {
58
+ setCropping(false);
59
+ }
60
+ }, [onCropComplete, onError]);
61
+ const handleCancel = useCallback(() => {
62
+ setModalVisible(false);
63
+ setImageSrc("");
64
+ }, []);
65
+ const triggerClasses = useMemo(
66
+ () => classNames(disabled ? cropUploadTriggerDisabledClasses : cropUploadTriggerClasses, className),
67
+ [disabled, className]
68
+ );
69
+ const handleKeyDown = useCallback(
70
+ (e) => {
71
+ if (e.key === "Enter" || e.key === " ") {
72
+ e.preventDefault();
73
+ handleTriggerClick();
74
+ }
75
+ },
76
+ [handleTriggerClick]
77
+ );
78
+ return /* @__PURE__ */ jsxs("div", { className: "tiger-crop-upload inline-block", children: [
79
+ /* @__PURE__ */ jsx(
80
+ "input",
81
+ {
82
+ ref: fileInputRef,
83
+ type: "file",
84
+ accept,
85
+ style: { display: "none" },
86
+ onChange: handleFileChange
87
+ }
88
+ ),
89
+ /* @__PURE__ */ jsx(
90
+ "div",
91
+ {
92
+ className: triggerClasses,
93
+ onClick: handleTriggerClick,
94
+ role: "button",
95
+ tabIndex: disabled ? -1 : 0,
96
+ "aria-label": "Select image to crop and upload",
97
+ "aria-disabled": disabled ? "true" : void 0,
98
+ onKeyDown: handleKeyDown,
99
+ children: children || /* @__PURE__ */ jsxs(Fragment, { children: [
100
+ /* @__PURE__ */ jsx(
101
+ "svg",
102
+ {
103
+ className: "w-5 h-5",
104
+ xmlns: "http://www.w3.org/2000/svg",
105
+ fill: "none",
106
+ viewBox: "0 0 24 24",
107
+ stroke: "currentColor",
108
+ children: /* @__PURE__ */ jsx(
109
+ "path",
110
+ {
111
+ strokeLinecap: "round",
112
+ strokeLinejoin: "round",
113
+ strokeWidth: "2",
114
+ d: uploadPlusIconPath
115
+ }
116
+ )
117
+ }
118
+ ),
119
+ /* @__PURE__ */ jsx("span", { children: "\u9009\u62E9\u56FE\u7247" })
120
+ ] })
121
+ }
122
+ ),
123
+ /* @__PURE__ */ jsx(
124
+ Modal,
125
+ {
126
+ visible: modalVisible,
127
+ size: "lg",
128
+ title: modalTitle,
129
+ closable: true,
130
+ maskClosable: false,
131
+ onClose: handleCancel,
132
+ footer: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-3", children: [
133
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: handleCancel, children: "\u53D6\u6D88" }),
134
+ /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, loading: cropping, children: "\u786E\u8BA4\u88C1\u526A" })
135
+ ] }),
136
+ children: imageSrc && /* @__PURE__ */ jsx(ImageCropper, { ref: cropperRef, src: imageSrc, ...cropperProps })
137
+ }
138
+ )
139
+ ] });
140
+ };
141
+
142
+ export { CropUpload };