@cadraos/sdk 0.3.14-p46.0 → 0.3.14-p46.1
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.
- package/dist/kanban/index.cjs +147 -23
- package/dist/kanban/index.cjs.map +1 -1
- package/dist/kanban/index.d.cts +164 -70
- package/dist/kanban/index.d.ts +164 -70
- package/dist/kanban/index.js +147 -23
- package/dist/kanban/index.js.map +1 -1
- package/package.json +1 -1
package/dist/kanban/index.cjs
CHANGED
|
@@ -266,9 +266,12 @@ function useKanbanBoard(options) {
|
|
|
266
266
|
]);
|
|
267
267
|
setBoard(nextBoard);
|
|
268
268
|
setCards(cardList.cards);
|
|
269
|
-
setSelectedCard(
|
|
270
|
-
|
|
271
|
-
|
|
269
|
+
setSelectedCard((prev) => {
|
|
270
|
+
if (!prev) return prev;
|
|
271
|
+
const next = cardList.cards.find((c) => c.id === prev.id);
|
|
272
|
+
if (!next) return prev;
|
|
273
|
+
return next.run ? next : { ...next, run: prev.run };
|
|
274
|
+
});
|
|
272
275
|
} catch (err) {
|
|
273
276
|
fail(err, "Failed to load board");
|
|
274
277
|
} finally {
|
|
@@ -283,9 +286,12 @@ function useKanbanBoard(options) {
|
|
|
283
286
|
]);
|
|
284
287
|
setBoard(nextBoard);
|
|
285
288
|
setCards(cardList.cards);
|
|
286
|
-
setSelectedCard(
|
|
287
|
-
|
|
288
|
-
|
|
289
|
+
setSelectedCard((prev) => {
|
|
290
|
+
if (!prev) return prev;
|
|
291
|
+
const next = cardList.cards.find((c) => c.id === prev.id);
|
|
292
|
+
if (!next) return prev;
|
|
293
|
+
return next.run ? next : { ...next, run: prev.run };
|
|
294
|
+
});
|
|
289
295
|
} catch {
|
|
290
296
|
}
|
|
291
297
|
}, [adapter]);
|
|
@@ -306,7 +312,7 @@ function useKanbanBoard(options) {
|
|
|
306
312
|
try {
|
|
307
313
|
const full = await adapter.getCard(cardId);
|
|
308
314
|
setSelectedCard(
|
|
309
|
-
(prev) => prev
|
|
315
|
+
(prev) => prev == null || prev.id === cardId ? full : prev
|
|
310
316
|
);
|
|
311
317
|
} catch (err) {
|
|
312
318
|
if (!known) fail(err, "Failed to open card");
|
|
@@ -415,6 +421,27 @@ function useKanbanBoard(options) {
|
|
|
415
421
|
},
|
|
416
422
|
[refresh]
|
|
417
423
|
);
|
|
424
|
+
const deleteCard = react.useCallback(
|
|
425
|
+
async (cardId) => {
|
|
426
|
+
if (!adapter.deleteCard) return false;
|
|
427
|
+
setError(null);
|
|
428
|
+
const prevCards = cards;
|
|
429
|
+
const prevSelected = selectedCard;
|
|
430
|
+
setCards((prev) => prev.filter((c) => c.id !== cardId));
|
|
431
|
+
setSelectedCard((prev) => prev && prev.id === cardId ? null : prev);
|
|
432
|
+
try {
|
|
433
|
+
await adapter.deleteCard(cardId);
|
|
434
|
+
void silentRefresh();
|
|
435
|
+
return true;
|
|
436
|
+
} catch (err) {
|
|
437
|
+
setCards(prevCards);
|
|
438
|
+
setSelectedCard(prevSelected);
|
|
439
|
+
fail(err, "Failed to delete card");
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
[adapter, cards, selectedCard, silentRefresh, fail]
|
|
444
|
+
);
|
|
418
445
|
return {
|
|
419
446
|
board,
|
|
420
447
|
lanes: board?.lanes ?? [],
|
|
@@ -430,6 +457,7 @@ function useKanbanBoard(options) {
|
|
|
430
457
|
createCard,
|
|
431
458
|
updateCard,
|
|
432
459
|
transitionCard,
|
|
460
|
+
deleteCard,
|
|
433
461
|
handleRunTerminal
|
|
434
462
|
};
|
|
435
463
|
}
|
|
@@ -2723,6 +2751,9 @@ function KanbanCard({
|
|
|
2723
2751
|
onClick,
|
|
2724
2752
|
selected,
|
|
2725
2753
|
dueState,
|
|
2754
|
+
draggable,
|
|
2755
|
+
onDragStart,
|
|
2756
|
+
onDragEnd,
|
|
2726
2757
|
className
|
|
2727
2758
|
}) {
|
|
2728
2759
|
const runStatus = card.run?.status;
|
|
@@ -2751,10 +2782,20 @@ function KanbanCard({
|
|
|
2751
2782
|
onClick: () => onClick?.(card),
|
|
2752
2783
|
"aria-pressed": selected,
|
|
2753
2784
|
"aria-busy": isWorking,
|
|
2785
|
+
draggable,
|
|
2786
|
+
onDragStart: draggable ? (e) => {
|
|
2787
|
+
e.dataTransfer.effectAllowed = "move";
|
|
2788
|
+
e.dataTransfer.setData("text/plain", card.id);
|
|
2789
|
+
onDragStart?.(card);
|
|
2790
|
+
} : void 0,
|
|
2791
|
+
onDragEnd: draggable ? () => onDragEnd?.() : void 0,
|
|
2754
2792
|
className: cn9(
|
|
2755
|
-
|
|
2793
|
+
// Solid card: fill + border + a faint token top-sheen (adapts to theme),
|
|
2794
|
+
// matching the host's cockpit cards (work-shell v2 visual pass).
|
|
2795
|
+
"relative w-full text-left rounded-xl border bg-card bg-gradient-to-b from-foreground/[0.03] to-transparent p-3 shadow-sm motion-safe:transition-shadow",
|
|
2756
2796
|
"hover:shadow-md hover:border-primary/40",
|
|
2757
2797
|
"focus:outline-none focus:ring-2 focus:ring-ring/50",
|
|
2798
|
+
draggable && "cursor-grab active:cursor-grabbing",
|
|
2758
2799
|
// The working card carries the SINGLE focal motion on the board (F11).
|
|
2759
2800
|
isWorking ? "border-info/60 ring-2 ring-info/40 animate-pulse" : selected ? "border-primary/60 ring-2 ring-primary/30" : "border-border",
|
|
2760
2801
|
className
|
|
@@ -3047,6 +3088,16 @@ function LaneAgentPicker({
|
|
|
3047
3088
|
)
|
|
3048
3089
|
] });
|
|
3049
3090
|
}
|
|
3091
|
+
function dueStateFor(card, lane, now) {
|
|
3092
|
+
const rs = card.run?.status;
|
|
3093
|
+
if (rs === "completed" && !lane.terminal) return "ready";
|
|
3094
|
+
if (card.nextDueAt) {
|
|
3095
|
+
const t = Date.parse(card.nextDueAt);
|
|
3096
|
+
if (!Number.isNaN(t) && t <= now) return "due";
|
|
3097
|
+
}
|
|
3098
|
+
if (lane.trigger === "scheduled" && !rs) return "waiting";
|
|
3099
|
+
return void 0;
|
|
3100
|
+
}
|
|
3050
3101
|
function LaneHealthDot({ health }) {
|
|
3051
3102
|
if (!health || health.state !== "down" && health.state !== "degraded") return null;
|
|
3052
3103
|
const down = health.state === "down";
|
|
@@ -3067,16 +3118,6 @@ function LaneHealthDot({ health }) {
|
|
|
3067
3118
|
}
|
|
3068
3119
|
);
|
|
3069
3120
|
}
|
|
3070
|
-
function dueStateFor(card, lane, now) {
|
|
3071
|
-
const rs = card.run?.status;
|
|
3072
|
-
if (rs === "completed" && !lane.terminal) return "ready";
|
|
3073
|
-
if (card.nextDueAt) {
|
|
3074
|
-
const t = Date.parse(card.nextDueAt);
|
|
3075
|
-
if (!Number.isNaN(t) && t <= now) return "due";
|
|
3076
|
-
}
|
|
3077
|
-
if (lane.trigger === "scheduled" && !rs) return "waiting";
|
|
3078
|
-
return void 0;
|
|
3079
|
-
}
|
|
3080
3121
|
function KanbanColumn({
|
|
3081
3122
|
lane,
|
|
3082
3123
|
cards,
|
|
@@ -3087,6 +3128,12 @@ function KanbanColumn({
|
|
|
3087
3128
|
count,
|
|
3088
3129
|
agentPicker,
|
|
3089
3130
|
canEditHandlers,
|
|
3131
|
+
draggableCards,
|
|
3132
|
+
dragActive,
|
|
3133
|
+
dropAllowed,
|
|
3134
|
+
onCardDragStart,
|
|
3135
|
+
onCardDragEnd,
|
|
3136
|
+
onLaneDrop,
|
|
3090
3137
|
health,
|
|
3091
3138
|
className
|
|
3092
3139
|
}) {
|
|
@@ -3098,9 +3145,21 @@ function KanbanColumn({
|
|
|
3098
3145
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3099
3146
|
"div",
|
|
3100
3147
|
{
|
|
3148
|
+
onDragOver: dropAllowed ? (e) => {
|
|
3149
|
+
e.preventDefault();
|
|
3150
|
+
e.dataTransfer.dropEffect = "move";
|
|
3151
|
+
} : void 0,
|
|
3152
|
+
onDrop: dropAllowed && onLaneDrop ? (e) => {
|
|
3153
|
+
e.preventDefault();
|
|
3154
|
+
onLaneDrop(lane);
|
|
3155
|
+
} : void 0,
|
|
3101
3156
|
className: cn9(
|
|
3102
|
-
"flex w-[85vw] max-w-sm snap-start shrink-0 flex-col rounded-xl bg-muted/40 border border-border sm:w-72 sm:max-w-none",
|
|
3157
|
+
"flex w-[85vw] max-w-sm snap-start shrink-0 flex-col rounded-xl bg-muted/40 border border-border transition sm:w-72 sm:max-w-none",
|
|
3103
3158
|
isScheduled && "border-border",
|
|
3159
|
+
// MV4 drag affordance: allowed targets glow; other lanes dim so the
|
|
3160
|
+
// valid drop zones read at a glance.
|
|
3161
|
+
dragActive && dropAllowed && "border-primary/60 ring-2 ring-primary/40 bg-primary/5",
|
|
3162
|
+
dragActive && !dropAllowed && "opacity-55",
|
|
3104
3163
|
className
|
|
3105
3164
|
),
|
|
3106
3165
|
children: [
|
|
@@ -3170,7 +3229,10 @@ function KanbanColumn({
|
|
|
3170
3229
|
card,
|
|
3171
3230
|
onClick: onCardClick,
|
|
3172
3231
|
selected: card.id === selectedCardId,
|
|
3173
|
-
dueState: dueStateFor(card, lane, now)
|
|
3232
|
+
dueState: dueStateFor(card, lane, now),
|
|
3233
|
+
draggable: draggableCards,
|
|
3234
|
+
onDragStart: onCardDragStart,
|
|
3235
|
+
onDragEnd: onCardDragEnd
|
|
3174
3236
|
},
|
|
3175
3237
|
card.id
|
|
3176
3238
|
)),
|
|
@@ -3331,6 +3393,8 @@ function KanbanBoard({
|
|
|
3331
3393
|
laneAgentPicker,
|
|
3332
3394
|
scheduleStatus,
|
|
3333
3395
|
focusCardId,
|
|
3396
|
+
renderCardDrawer,
|
|
3397
|
+
enableDrag,
|
|
3334
3398
|
className
|
|
3335
3399
|
}) {
|
|
3336
3400
|
const {
|
|
@@ -3345,6 +3409,7 @@ function KanbanBoard({
|
|
|
3345
3409
|
createCard,
|
|
3346
3410
|
updateCard,
|
|
3347
3411
|
transitionCard,
|
|
3412
|
+
deleteCard,
|
|
3348
3413
|
handleRunTerminal
|
|
3349
3414
|
} = useKanbanBoard({ adapter, onError, onCardCreated, pollIntervalMs });
|
|
3350
3415
|
const lastFocusedRef = react.useRef(void 0);
|
|
@@ -3389,6 +3454,44 @@ function KanbanBoard({
|
|
|
3389
3454
|
(cardId, toLane) => transitionCard({ cardId, targetLane: toLane }),
|
|
3390
3455
|
[transitionCard]
|
|
3391
3456
|
);
|
|
3457
|
+
const [dragging, setDragging] = react.useState(null);
|
|
3458
|
+
const draggingRef = react.useRef(null);
|
|
3459
|
+
const dropInFlightRef = react.useRef(null);
|
|
3460
|
+
const allowedDropLanes = react.useMemo(() => {
|
|
3461
|
+
if (!dragging || !board?.transitions) return /* @__PURE__ */ new Set();
|
|
3462
|
+
return new Set(
|
|
3463
|
+
board.transitions.filter((t) => t.fromLane === dragging.lane && t.manualAllowed).map((t) => t.toLane)
|
|
3464
|
+
);
|
|
3465
|
+
}, [dragging, board?.transitions]);
|
|
3466
|
+
const handleCardDragStart = react.useCallback((card) => {
|
|
3467
|
+
const d = { id: card.id, lane: card.lane };
|
|
3468
|
+
draggingRef.current = d;
|
|
3469
|
+
setDragging(d);
|
|
3470
|
+
}, []);
|
|
3471
|
+
const handleCardDragEnd = react.useCallback(() => {
|
|
3472
|
+
draggingRef.current = null;
|
|
3473
|
+
setDragging(null);
|
|
3474
|
+
}, []);
|
|
3475
|
+
const handleLaneDrop = react.useCallback(
|
|
3476
|
+
(lane) => {
|
|
3477
|
+
const cur = draggingRef.current;
|
|
3478
|
+
draggingRef.current = null;
|
|
3479
|
+
setDragging(null);
|
|
3480
|
+
if (!cur || lane.key === cur.lane) return;
|
|
3481
|
+
if (dropInFlightRef.current === cur.id) return;
|
|
3482
|
+
const allowed = (board?.transitions ?? []).some(
|
|
3483
|
+
(t) => t.fromLane === cur.lane && t.toLane === lane.key && t.manualAllowed
|
|
3484
|
+
);
|
|
3485
|
+
if (!allowed) return;
|
|
3486
|
+
dropInFlightRef.current = cur.id;
|
|
3487
|
+
void Promise.resolve(transitionCard({ cardId: cur.id, targetLane: lane.key })).finally(
|
|
3488
|
+
() => {
|
|
3489
|
+
if (dropInFlightRef.current === cur.id) dropInFlightRef.current = null;
|
|
3490
|
+
}
|
|
3491
|
+
);
|
|
3492
|
+
},
|
|
3493
|
+
[board?.transitions, transitionCard]
|
|
3494
|
+
);
|
|
3392
3495
|
const initialLaneKey = lanes.find((l) => !l.terminal)?.key ?? lanes[0]?.key;
|
|
3393
3496
|
const selectedLane = selectedCard ? lanes.find((l) => l.key === selectedCard.lane) : void 0;
|
|
3394
3497
|
const canAdvanceSelected = !!selectedLane && !selectedLane.terminal;
|
|
@@ -3410,12 +3513,32 @@ function KanbanBoard({
|
|
|
3410
3513
|
count: laneCounts?.[lane.key],
|
|
3411
3514
|
health: laneHealth?.[lane.key],
|
|
3412
3515
|
agentPicker: laneAgentPicker?.(lane),
|
|
3413
|
-
canEditHandlers
|
|
3516
|
+
canEditHandlers,
|
|
3517
|
+
draggableCards: enableDrag && enableAdvance,
|
|
3518
|
+
dragActive: !!dragging,
|
|
3519
|
+
dropAllowed: !!dragging && dragging.lane !== lane.key && allowedDropLanes.has(lane.key),
|
|
3520
|
+
onCardDragStart: handleCardDragStart,
|
|
3521
|
+
onCardDragEnd: handleCardDragEnd,
|
|
3522
|
+
onLaneDrop: handleLaneDrop
|
|
3414
3523
|
},
|
|
3415
3524
|
lane.id ?? lane.key
|
|
3416
3525
|
))
|
|
3417
3526
|
] }),
|
|
3418
|
-
selectedCard &&
|
|
3527
|
+
selectedCard && (renderCardDrawer ? renderCardDrawer({
|
|
3528
|
+
card: selectedCard,
|
|
3529
|
+
adapter,
|
|
3530
|
+
lanes,
|
|
3531
|
+
transitions: enableAdvance ? board?.transitions : void 0,
|
|
3532
|
+
canAdvance: canAdvanceSelected,
|
|
3533
|
+
onClose: closeCard,
|
|
3534
|
+
onRetry: onRetryCard ? handleRetry : void 0,
|
|
3535
|
+
onUpdate: enableEdit ? handleUpdate : void 0,
|
|
3536
|
+
onAdvance: enableAdvance ? handleAdvance : void 0,
|
|
3537
|
+
onTransition: enableAdvance ? handleTransition : void 0,
|
|
3538
|
+
onDelete: adapter.deleteCard ? deleteCard : void 0,
|
|
3539
|
+
onRunTerminal: handleRunTerminal,
|
|
3540
|
+
onError
|
|
3541
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
3419
3542
|
CardDrawer,
|
|
3420
3543
|
{
|
|
3421
3544
|
card: selectedCard,
|
|
@@ -3431,7 +3554,7 @@ function KanbanBoard({
|
|
|
3431
3554
|
onRunTerminal: handleRunTerminal,
|
|
3432
3555
|
onError
|
|
3433
3556
|
}
|
|
3434
|
-
)
|
|
3557
|
+
))
|
|
3435
3558
|
] })
|
|
3436
3559
|
] });
|
|
3437
3560
|
}
|
|
@@ -3456,6 +3579,7 @@ function composeAdapter(source, boardConfigUuid, version, cardSource) {
|
|
|
3456
3579
|
transitionCard(input) {
|
|
3457
3580
|
return cardSource.transitionCard(input);
|
|
3458
3581
|
},
|
|
3582
|
+
...cardSource.deleteCard ? { deleteCard: (id) => cardSource.deleteCard(id) } : {},
|
|
3459
3583
|
...cardSource.createRunStream ? { createRunStream: (id) => cardSource.createRunStream(id) } : {}
|
|
3460
3584
|
};
|
|
3461
3585
|
}
|