@asteby/metacore-runtime-react 20.1.0 → 20.1.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.
- package/CHANGELOG.md +45 -0
- package/dist/dynamic-kanban.js +5 -5
- package/package.json +4 -4
- package/src/dynamic-kanban.tsx +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 20.1.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 3d0a624: fix(kanban): wrap long card field values to 2 lines + ellipsis instead of a 1-line hard cut
|
|
8
|
+
|
|
9
|
+
Kanban card fields rendered each value on a single `truncate` line, so a long
|
|
10
|
+
text field — e.g. a github Issue whose title lands in a _field_ because the first
|
|
11
|
+
text column (`repo`) is picked as the card title — was hard-cut mid-line and lost
|
|
12
|
+
most of its content. Field values now `line-clamp-2 break-words`, so they grow to
|
|
13
|
+
two lines and then ellipsis cleanly, matching the title's treatment.
|
|
14
|
+
|
|
15
|
+
## 20.1.1
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- eb6c65f: Kanban responsive board + cards truncate; sidebar nav lights the default view on a view-less landing
|
|
20
|
+
|
|
21
|
+
Two frontend UX fixes reported against the ops board.
|
|
22
|
+
|
|
23
|
+
**Kanban now adapts instead of overflowing (`@asteby/metacore-runtime-react`).**
|
|
24
|
+
`DynamicKanban` lanes were fixed-width (`w-72 shrink-0`), so with 4+ stages the
|
|
25
|
+
last lane was clipped off-viewport and long card text was cut by the card edge
|
|
26
|
+
with no ellipsis. Lanes are now responsive — `flex-1 min-w-[220px] max-w-[320px]`
|
|
27
|
+
— so they shrink to fit the available width and only scroll horizontally when
|
|
28
|
+
they genuinely can't fit. Card titles now `line-clamp-2 break-words` and the
|
|
29
|
+
secondary field rows carry `min-w-0` so long values ellipsize _inside_ the card
|
|
30
|
+
rather than being clipped by the border. The optimistic drag-to-move (PUT
|
|
31
|
+
`<base>/<id>`) is untouched.
|
|
32
|
+
|
|
33
|
+
**Sidebar nav active-state on the default/view-less landing (`@asteby/metacore-ui`,
|
|
34
|
+
`@asteby/metacore-starter-core`).** Landing on a model's bare list surface
|
|
35
|
+
(e.g. `/m/github_issues?per_page=15` — a transient param, no `view`) lit
|
|
36
|
+
_neither_ the "Tablero" (`?view=kanban`) nor the "Issues" (`?view=list`) nav
|
|
37
|
+
item, because the empty view bucket matched neither sibling's explicit view.
|
|
38
|
+
`checkIsActive` now treats the empty/`view=list`/`view=table` buckets as
|
|
39
|
+
"default-equivalent": a view-less current URL lights the list/default item while
|
|
40
|
+
the board (`?view=kanban`, never a default bucket) stays mutually exclusive. The
|
|
41
|
+
prior Board-vs-Issues exclusivity, `f_` filter and transient (page/sort/search)
|
|
42
|
+
behaviour are all preserved (18 matcher tests, +4 new). Ported to the
|
|
43
|
+
`starter-core` scaffold's embedded copy for parity.
|
|
44
|
+
|
|
45
|
+
- Updated dependencies [eb6c65f]
|
|
46
|
+
- @asteby/metacore-ui@2.6.1
|
|
47
|
+
|
|
3
48
|
## 20.1.0
|
|
4
49
|
|
|
5
50
|
### Minor Changes
|
package/dist/dynamic-kanban.js
CHANGED
|
@@ -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: "w-
|
|
287
|
+
return (_jsx("div", { className: "flex gap-4 overflow-x-auto p-1", children: [0, 1, 2, 3].map((i) => (_jsxs("div", { className: "min-w-[220px] max-w-[320px] flex-1 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,7 +322,7 @@ 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 w-
|
|
325
|
+
return (_jsxs("div", { ref: setNodeRef, className: "flex min-w-[220px] max-w-[320px] flex-1 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,
|
|
@@ -333,14 +333,14 @@ function KanbanCard({ card, titleCol, fieldCols, actions, locale, timeZone, curr
|
|
|
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 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: "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: "line-clamp-2 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();
|
|
340
340
|
onAction(a, card);
|
|
341
|
-
}, children: [_jsx(DynamicIcon, { name: a.icon || 'Zap', className: "mr-2 h-4 w-4" }), a.label] }, a.key))) })] }))] }), fieldCols.map((col) => (_jsxs("div", { className: "flex items-
|
|
341
|
+
}, children: [_jsx(DynamicIcon, { name: a.icon || 'Zap', className: "mr-2 h-4 w-4" }), a.label] }, a.key))) })] }))] }), 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: "line-clamp-2 min-w-0 break-words", children: _jsx(ActivityValueRenderer, { value: card[col.key], col: col, locale: locale, timeZone: timeZone, currency: currency }) })] }, col.key)))] }) }));
|
|
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-72 cursor-grabbing border-primary/40 shadow-lg", children: _jsxs(CardContent, { className: "space-y-1.5 p-3", children: [_jsx("div", { className: "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 items-
|
|
345
|
+
return (_jsx(Card, { className: "w-72 cursor-grabbing border-primary/40 shadow-lg", children: _jsxs(CardContent, { className: "space-y-1.5 p-3", children: [_jsx("div", { className: "line-clamp-2 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: "line-clamp-2 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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asteby/metacore-runtime-react",
|
|
3
|
-
"version": "20.1.
|
|
3
|
+
"version": "20.1.2",
|
|
4
4
|
"description": "React runtime for metacore hosts — renders addon contributions dynamically",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"sonner": ">=1.7",
|
|
39
39
|
"zustand": ">=5",
|
|
40
40
|
"@asteby/metacore-sdk": "^3.2.0",
|
|
41
|
-
"@asteby/metacore-ui": "^2.6.
|
|
41
|
+
"@asteby/metacore-ui": "^2.6.2"
|
|
42
42
|
},
|
|
43
43
|
"peerDependenciesMeta": {
|
|
44
44
|
"@tanstack/react-router": {
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
"typescript": "^6.0.0",
|
|
68
68
|
"vitest": "^4.0.0",
|
|
69
69
|
"zustand": "^5.0.0",
|
|
70
|
-
"@asteby/metacore-
|
|
71
|
-
"@asteby/metacore-
|
|
70
|
+
"@asteby/metacore-ui": "2.6.2",
|
|
71
|
+
"@asteby/metacore-sdk": "3.2.0"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|
|
74
74
|
"build": "tsc -p tsconfig.json",
|
package/src/dynamic-kanban.tsx
CHANGED
|
@@ -441,7 +441,7 @@ export function DynamicKanban({
|
|
|
441
441
|
return (
|
|
442
442
|
<div className="flex gap-4 overflow-x-auto p-1">
|
|
443
443
|
{[0, 1, 2, 3].map((i) => (
|
|
444
|
-
<div key={i} className="w-
|
|
444
|
+
<div key={i} className="min-w-[220px] max-w-[320px] flex-1 space-y-3">
|
|
445
445
|
<Skeleton className="h-8 w-full" />
|
|
446
446
|
<Skeleton className="h-24 w-full" />
|
|
447
447
|
<Skeleton className="h-24 w-full" />
|
|
@@ -580,7 +580,7 @@ function KanbanLane({ stage, count, isDark, dimmed, disabled, children }: Kanban
|
|
|
580
580
|
return (
|
|
581
581
|
<div
|
|
582
582
|
ref={setNodeRef}
|
|
583
|
-
className="flex w-
|
|
583
|
+
className="flex min-w-[220px] max-w-[320px] flex-1 flex-col rounded-lg border bg-muted/30 transition-opacity"
|
|
584
584
|
style={{
|
|
585
585
|
opacity: dimmed ? 0.45 : 1,
|
|
586
586
|
outline: isOver && !disabled ? '2px solid var(--ring, #3b82f6)' : 'none',
|
|
@@ -655,7 +655,7 @@ function KanbanCard({
|
|
|
655
655
|
>
|
|
656
656
|
<CardContent className="space-y-1.5 p-3">
|
|
657
657
|
<div className="flex items-start justify-between gap-2">
|
|
658
|
-
<div className="min-w-0 flex-1 text-sm font-medium leading-snug">
|
|
658
|
+
<div className="line-clamp-2 min-w-0 flex-1 break-words text-sm font-medium leading-snug">
|
|
659
659
|
{titleCol ? (
|
|
660
660
|
<ActivityValueRenderer
|
|
661
661
|
value={card[titleCol.key]}
|
|
@@ -705,10 +705,10 @@ function KanbanCard({
|
|
|
705
705
|
{fieldCols.map((col) => (
|
|
706
706
|
<div
|
|
707
707
|
key={col.key}
|
|
708
|
-
className="flex items-
|
|
708
|
+
className="flex min-w-0 items-start gap-1.5 text-xs text-muted-foreground"
|
|
709
709
|
>
|
|
710
710
|
<span className="shrink-0 opacity-70">{col.label}:</span>
|
|
711
|
-
<span className="min-w-0
|
|
711
|
+
<span className="line-clamp-2 min-w-0 break-words">
|
|
712
712
|
<ActivityValueRenderer
|
|
713
713
|
value={card[col.key]}
|
|
714
714
|
col={col}
|
|
@@ -736,7 +736,7 @@ function CardPreview({
|
|
|
736
736
|
return (
|
|
737
737
|
<Card className="w-72 cursor-grabbing border-primary/40 shadow-lg">
|
|
738
738
|
<CardContent className="space-y-1.5 p-3">
|
|
739
|
-
<div className="text-sm font-medium leading-snug">
|
|
739
|
+
<div className="line-clamp-2 break-words text-sm font-medium leading-snug">
|
|
740
740
|
{titleCol ? (
|
|
741
741
|
<ActivityValueRenderer
|
|
742
742
|
value={card[titleCol.key]}
|
|
@@ -752,10 +752,10 @@ function CardPreview({
|
|
|
752
752
|
{fieldCols.map((col) => (
|
|
753
753
|
<div
|
|
754
754
|
key={col.key}
|
|
755
|
-
className="flex items-
|
|
755
|
+
className="flex min-w-0 items-start gap-1.5 text-xs text-muted-foreground"
|
|
756
756
|
>
|
|
757
757
|
<span className="shrink-0 opacity-70">{col.label}:</span>
|
|
758
|
-
<span className="min-w-0
|
|
758
|
+
<span className="line-clamp-2 min-w-0 break-words">
|
|
759
759
|
<ActivityValueRenderer
|
|
760
760
|
value={card[col.key]}
|
|
761
761
|
col={col}
|