@expcat/tigercat-vue 0.3.70 → 0.4.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 (43) hide show
  1. package/dist/{chunk-ZTJTIQZY.mjs → chunk-DEFEAEYE.mjs} +126 -6
  2. package/dist/{chunk-KUJ75OHX.js → chunk-ESALMEHU.js} +10 -9
  3. package/dist/{chunk-KVZLGW45.js → chunk-ETTYERGO.js} +14 -5
  4. package/dist/chunk-HFBRO2IF.mjs +440 -0
  5. package/dist/chunk-HK2TAPQX.js +334 -0
  6. package/dist/{chunk-YZK2HXRT.js → chunk-LGRUMMOG.js} +2 -2
  7. package/dist/chunk-LW3LFCRZ.mjs +331 -0
  8. package/dist/{chunk-ND4XDRYR.mjs → chunk-TCJBN2DA.mjs} +1 -1
  9. package/dist/{chunk-7FCHU5KV.mjs → chunk-TTDBR2B4.mjs} +11 -10
  10. package/dist/{chunk-RKPYLBPU.mjs → chunk-WM4ESIHG.mjs} +15 -6
  11. package/dist/{chunk-3PQIZBT5.js → chunk-WV3Y45YK.js} +125 -5
  12. package/dist/chunk-YQGKXFV5.js +443 -0
  13. package/dist/components/ActivityFeed.js +4 -4
  14. package/dist/components/ActivityFeed.mjs +2 -2
  15. package/dist/components/Collapse.d.mts +1 -1
  16. package/dist/components/Collapse.d.ts +1 -1
  17. package/dist/components/DataTableWithToolbar.js +4 -4
  18. package/dist/components/DataTableWithToolbar.mjs +2 -2
  19. package/dist/components/InputNumber.d.mts +170 -0
  20. package/dist/components/InputNumber.d.ts +170 -0
  21. package/dist/components/InputNumber.js +17 -0
  22. package/dist/components/InputNumber.mjs +2 -0
  23. package/dist/components/Sidebar.d.mts +20 -0
  24. package/dist/components/Sidebar.d.ts +20 -0
  25. package/dist/components/Sidebar.js +3 -3
  26. package/dist/components/Sidebar.mjs +1 -1
  27. package/dist/components/SubMenu.js +3 -3
  28. package/dist/components/SubMenu.mjs +1 -1
  29. package/dist/components/Table.d.mts +16 -2
  30. package/dist/components/Table.d.ts +16 -2
  31. package/dist/components/Table.js +3 -3
  32. package/dist/components/Table.mjs +1 -1
  33. package/dist/components/TaskBoard.d.mts +129 -0
  34. package/dist/components/TaskBoard.d.ts +129 -0
  35. package/dist/components/TaskBoard.js +18 -0
  36. package/dist/components/TaskBoard.mjs +3 -0
  37. package/dist/index.d.mts +2 -0
  38. package/dist/index.d.ts +2 -0
  39. package/dist/index.js +50 -40
  40. package/dist/index.mjs +13 -11
  41. package/package.json +2 -2
  42. package/dist/{chunk-NGW5UMAN.js → chunk-EBTLMVDJ.js} +1 -1
  43. package/dist/{chunk-D7VMY6WX.mjs → chunk-RVEEEDJQ.mjs} +1 -1
