@asteby/metacore-runtime-react 20.1.4 → 20.1.6
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/CHANGELOG.md +25 -0
- package/dist/dynamic-kanban.d.ts.map +1 -1
- package/dist/dynamic-kanban.js +6 -6
- package/package.json +1 -1
- package/src/dynamic-kanban.tsx +13 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 20.1.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 0ff3d4e: fix(kanban): fixed-width lanes (horizontal scroll, no squish) + drag preview matches card
|
|
8
|
+
|
|
9
|
+
Lanes were `flex-1 min-w-[220px] max-w-[320px]`, so with many stages they compressed
|
|
10
|
+
to a cramped width. They're now a fixed `w-[300px] shrink-0` so columns keep a
|
|
11
|
+
comfortable width and the board scrolls horizontally instead of squishing. The drag
|
|
12
|
+
overlay was a fixed `w-72` that no longer matched the in-lane card; it's now
|
|
13
|
+
`w-[284px]` (lane width minus the column padding) so a dragged card is the same size
|
|
14
|
+
as it sits in the column.
|
|
15
|
+
|
|
16
|
+
## 20.1.5
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 5b7fd84: fix(kanban): constrain cards to the lane width so they stop spilling out of the stage
|
|
21
|
+
|
|
22
|
+
The lane used a Radix ScrollArea whose viewport wraps content in a `display:table`
|
|
23
|
+
element that shrink-to-fits the widest card. Once card text wrapped freely (no
|
|
24
|
+
line-clamp) the cards grew to their natural content width and overflowed the
|
|
25
|
+
column. Replaced the ScrollArea with a plain `overflow-y-auto` block and gave the
|
|
26
|
+
card `w-full min-w-0`, so every card fits the lane and its text wraps inside it.
|
|
27
|
+
|
|
3
28
|
## 20.1.4
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-kanban.d.ts","sourceRoot":"","sources":["../src/dynamic-kanban.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-kanban.d.ts","sourceRoot":"","sources":["../src/dynamic-kanban.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAoC9B,OAAO,KAAK,EACR,aAAa,EACb,gBAAgB,EAGhB,SAAS,EACT,eAAe,EAClB,MAAM,SAAS,CAAA;AAMhB;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,SAAS,EAAE,CAejE;AAQD;;;;;GAKG;AACH,eAAO,MAAM,eAAe,mBAAmB,CAAA;AAE/C,wBAAgB,YAAY,CACxB,OAAO,EAAE,GAAG,EAAE,EACd,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,SAAS,EAAE,GACpB,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAepB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAC/B,WAAW,EAAE,eAAe,EAAE,GAAG,SAAS,EAC1C,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACX,OAAO,CAOT;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAC/B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,EAC3B,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACnB,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAYpB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC7B,QAAQ,EAAE,aAAa,EACvB,SAAS,SAAI,GACd;IAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAkBhE;AA8BD,MAAM,WAAW,kBAAkB;IAC/B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,kFAAkF;IAClF,cAAc,CAAC,EAAE,GAAG,CAAA;IACpB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wBAAgB,aAAa,CAAC,EAC1B,KAAK,EACL,QAAQ,EACR,cAAc,EACd,WAAW,EACX,QAAc,EACd,QAAQ,EACR,QAAQ,GACX,EAAE,kBAAkB,qBAmSpB"}
|
package/dist/dynamic-kanban.js
CHANGED
|
@@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
4
4
|
import { DndContext, DragOverlay, PointerSensor, useSensor, useSensors, useDraggable, useDroppable, } from '@dnd-kit/core';
|
|
5
5
|
import { MoreHorizontal } from 'lucide-react';
|
|
6
6
|
import { toast } from 'sonner';
|
|
7
|
-
import { Badge, Button, Card, CardContent, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger,
|
|
7
|
+
import { Badge, Button, Card, CardContent, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, Skeleton, } from '@asteby/metacore-ui/primitives';
|
|
8
8
|
import { generateBadgeStyles, optionColor } from '@asteby/metacore-ui/lib';
|
|
9
9
|
import { useApi } from './api-context';
|
|
10
10
|
import { useMetadataCache } from './metadata-cache';
|
|
@@ -284,7 +284,7 @@ export function DynamicKanban({ model, endpoint, refreshTrigger, onCardClick, pa
|
|
|
284
284
|
}
|
|
285
285
|
}, [api, endpoint, groupByKey, model, records, stageOfCard, t, transitions]);
|
|
286
286
|
if (loading) {
|
|
287
|
-
return (_jsx("div", { className: "flex gap-4 overflow-x-auto p-1", children: [0, 1, 2, 3].map((i) => (_jsxs("div", { className: "
|
|
287
|
+
return (_jsx("div", { className: "flex gap-4 overflow-x-auto p-1", children: [0, 1, 2, 3].map((i) => (_jsxs("div", { className: "w-[300px] shrink-0 space-y-3", children: [_jsx(Skeleton, { className: "h-8 w-full" }), _jsx(Skeleton, { className: "h-24 w-full" }), _jsx(Skeleton, { className: "h-24 w-full" })] }, i))) }));
|
|
288
288
|
}
|
|
289
289
|
if (!metadata || !groupByKey || stages.length === 0) {
|
|
290
290
|
return (_jsx("div", { className: "rounded-md border border-dashed p-8 text-center text-sm text-muted-foreground", children: t('kanban.noStages', {
|
|
@@ -322,18 +322,18 @@ function KanbanLane({ stage, count, isDark, dimmed, disabled, children }) {
|
|
|
322
322
|
const headerStyle = generateBadgeStyles(stage.color || optionColor(stage.key), {
|
|
323
323
|
isDark,
|
|
324
324
|
});
|
|
325
|
-
return (_jsxs("div", { ref: setNodeRef, className: "flex
|
|
325
|
+
return (_jsxs("div", { ref: setNodeRef, className: "flex w-[300px] shrink-0 flex-col rounded-lg border bg-muted/30 transition-opacity", style: {
|
|
326
326
|
opacity: dimmed ? 0.45 : 1,
|
|
327
327
|
outline: isOver && !disabled ? '2px solid var(--ring, #3b82f6)' : 'none',
|
|
328
328
|
outlineOffset: 2,
|
|
329
|
-
}, "data-stage": stage.key, "data-disabled": disabled || undefined, children: [_jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2.5", children: [_jsx(Badge, { variant: "outline", className: "border-0 text-xs font-semibold", style: headerStyle, children: t(stage.label, { defaultValue: stage.label }) }), _jsx("span", { className: "text-xs font-medium tabular-nums text-muted-foreground", children: count })] }), _jsx(
|
|
329
|
+
}, "data-stage": stage.key, "data-disabled": disabled || undefined, children: [_jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2.5", children: [_jsx(Badge, { variant: "outline", className: "border-0 text-xs font-semibold", style: headerStyle, children: t(stage.label, { defaultValue: stage.label }) }), _jsx("span", { className: "text-xs font-medium tabular-nums text-muted-foreground", children: count })] }), _jsx("div", { className: "flex min-h-[55vh] max-h-[70vh] min-w-0 flex-col gap-2 overflow-y-auto px-2 pb-3", children: children })] }));
|
|
330
330
|
}
|
|
331
331
|
function KanbanCard({ card, titleCol, fieldCols, actions, locale, timeZone, currency, onClick, onAction, }) {
|
|
332
332
|
const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
|
|
333
333
|
id: String(card.id),
|
|
334
334
|
});
|
|
335
335
|
const visibleActions = actions.filter((a) => isActionAllowedForRowState(a, card));
|
|
336
|
-
return (_jsx(Card, { ref: setNodeRef, ...attributes, ...listeners, className: "cursor-grab active:cursor-grabbing border-border/70 shadow-sm", style: { opacity: isDragging ? 0.4 : 1 }, onClick: () => onClick?.(card), "data-card-id": String(card.id), children: _jsxs(CardContent, { className: "space-y-1.5 p-3", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsx("div", { className: "min-w-0 flex-1 break-words text-sm font-medium leading-snug", children: titleCol ? (_jsx(ActivityValueRenderer, { value: card[titleCol.key], col: titleCol, locale: locale, timeZone: timeZone, currency: currency })) : (_jsx("span", { className: "truncate", children: String(card.id) })) }), visibleActions.length > 0 && (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6 shrink-0 -mr-1 -mt-1",
|
|
336
|
+
return (_jsx(Card, { ref: setNodeRef, ...attributes, ...listeners, className: "w-full min-w-0 cursor-grab active:cursor-grabbing border-border/70 shadow-sm", style: { opacity: isDragging ? 0.4 : 1 }, onClick: () => onClick?.(card), "data-card-id": String(card.id), children: _jsxs(CardContent, { className: "space-y-1.5 p-3", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsx("div", { className: "min-w-0 flex-1 break-words text-sm font-medium leading-snug", children: titleCol ? (_jsx(ActivityValueRenderer, { value: card[titleCol.key], col: titleCol, locale: locale, timeZone: timeZone, currency: currency })) : (_jsx("span", { className: "truncate", children: String(card.id) })) }), visibleActions.length > 0 && (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6 shrink-0 -mr-1 -mt-1",
|
|
337
337
|
// Don't start a drag / card click from the menu button.
|
|
338
338
|
onPointerDown: (e) => e.stopPropagation(), onClick: (e) => e.stopPropagation(), children: _jsx(MoreHorizontal, { className: "h-4 w-4" }) }) }), _jsx(DropdownMenuContent, { align: "end", onClick: (e) => e.stopPropagation(), children: visibleActions.map((a) => (_jsxs(DropdownMenuItem, { onClick: (e) => {
|
|
339
339
|
e.stopPropagation();
|
|
@@ -342,5 +342,5 @@ function KanbanCard({ card, titleCol, fieldCols, actions, locale, timeZone, curr
|
|
|
342
342
|
}
|
|
343
343
|
// Static preview rendered inside the DragOverlay (no dnd hooks, no menu).
|
|
344
344
|
function CardPreview({ card, titleCol, fieldCols, locale, timeZone, currency, }) {
|
|
345
|
-
return (_jsx(Card, { className: "w-
|
|
345
|
+
return (_jsx(Card, { className: "w-[284px] cursor-grabbing border-primary/40 shadow-lg", children: _jsxs(CardContent, { className: "space-y-1.5 p-3", children: [_jsx("div", { className: "break-words text-sm font-medium leading-snug", children: titleCol ? (_jsx(ActivityValueRenderer, { value: card[titleCol.key], col: titleCol, locale: locale, timeZone: timeZone, currency: currency })) : (String(card.id)) }), fieldCols.map((col) => (_jsxs("div", { className: "flex min-w-0 items-start gap-1.5 text-xs text-muted-foreground", children: [_jsxs("span", { className: "shrink-0 opacity-70", children: [col.label, ":"] }), _jsx("span", { className: "min-w-0 break-words", children: _jsx(ActivityValueRenderer, { value: card[col.key], col: col, locale: locale, timeZone: timeZone, currency: currency }) })] }, col.key)))] }) }));
|
|
346
346
|
}
|
package/package.json
CHANGED
package/src/dynamic-kanban.tsx
CHANGED
|
@@ -48,7 +48,6 @@ import {
|
|
|
48
48
|
DropdownMenuContent,
|
|
49
49
|
DropdownMenuItem,
|
|
50
50
|
DropdownMenuTrigger,
|
|
51
|
-
ScrollArea,
|
|
52
51
|
Skeleton,
|
|
53
52
|
} from '@asteby/metacore-ui/primitives'
|
|
54
53
|
import { generateBadgeStyles, optionColor } from '@asteby/metacore-ui/lib'
|
|
@@ -441,7 +440,7 @@ export function DynamicKanban({
|
|
|
441
440
|
return (
|
|
442
441
|
<div className="flex gap-4 overflow-x-auto p-1">
|
|
443
442
|
{[0, 1, 2, 3].map((i) => (
|
|
444
|
-
<div key={i} className="
|
|
443
|
+
<div key={i} className="w-[300px] shrink-0 space-y-3">
|
|
445
444
|
<Skeleton className="h-8 w-full" />
|
|
446
445
|
<Skeleton className="h-24 w-full" />
|
|
447
446
|
<Skeleton className="h-24 w-full" />
|
|
@@ -580,7 +579,7 @@ function KanbanLane({ stage, count, isDark, dimmed, disabled, children }: Kanban
|
|
|
580
579
|
return (
|
|
581
580
|
<div
|
|
582
581
|
ref={setNodeRef}
|
|
583
|
-
className="flex
|
|
582
|
+
className="flex w-[300px] shrink-0 flex-col rounded-lg border bg-muted/30 transition-opacity"
|
|
584
583
|
style={{
|
|
585
584
|
opacity: dimmed ? 0.45 : 1,
|
|
586
585
|
outline: isOver && !disabled ? '2px solid var(--ring, #3b82f6)' : 'none',
|
|
@@ -601,9 +600,15 @@ function KanbanLane({ stage, count, isDark, dimmed, disabled, children }: Kanban
|
|
|
601
600
|
{count}
|
|
602
601
|
</span>
|
|
603
602
|
</div>
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
603
|
+
{/* Plain vertical-scroll column, NOT a Radix ScrollArea: the
|
|
604
|
+
ScrollArea viewport wraps its content in a `display:table`
|
|
605
|
+
element that shrink-to-fits the WIDEST card, so once the card
|
|
606
|
+
text wraps freely (no line-clamp) the cards grew past the lane
|
|
607
|
+
and spilled out of the stage. A normal `overflow-y-auto` block
|
|
608
|
+
constrains every card to the lane width so text wraps inside it. */}
|
|
609
|
+
<div className="flex min-h-[55vh] max-h-[70vh] min-w-0 flex-col gap-2 overflow-y-auto px-2 pb-3">
|
|
610
|
+
{children}
|
|
611
|
+
</div>
|
|
607
612
|
</div>
|
|
608
613
|
)
|
|
609
614
|
}
|
|
@@ -648,7 +653,7 @@ function KanbanCard({
|
|
|
648
653
|
ref={setNodeRef}
|
|
649
654
|
{...attributes}
|
|
650
655
|
{...listeners}
|
|
651
|
-
className="cursor-grab active:cursor-grabbing border-border/70 shadow-sm"
|
|
656
|
+
className="w-full min-w-0 cursor-grab active:cursor-grabbing border-border/70 shadow-sm"
|
|
652
657
|
style={{ opacity: isDragging ? 0.4 : 1 }}
|
|
653
658
|
onClick={() => onClick?.(card)}
|
|
654
659
|
data-card-id={String(card.id)}
|
|
@@ -734,7 +739,7 @@ function CardPreview({
|
|
|
734
739
|
currency,
|
|
735
740
|
}: Omit<KanbanCardProps, 'actions' | 'onClick' | 'onAction'>) {
|
|
736
741
|
return (
|
|
737
|
-
<Card className="w-
|
|
742
|
+
<Card className="w-[284px] cursor-grabbing border-primary/40 shadow-lg">
|
|
738
743
|
<CardContent className="space-y-1.5 p-3">
|
|
739
744
|
<div className="break-words text-sm font-medium leading-snug">
|
|
740
745
|
{titleCol ? (
|