@asteby/metacore-runtime-react 23.5.0 → 23.5.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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 23.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 36e7cb8: DynamicKanban: las lanes ahora aprovechan el ancho del viewport. Crecen (flex-1) para llenar el contenedor cuando todas caben, con un ancho mínimo legible (280px) y un máximo razonable (420px); el scroll horizontal solo aparece cuando ya no caben. Elimina el espacio muerto a la derecha y las columnas angostas al reducir la ventana.
|
|
8
|
+
|
|
3
9
|
## 23.5.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
package/dist/dynamic-kanban.js
CHANGED
|
@@ -588,7 +588,7 @@ export function DynamicKanban({ model, endpoint, refreshTrigger, onCardClick, on
|
|
|
588
588
|
}
|
|
589
589
|
}, [api, endpoint, groupByKey, lanePagination, model, records, stageOfCard, t, transitions]);
|
|
590
590
|
if (loading) {
|
|
591
|
-
return (_jsx("div", { className: "flex gap-4 overflow-x-auto p-1", children: [0, 1, 2, 3].map((i) => (_jsxs("div", { className: "w-[
|
|
591
|
+
return (_jsx("div", { className: "flex w-full gap-4 overflow-x-auto p-1", children: [0, 1, 2, 3].map((i) => (_jsxs("div", { className: "min-w-[280px] max-w-[420px] flex-1 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))) }));
|
|
592
592
|
}
|
|
593
593
|
if (!metadata || !groupByKey || stages.length === 0) {
|
|
594
594
|
return (_jsx("div", { className: "rounded-md border border-dashed p-8 text-center text-sm text-muted-foreground", children: t('kanban.noStages', {
|
|
@@ -615,7 +615,7 @@ export function DynamicKanban({ model, endpoint, refreshTrigger, onCardClick, on
|
|
|
615
615
|
})
|
|
616
616
|
: t('kanban.noActiveFilters', {
|
|
617
617
|
defaultValue: 'Sin filtros',
|
|
618
|
-
}) }), _jsxs(Button, { variant: "ghost", size: "sm", className: "h-7 gap-1 text-xs", onClick: clearAll, disabled: activeFilterCount === 0, children: [_jsx(X, { className: "h-3.5 w-3.5" }), t('kanban.clearAll', { defaultValue: 'Limpiar todo' }), activeFilterCount > 0 ? ` (${activeFilterCount})` : ''] })] })] })] }))] }), _jsx(FilterChipsRow, { fields: activeFields, onClearAll: clearAll, "data-testid": "kanban-filter-chips" }), _jsxs(DndContext, { sensors: sensors, onDragStart: onDragStart, onDragEnd: onDragEnd, children: [_jsx("div", { className: "flex min-w-0 gap-4 overflow-x-auto p-1", "data-testid": "kanban-board", children: lanes.map((stage) => {
|
|
618
|
+
}) }), _jsxs(Button, { variant: "ghost", size: "sm", className: "h-7 gap-1 text-xs", onClick: clearAll, disabled: activeFilterCount === 0, children: [_jsx(X, { className: "h-3.5 w-3.5" }), t('kanban.clearAll', { defaultValue: 'Limpiar todo' }), activeFilterCount > 0 ? ` (${activeFilterCount})` : ''] })] })] })] }))] }), _jsx(FilterChipsRow, { fields: activeFields, onClearAll: clearAll, "data-testid": "kanban-filter-chips" }), _jsxs(DndContext, { sensors: sensors, onDragStart: onDragStart, onDragEnd: onDragEnd, children: [_jsx("div", { className: "flex w-full min-w-0 gap-4 overflow-x-auto p-1", "data-testid": "kanban-board", children: lanes.map((stage) => {
|
|
619
619
|
const allCards = grouped.get(stage.key) ?? [];
|
|
620
620
|
// Per-lane client-side narrowing (instant, scoped to this
|
|
621
621
|
// stage). The funnel (field/value) and the lane search
|
|
@@ -710,7 +710,12 @@ function KanbanLane({ stage, count, totalCount, serverTotal, hasMore, loadingMor
|
|
|
710
710
|
text: laneFilter.text,
|
|
711
711
|
}
|
|
712
712
|
: undefined;
|
|
713
|
-
return (_jsxs("div", { ref: setNodeRef,
|
|
713
|
+
return (_jsxs("div", { ref: setNodeRef,
|
|
714
|
+
// Fluid width: lanes grow (flex-1) to fill the board when they all
|
|
715
|
+
// fit, capped at max-w so a couple of lanes don't stretch absurdly
|
|
716
|
+
// wide. Below min-w the board's overflow-x-auto takes over and the
|
|
717
|
+
// lanes scroll horizontally at their minimum width.
|
|
718
|
+
className: "group/lane flex min-w-[280px] max-w-[420px] flex-1 shrink-0 flex-col rounded-xl border bg-muted/30 transition-opacity", style: {
|
|
714
719
|
opacity: dimmed ? 0.45 : 1,
|
|
715
720
|
outline: isOver && !disabled ? '2px solid var(--ring, #3b82f6)' : 'none',
|
|
716
721
|
outlineOffset: 2,
|
package/package.json
CHANGED
|
@@ -383,6 +383,29 @@ describe('DynamicKanban render', () => {
|
|
|
383
383
|
// a secondary field label is present
|
|
384
384
|
expect(screen.getAllByText('Assignee:').length).toBeGreaterThan(0)
|
|
385
385
|
})
|
|
386
|
+
|
|
387
|
+
it('lays out fluid lanes: the board fills the width and lanes grow (flex-1) with a min/max width', async () => {
|
|
388
|
+
useMetadataCache.getState().setMetadata('issue', meta())
|
|
389
|
+
const { container } = render(
|
|
390
|
+
<ApiProvider client={fakeApi()}>
|
|
391
|
+
<DynamicKanban model="issue" />
|
|
392
|
+
</ApiProvider>,
|
|
393
|
+
)
|
|
394
|
+
await screen.findByText('Backlog')
|
|
395
|
+
// The board fills the container and scrolls horizontally only on overflow.
|
|
396
|
+
const board = container.querySelector('[data-testid="kanban-board"]')!
|
|
397
|
+
expect(board.className).toContain('w-full')
|
|
398
|
+
expect(board.className).toContain('overflow-x-auto')
|
|
399
|
+
// Each lane grows to fill the available width but never shrinks past a
|
|
400
|
+
// readable min-width nor stretches beyond a sane max-width.
|
|
401
|
+
const lanes = container.querySelectorAll('[data-stage]')
|
|
402
|
+
expect(lanes.length).toBe(4)
|
|
403
|
+
lanes.forEach((lane) => {
|
|
404
|
+
expect(lane.className).toContain('flex-1')
|
|
405
|
+
expect(lane.className).toContain('min-w-[280px]')
|
|
406
|
+
expect(lane.className).toContain('max-w-[420px]')
|
|
407
|
+
})
|
|
408
|
+
})
|
|
386
409
|
})
|
|
387
410
|
|
|
388
411
|
// The drag itself is wired by dnd-kit (pointer + layout), which happy-dom can't
|
package/src/dynamic-kanban.tsx
CHANGED
|
@@ -877,9 +877,9 @@ export function DynamicKanban({
|
|
|
877
877
|
|
|
878
878
|
if (loading) {
|
|
879
879
|
return (
|
|
880
|
-
<div className="flex gap-4 overflow-x-auto p-1">
|
|
880
|
+
<div className="flex w-full gap-4 overflow-x-auto p-1">
|
|
881
881
|
{[0, 1, 2, 3].map((i) => (
|
|
882
|
-
<div key={i} className="w-[
|
|
882
|
+
<div key={i} className="min-w-[280px] max-w-[420px] flex-1 shrink-0 space-y-3">
|
|
883
883
|
<Skeleton className="h-8 w-full" />
|
|
884
884
|
<Skeleton className="h-24 w-full" />
|
|
885
885
|
<Skeleton className="h-24 w-full" />
|
|
@@ -1023,7 +1023,7 @@ export function DynamicKanban({
|
|
|
1023
1023
|
/>
|
|
1024
1024
|
|
|
1025
1025
|
<DndContext sensors={sensors} onDragStart={onDragStart} onDragEnd={onDragEnd}>
|
|
1026
|
-
<div className="flex min-w-0 gap-4 overflow-x-auto p-1" data-testid="kanban-board">
|
|
1026
|
+
<div className="flex w-full min-w-0 gap-4 overflow-x-auto p-1" data-testid="kanban-board">
|
|
1027
1027
|
{lanes.map((stage) => {
|
|
1028
1028
|
const allCards = grouped.get(stage.key) ?? []
|
|
1029
1029
|
// Per-lane client-side narrowing (instant, scoped to this
|
|
@@ -1309,7 +1309,11 @@ function KanbanLane({
|
|
|
1309
1309
|
return (
|
|
1310
1310
|
<div
|
|
1311
1311
|
ref={setNodeRef}
|
|
1312
|
-
|
|
1312
|
+
// Fluid width: lanes grow (flex-1) to fill the board when they all
|
|
1313
|
+
// fit, capped at max-w so a couple of lanes don't stretch absurdly
|
|
1314
|
+
// wide. Below min-w the board's overflow-x-auto takes over and the
|
|
1315
|
+
// lanes scroll horizontally at their minimum width.
|
|
1316
|
+
className="group/lane flex min-w-[280px] max-w-[420px] flex-1 shrink-0 flex-col rounded-xl border bg-muted/30 transition-opacity"
|
|
1313
1317
|
style={{
|
|
1314
1318
|
opacity: dimmed ? 0.45 : 1,
|
|
1315
1319
|
outline: isOver && !disabled ? '2px solid var(--ring, #3b82f6)' : 'none',
|