@@ -0,0 +1,440 @@
1
+ import { useTigerConfig } from './chunk-TRDG56CB.mjs';
2
+ import { defineComponent, computed, ref, watch, onMounted, onBeforeUnmount, h } from 'vue';
3
+ import { mergeTigerLocale, getTaskBoardLabels, classNames, taskBoardBaseClasses, coerceClassValue, mergeStyleValues, resolveLocaleText, createTouchDragTracker, isWipExceeded, taskBoardColumnClasses, taskBoardColumnDropTargetClasses, taskBoardColumnDraggingClasses, taskBoardWipExceededClasses, taskBoardColumnHeaderClasses, taskBoardDropIndicatorClasses, taskBoardEmptyClasses, taskBoardColumnBodyClasses, taskBoardAddCardClasses, getColumnDropIndex, setDragData, createColumnDragData, taskBoardCardClasses, taskBoardCardDraggingClasses, parseDragData, getDropIndex, reorderColumns, findColumnFromPoint, createCardDragData, moveCard } from '@expcat/tigercat-core';
4
+
5
+ var TaskBoard = defineComponent({
6
+ name: "TigerTaskBoard",
7
+ inheritAttrs: false,
8
+ props: {
9
+ columns: {
10
+ type: Array,
11
+ default: void 0
12
+ },
13
+ defaultColumns: {
14
+ type: Array,
15
+ default: () => []
16
+ },
17
+ draggable: {
18
+ type: Boolean,
19
+ default: true
20
+ },
21
+ columnDraggable: {
22
+ type: Boolean,
23
+ default: true
24
+ },
25
+ enforceWipLimit: {
26
+ type: Boolean,
27
+ default: false
28
+ },
29
+ beforeCardMove: {
30
+ type: Function,
31
+ default: void 0
32
+ },
33
+ beforeColumnMove: {
34
+ type: Function,
35
+ default: void 0
36
+ },
37
+ onCardAdd: {
38
+ type: Function,
39
+ default: void 0
40
+ },
41
+ locale: {
42
+ type: Object,
43
+ default: void 0
44
+ },
45
+ className: {
46
+ type: String,
47
+ default: void 0
48
+ },
49
+ style: {
50
+ type: Object,
51
+ default: void 0
52
+ }
53
+ },
54
+ emits: ["card-move", "column-move", "card-add", "update:columns"],
55
+ setup(props, { slots, attrs, emit }) {
56
+ const config = useTigerConfig();
57
+ const mergedLocale = computed(() => mergeTigerLocale(config.value.locale, props.locale));
58
+ const labels = computed(() => getTaskBoardLabels(mergedLocale.value));
59
+ const innerColumns = ref(props.columns ?? props.defaultColumns ?? []);
60
+ watch(
61
+ () => props.columns,
62
+ (value) => {
63
+ if (value !== void 0) innerColumns.value = value;
64
+ }
65
+ );
66
+ watch(
67
+ () => props.defaultColumns,
68
+ (value) => {
69
+ if (props.columns === void 0 && value !== void 0) {
70
+ innerColumns.value = value;
71
+ }
72
+ }
73
+ );
74
+ const currentColumns = computed(() => props.columns ?? innerColumns.value);
75
+ const updateColumns = (next) => {
76
+ innerColumns.value = next;
77
+ emit("update:columns", next);
78
+ };
79
+ const dragState = ref(null);
80
+ const dropTargetColumnId = ref(null);
81
+ const dropIndex = ref(-1);
82
+ const boardRef = ref(null);
83
+ let touchTracker = null;
84
+ let touchRaf = 0;
85
+ const isTouchDevice = () => typeof window !== "undefined" && ("ontouchstart" in window || navigator.maxTouchPoints > 0);
86
+ const applyCardMove = async (cardId, fromColumnId, toColumnId, toIdx) => {
87
+ const result = moveCard(currentColumns.value, cardId, fromColumnId, toColumnId, toIdx, {
88
+ enforceWipLimit: props.enforceWipLimit
89
+ });
90
+ if (!result) return;
91
+ if (props.beforeCardMove) {
92
+ const ok = await props.beforeCardMove(result.event);
93
+ if (!ok) return;
94
+ }
95
+ updateColumns(result.columns);
96
+ emit("card-move", result.event);
97
+ };
98
+ const applyColumnMove = async (fromIdx, toIdx) => {
99
+ const result = reorderColumns(
100
+ currentColumns.value,
101
+ fromIdx,
102
+ Math.min(toIdx, currentColumns.value.length - 1)
103
+ );
104
+ if (!result) return;
105
+ if (props.beforeColumnMove) {
106
+ const ok = await props.beforeColumnMove(result.event);
107
+ if (!ok) return;
108
+ }
109
+ updateColumns(result.columns);
110
+ emit("column-move", result.event);
111
+ };
112
+ const handleCardDragStart = (e, card, column) => {
113
+ if (!props.draggable || !e.dataTransfer) return;
114
+ const idx = column.cards.findIndex((c) => c.id === card.id);
115
+ setDragData(e.dataTransfer, createCardDragData(card.id, column.id, idx));
116
+ dragState.value = { type: "card", id: card.id, fromColumnId: column.id, fromIndex: idx };
117
+ };
118
+ const handleCardDragOver = (e, column) => {
119
+ e.preventDefault();
120
+ if (!dragState.value || dragState.value.type !== "card") return;
121
+ dropTargetColumnId.value = column.id;
122
+ const target = e.currentTarget;
123
+ const cardEls = target.querySelectorAll("[data-tiger-taskboard-card]");
124
+ const rects = [];
125
+ cardEls.forEach((el) => rects.push(el.getBoundingClientRect()));
126
+ dropIndex.value = getDropIndex(e.clientY, rects);
127
+ };
128
+ const handleCardDrop = (e, column) => {
129
+ e.preventDefault();
130
+ if (!e.dataTransfer) return;
131
+ const data = parseDragData(e.dataTransfer);
132
+ if (!data || data.type !== "card") return;
133
+ applyCardMove(
134
+ data.cardId,
135
+ data.columnId,
136
+ column.id,
137
+ dropIndex.value >= 0 ? dropIndex.value : column.cards.length
138
+ );
139
+ resetDragState();
140
+ };
141
+ const handleColumnDragStart = (e, column, index) => {
142
+ if (!props.columnDraggable || !e.dataTransfer) return;
143
+ setDragData(e.dataTransfer, createColumnDragData(column.id, index));
144
+ dragState.value = { type: "column", id: column.id, fromIndex: index };
145
+ };
146
+ const handleColumnDragOver = (e) => {
147
+ if (!dragState.value || dragState.value.type !== "column") return;
148
+ e.preventDefault();
149
+ };
150
+ const handleColumnDrop = (e) => {
151
+ e.preventDefault();
152
+ if (!e.dataTransfer) return;
153
+ const data = parseDragData(e.dataTransfer);
154
+ if (!data || data.type !== "column") return;
155
+ const colEls = boardRef.value?.querySelectorAll("[data-tiger-taskboard-column]");
156
+ if (!colEls) return;
157
+ const rects = [];
158
+ colEls.forEach((el) => rects.push(el.getBoundingClientRect()));
159
+ const toIdx = getColumnDropIndex(e.clientX, rects);
160
+ applyColumnMove(data.index, toIdx);
161
+ resetDragState();
162
+ };
163
+ const handleDragEnd = () => {
164
+ resetDragState();
165
+ };
166
+ const handleDragLeave = (e) => {
167
+ const related = e.relatedTarget;
168
+ if (!related || !e.currentTarget.contains(related)) {
169
+ if (dragState.value?.type === "card") {
170
+ dropTargetColumnId.value = null;
171
+ dropIndex.value = -1;
172
+ }
173
+ }
174
+ };
175
+ const resetDragState = () => {
176
+ dragState.value = null;
177
+ dropTargetColumnId.value = null;
178
+ dropIndex.value = -1;
179
+ };
180
+ const setupTouch = () => {
181
+ if (!isTouchDevice()) return;
182
+ touchTracker = createTouchDragTracker();
183
+ };
184
+ const handleTouchStart = (e, card, column) => {
185
+ if (!props.draggable || !touchTracker) return;
186
+ const idx = column.cards.findIndex((c) => c.id === card.id);
187
+ touchTracker.onTouchStart(e, e.currentTarget);
188
+ dragState.value = { type: "card", id: card.id, fromColumnId: column.id, fromIndex: idx };
189
+ };
190
+ const handleTouchMove = (e) => {
191
+ if (!touchTracker || !dragState.value) return;
192
+ touchTracker.onTouchMove(e);
193
+ cancelAnimationFrame(touchRaf);
194
+ touchRaf = requestAnimationFrame(() => {
195
+ const st = touchTracker.getState();
196
+ if (dragState.value?.type === "card") {
197
+ const colEl = findColumnFromPoint(st.currentX, st.currentY, boardRef.value);
198
+ if (colEl) {
199
+ const colId = colEl.getAttribute("data-tiger-taskboard-column-id");
200
+ dropTargetColumnId.value = colId ?? null;
201
+ const cardEls = colEl.querySelectorAll("[data-tiger-taskboard-card]");
202
+ const rects = [];
203
+ cardEls.forEach((el) => rects.push(el.getBoundingClientRect()));
204
+ dropIndex.value = getDropIndex(st.currentY, rects);
205
+ }
206
+ }
207
+ });
208
+ };
209
+ const handleTouchEnd = () => {
210
+ if (!touchTracker || !dragState.value) return;
211
+ touchTracker.onTouchEnd();
212
+ if (dragState.value.type === "card" && dropTargetColumnId.value != null) {
213
+ applyCardMove(
214
+ dragState.value.id,
215
+ dragState.value.fromColumnId,
216
+ dropTargetColumnId.value,
217
+ dropIndex.value >= 0 ? dropIndex.value : 0
218
+ );
219
+ }
220
+ resetDragState();
221
+ };
222
+ const handleColumnTouchStart = (e, column, index) => {
223
+ if (!props.columnDraggable || !touchTracker) return;
224
+ touchTracker.onTouchStart(e, e.currentTarget);
225
+ dragState.value = { type: "column", id: column.id, fromIndex: index };
226
+ };
227
+ const handleColumnTouchMove = (e) => {
228
+ if (!touchTracker || !dragState.value || dragState.value.type !== "column") return;
229
+ touchTracker.onTouchMove(e);
230
+ };
231
+ const handleColumnTouchEnd = () => {
232
+ if (!touchTracker || !dragState.value || dragState.value.type !== "column") return;
233
+ const st = touchTracker.onTouchEnd();
234
+ const colEls = boardRef.value?.querySelectorAll("[data-tiger-taskboard-column]");
235
+ if (!colEls) {
236
+ resetDragState();
237
+ return;
238
+ }
239
+ const rects = [];
240
+ colEls.forEach((el) => rects.push(el.getBoundingClientRect()));
241
+ const toIdx = getColumnDropIndex(st.currentX, rects);
242
+ applyColumnMove(dragState.value.fromIndex, Math.min(toIdx, currentColumns.value.length - 1));
243
+ resetDragState();
244
+ };
245
+ const kbDragState = ref(null);
246
+ const handleCardKeyDown = (e, card, column) => {
247
+ if (!props.draggable) return;
248
+ if (e.key === "Enter" || e.key === " ") {
249
+ e.preventDefault();
250
+ if (!kbDragState.value) {
251
+ const idx = column.cards.findIndex((c) => c.id === card.id);
252
+ kbDragState.value = { type: "card", id: card.id, fromColumnId: column.id, fromIndex: idx };
253
+ } else {
254
+ const cardIdx = column.cards.findIndex((c) => c.id === card.id);
255
+ if (kbDragState.value.fromColumnId !== void 0) {
256
+ applyCardMove(kbDragState.value.id, kbDragState.value.fromColumnId, column.id, cardIdx);
257
+ }
258
+ kbDragState.value = null;
259
+ }
260
+ return;
261
+ }
262
+ if (e.key === "Escape" && kbDragState.value) {
263
+ e.preventDefault();
264
+ kbDragState.value = null;
265
+ }
266
+ };
267
+ onMounted(() => {
268
+ setupTouch();
269
+ });
270
+ onBeforeUnmount(() => {
271
+ cancelAnimationFrame(touchRaf);
272
+ });
273
+ const wrapperClasses = computed(
274
+ () => classNames(
275
+ taskBoardBaseClasses,
276
+ props.className,
277
+ coerceClassValue(attrs.class)
278
+ )
279
+ );
280
+ const wrapperStyle = computed(
281
+ () => mergeStyleValues(attrs.style, props.style)
282
+ );
283
+ const renderCard = (card, column) => {
284
+ const isDragging = dragState.value?.type === "card" && dragState.value.id === card.id;
285
+ const isKbGrabbed = kbDragState.value?.id === card.id;
286
+ const cardClasses = classNames(
287
+ taskBoardCardClasses,
288
+ isDragging && taskBoardCardDraggingClasses,
289
+ isKbGrabbed && "ring-2 ring-[var(--tiger-primary,#2563eb)]"
290
+ );
291
+ const cardAttrs = {
292
+ key: String(card.id),
293
+ class: cardClasses,
294
+ draggable: props.draggable,
295
+ tabindex: 0,
296
+ role: "listitem",
297
+ "aria-roledescription": labels.value.dragHintText,
298
+ "aria-grabbed": isKbGrabbed ? "true" : void 0,
299
+ "data-tiger-taskboard-card": "",
300
+ "data-tiger-taskboard-card-id": String(card.id),
301
+ onDragstart: (e) => handleCardDragStart(e, card, column),
302
+ onDragend: handleDragEnd,
303
+ onTouchstart: (e) => handleTouchStart(e, card, column),
304
+ onTouchmove: handleTouchMove,
305
+ onTouchend: handleTouchEnd,
306
+ onKeydown: (e) => handleCardKeyDown(e, card, column)
307
+ };
308
+ if (slots.card) {
309
+ return h("div", cardAttrs, slots.card({ card, column, isDragging }));
310
+ }
311
+ return h("div", cardAttrs, [
312
+ h("div", { class: "font-medium text-sm text-[var(--tiger-text,#1f2937)]" }, card.title),
313
+ card.description ? h(
314
+ "div",
315
+ { class: "mt-1 text-xs text-[var(--tiger-text-muted,#6b7280)] line-clamp-2" },
316
+ card.description
317
+ ) : null
318
+ ]);
319
+ };
320
+ const renderColumnNode = (column, colIndex) => {
321
+ const isDropTarget = dragState.value?.type === "card" && dropTargetColumnId.value === column.id;
322
+ const isColDragging = dragState.value?.type === "column" && dragState.value.id === column.id;
323
+ const wipOver = isWipExceeded(column);
324
+ const colClasses = classNames(
325
+ taskBoardColumnClasses,
326
+ isDropTarget && taskBoardColumnDropTargetClasses,
327
+ isColDragging && taskBoardColumnDraggingClasses
328
+ );
329
+ const headerContent = slots["column-header"] ? slots["column-header"]({ column }) : [
330
+ h("span", { class: wipOver ? taskBoardWipExceededClasses : void 0 }, [
331
+ column.title,
332
+ column.wipLimit != null ? h(
333
+ "span",
334
+ {
335
+ class: "ml-2 text-xs font-normal opacity-70",
336
+ title: resolveLocaleText(
337
+ labels.value.wipLimitText.replace("{limit}", String(column.wipLimit))
338
+ )
339
+ },
340
+ `(${column.cards.length}/${column.wipLimit})`
341
+ ) : h(
342
+ "span",
343
+ { class: "ml-2 text-xs font-normal opacity-50" },
344
+ String(column.cards.length)
345
+ )
346
+ ]),
347
+ column.description ? h(
348
+ "span",
349
+ {
350
+ class: "text-xs font-normal text-[var(--tiger-text-muted,#6b7280)] truncate max-w-[120px]"
351
+ },
352
+ column.description
353
+ ) : null
354
+ ];
355
+ const header = h(
356
+ "div",
357
+ {
358
+ class: taskBoardColumnHeaderClasses,
359
+ draggable: props.columnDraggable,
360
+ onDragstart: (e) => handleColumnDragStart(e, column, colIndex),
361
+ onDragend: handleDragEnd,
362
+ onTouchstart: (e) => handleColumnTouchStart(e, column, colIndex),
363
+ onTouchmove: handleColumnTouchMove,
364
+ onTouchend: handleColumnTouchEnd,
365
+ style: props.columnDraggable ? "cursor: grab" : void 0
366
+ },
367
+ headerContent
368
+ );
369
+ const cards = column.cards.length > 0 ? column.cards.flatMap((card, i) => {
370
+ const nodes = [];
371
+ if (isDropTarget && dropIndex.value === i) {
372
+ nodes.push(h("div", { key: `drop-${i}`, class: taskBoardDropIndicatorClasses }));
373
+ }
374
+ nodes.push(renderCard(card, column));
375
+ return nodes;
376
+ }).concat(
377
+ isDropTarget && dropIndex.value >= column.cards.length ? [h("div", { key: "drop-end", class: taskBoardDropIndicatorClasses })] : []
378
+ ) : [
379
+ isDropTarget ? h("div", { key: "drop-empty", class: taskBoardDropIndicatorClasses }) : slots["empty-column"] ? slots["empty-column"]({ column }) : h(
380
+ "div",
381
+ { class: taskBoardEmptyClasses },
382
+ resolveLocaleText(labels.value.emptyColumnText)
383
+ )
384
+ ];
385
+ const body = h(
386
+ "div",
387
+ {
388
+ class: taskBoardColumnBodyClasses,
389
+ role: "list",
390
+ "aria-label": column.title,
391
+ onDragover: (e) => handleCardDragOver(e, column),
392
+ onDrop: (e) => handleCardDrop(e, column),
393
+ onDragleave: handleDragLeave
394
+ },
395
+ cards
396
+ );
397
+ const footer = slots["column-footer"] ? slots["column-footer"]({ column }) : props.onCardAdd ? h(
398
+ "div",
399
+ {
400
+ class: classNames(
401
+ "border-t border-[var(--tiger-border,#e5e7eb)]",
402
+ taskBoardAddCardClasses
403
+ ),
404
+ onClick: () => {
405
+ emit("card-add", column.id);
406
+ }
407
+ },
408
+ [h("span", null, "+"), h("span", null, resolveLocaleText(labels.value.addCardText))]
409
+ ) : null;
410
+ return h(
411
+ "div",
412
+ {
413
+ key: String(column.id),
414
+ class: colClasses,
415
+ "data-tiger-taskboard-column": "",
416
+ "data-tiger-taskboard-column-id": String(column.id),
417
+ onDragover: dragState.value?.type === "column" ? handleColumnDragOver : void 0,
418
+ onDrop: dragState.value?.type === "column" ? handleColumnDrop : void 0
419
+ },
420
+ [header, body, footer]
421
+ );
422
+ };
423
+ return () => h(
424
+ "div",
425
+ {
426
+ ...attrs,
427
+ ref: boardRef,
428
+ class: wrapperClasses.value,
429
+ style: wrapperStyle.value,
430
+ role: "region",
431
+ "aria-label": resolveLocaleText(labels.value.boardAriaLabel),
432
+ "data-tiger-task-board": ""
433
+ },
434
+ currentColumns.value.map((col, i) => renderColumnNode(col, i))
435
+ );
436
+ }
437
+ });
438
+ var TaskBoard_default = TaskBoard;
439
+
440
+ export { TaskBoard, TaskBoard_default };