@adea-ai/ui 0.101.1 → 0.102.0
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/components/ui/board/board.d.ts +39 -2
- package/dist/components/ui/board/board.d.ts.map +1 -1
- package/dist/components/ui/board/board.js +230 -92
- package/dist/components/ui/board/board.js.map +1 -1
- package/dist/components/ui/board/index.d.ts +1 -1
- package/dist/components/ui/board/index.d.ts.map +1 -1
- package/dist/components/ui/board/index.js +2 -2
- package/dist/index.js +2 -2
- package/dist/r/board.json +2 -0
- package/dist/r/registry.json +2 -0
- package/dist/r/src/components/ui/board/board.tsx +231 -77
- package/dist/r/src/components/ui/board/index.ts +2 -0
- package/dist/r/src/styles/base.css +11 -0
- package/package.json +1 -1
- package/registry.json +2 -0
- package/src/components/ui/board/board.tsx +231 -77
- package/src/components/ui/board/index.ts +2 -0
- package/src/styles/base.css +11 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type JSX } from 'solid-js';
|
|
1
|
+
import { type ComponentProps, type JSX } from 'solid-js';
|
|
2
2
|
import { type VariantProps } from '#lib/variants';
|
|
3
3
|
/**
|
|
4
4
|
* Board.
|
|
@@ -26,12 +26,39 @@ import { type VariantProps } from '#lib/variants';
|
|
|
26
26
|
* of drag props. That is deliberate: a card's contents are domain — a title, a
|
|
27
27
|
* priority tag, an assignee — and a board that rendered them itself could only
|
|
28
28
|
* ever serve one product.
|
|
29
|
+
*
|
|
30
|
+
* `collapseEmpty` folds a column with no cards to a strip one line of text wide,
|
|
31
|
+
* its label turned on its side. A board of seven lanes where three are empty
|
|
32
|
+
* otherwise spends half its width on nothing, and the lanes with work in them
|
|
33
|
+
* are the ones that need the room. A folded lane is still a full-height drop
|
|
34
|
+
* target and still accepts a keyboard move, so nothing about operating the
|
|
35
|
+
* board changes; it does not unfold under a drag, because a lane that grows
|
|
36
|
+
* under the pointer moves every lane after it and the drop lands somewhere else.
|
|
37
|
+
*
|
|
38
|
+
* Give the board a height (`class="h-full"`) and each lane scrolls on its own;
|
|
39
|
+
* leave it unconstrained and lanes grow with their cards and the page scrolls.
|
|
40
|
+
*/
|
|
41
|
+
/**
|
|
42
|
+
* A lane's identifying colour, drawn as a dot before its label. The chart hues,
|
|
43
|
+
* in the order the token set gives them, because a lane colour tells lanes apart
|
|
44
|
+
* like a series does; it carries no status. `neutral` is for a lane that should
|
|
45
|
+
* not draw the eye — a backlog, an archive.
|
|
29
46
|
*/
|
|
47
|
+
export type BoardTone = 'neutral' | 'chart-1' | 'chart-2' | 'chart-3' | 'chart-4' | 'chart-5' | 'chart-6';
|
|
30
48
|
export type BoardColumn = Readonly<{
|
|
31
49
|
id: string;
|
|
32
50
|
label: string;
|
|
33
|
-
/**
|
|
51
|
+
/** The number of cards, shown as an accent count beside the label. */
|
|
52
|
+
count?: number;
|
|
53
|
+
/** A limit or any other note, shown after the count. */
|
|
34
54
|
meta?: JSX.Element;
|
|
55
|
+
/** The lane's dot colour. Omitted, the header has no dot. */
|
|
56
|
+
tone?: BoardTone;
|
|
57
|
+
/**
|
|
58
|
+
* `false` keeps this lane open when it is empty under `collapseEmpty` — the
|
|
59
|
+
* inbox lane new cards arrive in, which should always show where they land.
|
|
60
|
+
*/
|
|
61
|
+
collapsible?: boolean;
|
|
35
62
|
/** Dim the column and refuse drops — a lane that is closed or read-only. */
|
|
36
63
|
disabled?: boolean;
|
|
37
64
|
}>;
|
|
@@ -58,6 +85,8 @@ export type BoardProps<T> = {
|
|
|
58
85
|
emptyColumn?: (column: BoardColumn) => JSX.Element;
|
|
59
86
|
/** The board's accessible name. Defaults to "Board". */
|
|
60
87
|
label?: string;
|
|
88
|
+
/** Fold columns with no cards to a narrow strip with a sideways label. */
|
|
89
|
+
collapseEmpty?: boolean;
|
|
61
90
|
class?: string;
|
|
62
91
|
};
|
|
63
92
|
export declare function Board<T>(props: BoardProps<T>): JSX.Element;
|
|
@@ -75,4 +104,12 @@ export declare function BoardCardBody(props: {
|
|
|
75
104
|
class?: string;
|
|
76
105
|
children: JSX.Element;
|
|
77
106
|
}): JSX.Element;
|
|
107
|
+
/**
|
|
108
|
+
* The card's open action: its title, as a real button whose hit area stretches
|
|
109
|
+
* over the whole card. A card is one target to a pointer — clicking anywhere on
|
|
110
|
+
* it opens it — while assistive technology still meets a named button rather
|
|
111
|
+
* than a clickable `article`. Other controls on the card sit above the stretched
|
|
112
|
+
* area by being positioned (`class="relative"`), so they keep their own click.
|
|
113
|
+
*/
|
|
114
|
+
export declare function BoardCardTrigger(props: ComponentProps<'button'>): JSX.Element;
|
|
78
115
|
//# sourceMappingURL=board.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/board/board.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/board/board.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EASnB,KAAK,GAAG,EACT,MAAM,UAAU,CAAA;AACjB,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAKtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,CAAA;AAEb,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wDAAwD;IACxD,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IAClB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAC,CAAA;AAEF,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;CACX,CAAC,CAAA;AAEF,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI;IAC1B,OAAO,EAAE,SAAS,WAAW,EAAE,CAAA;IAC/B,KAAK,EAAE,SAAS,CAAC,EAAE,CAAA;IACnB,4BAA4B;IAC5B,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAA;IAC3B,uDAAuD;IACvD,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAA;IAC/B,iFAAiF;IACjF,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAA;IACvD,MAAM,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACjC,kFAAkF;IAClF,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,KAAK,GAAG,CAAC,OAAO,CAAA;IAChE,wCAAwC;IACxC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,GAAG,CAAC,OAAO,CAAA;IAClD,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0EAA0E;IAC1E,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAyCD,wBAAgB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,eAkR5C;AAED,eAAO,MAAM,sBAAsB;;8EAGjC,CAAA;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAA;CAAE,GAAG,YAAY,CACxF,OAAO,sBAAsB,CAC9B,CAAA;AAED,4DAA4D;AAC5D,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,eAIxD;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,KAAK,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAA;CAAE,eAE7E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,QAAQ,CAAC,eAgB/D"}
|
|
@@ -1,19 +1,64 @@
|
|
|
1
1
|
import { cn } from "../../../lib/utils.js";
|
|
2
2
|
import { cva } from "../../../lib/variants.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { headingVariants, textVariants } from "../typography/typography.js";
|
|
4
|
+
import { badgeVariants } from "../badge/badge.js";
|
|
5
|
+
import { className, createComponent, delegateEvents, effect, insert, mergeProps, setAttribute, spread, template, use } from "solid-js/web";
|
|
6
|
+
import { For, Index, Show, createEffect, createMemo, createSignal, onCleanup, splitProps } from "solid-js";
|
|
5
7
|
//#region src/components/ui/board/board.tsx
|
|
6
|
-
var _tmpl$ = /*#__PURE__*/ template(`<
|
|
7
|
-
var _tmpl$2 = /*#__PURE__*/ template(`<span
|
|
8
|
-
var _tmpl$3 = /*#__PURE__*/ template(`<
|
|
9
|
-
var _tmpl$4 = /*#__PURE__*/ template(`<
|
|
10
|
-
var _tmpl$5 = /*#__PURE__*/ template(`<
|
|
11
|
-
var _tmpl$6 = /*#__PURE__*/ template(`<
|
|
12
|
-
var _tmpl$7 = /*#__PURE__*/ template(`<div>`);
|
|
8
|
+
var _tmpl$ = /*#__PURE__*/ template(`<span aria-hidden=true>`);
|
|
9
|
+
var _tmpl$2 = /*#__PURE__*/ template(`<span data-slot=board-column-count>`);
|
|
10
|
+
var _tmpl$3 = /*#__PURE__*/ template(`<div role=region tabindex=0><div class=visually-hidden role=status aria-live=polite>`);
|
|
11
|
+
var _tmpl$4 = /*#__PURE__*/ template(`<span class="ms-auto text-2xs text-muted-foreground">`);
|
|
12
|
+
var _tmpl$5 = /*#__PURE__*/ template(`<header class="flex h-10 shrink-0 items-center gap-2 px-3"><h3>`);
|
|
13
|
+
var _tmpl$6 = /*#__PURE__*/ template(`<p class="rounded-md border border-dashed border-border px-2 py-4 text-center text-2xs text-muted-foreground">`);
|
|
14
|
+
var _tmpl$7 = /*#__PURE__*/ template(`<div class="flex min-h-16 flex-1 flex-col gap-2 overflow-y-auto px-2 pb-2">`);
|
|
15
|
+
var _tmpl$8 = /*#__PURE__*/ template(`<section>`);
|
|
16
|
+
var _tmpl$9 = /*#__PURE__*/ template(`<header class="flex flex-col items-center gap-2 py-3"><h3>`);
|
|
17
|
+
var _tmpl$0 = /*#__PURE__*/ template(`<article tabindex=0 aria-roledescription="Draggable card">`);
|
|
18
|
+
var _tmpl$1 = /*#__PURE__*/ template(`<h4>`);
|
|
19
|
+
var _tmpl$10 = /*#__PURE__*/ template(`<div>`);
|
|
20
|
+
var _tmpl$11 = /*#__PURE__*/ template(`<button data-slot=board-card-trigger>`);
|
|
13
21
|
var cardDragState = {
|
|
14
22
|
idle: "",
|
|
15
23
|
dragging: "opacity-40"
|
|
16
24
|
};
|
|
25
|
+
var toneDot = {
|
|
26
|
+
neutral: "bg-muted-foreground",
|
|
27
|
+
"chart-1": "bg-chart-1",
|
|
28
|
+
"chart-2": "bg-chart-2",
|
|
29
|
+
"chart-3": "bg-chart-3",
|
|
30
|
+
"chart-4": "bg-chart-4",
|
|
31
|
+
"chart-5": "bg-chart-5",
|
|
32
|
+
"chart-6": "bg-chart-6"
|
|
33
|
+
};
|
|
34
|
+
function BoardColumnDot(props) {
|
|
35
|
+
return createComponent(Show, {
|
|
36
|
+
get when() {
|
|
37
|
+
return props.tone;
|
|
38
|
+
},
|
|
39
|
+
children: (tone) => (() => {
|
|
40
|
+
var _el$ = _tmpl$();
|
|
41
|
+
effect(() => className(_el$, cn("size-2 shrink-0 rounded-full", toneDot[tone()])));
|
|
42
|
+
return _el$;
|
|
43
|
+
})()
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function BoardColumnCount(props) {
|
|
47
|
+
return createComponent(Show, {
|
|
48
|
+
get when() {
|
|
49
|
+
return props.count !== void 0;
|
|
50
|
+
},
|
|
51
|
+
get children() {
|
|
52
|
+
var _el$2 = _tmpl$2();
|
|
53
|
+
insert(_el$2, () => props.count);
|
|
54
|
+
effect(() => className(_el$2, cn(badgeVariants({
|
|
55
|
+
variant: "subtle",
|
|
56
|
+
size: "sm"
|
|
57
|
+
}), "tabular-nums")));
|
|
58
|
+
return _el$2;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
17
62
|
function Board(props) {
|
|
18
63
|
const [local] = splitProps(props, [
|
|
19
64
|
"columns",
|
|
@@ -25,6 +70,7 @@ function Board(props) {
|
|
|
25
70
|
"children",
|
|
26
71
|
"emptyColumn",
|
|
27
72
|
"label",
|
|
73
|
+
"collapseEmpty",
|
|
28
74
|
"class"
|
|
29
75
|
]);
|
|
30
76
|
const [dragging, setDragging] = createSignal(null);
|
|
@@ -59,9 +105,15 @@ function Board(props) {
|
|
|
59
105
|
if (target?.isConnected) target.focus();
|
|
60
106
|
});
|
|
61
107
|
});
|
|
62
|
-
|
|
108
|
+
/**
|
|
109
|
+
* `always` is for a pointer drop: dragging a card is a direct act on it, so it
|
|
110
|
+
* ends focused wherever focus was. Chromium also blurs a focused control
|
|
111
|
+
* inside a draggable once the native drag starts, so "was focus in the card"
|
|
112
|
+
* cannot be read at drop time.
|
|
113
|
+
*/
|
|
114
|
+
const prepareFocus = (item, columnId, source, always = false) => {
|
|
63
115
|
const card = source ?? cardElements.get(local.itemId(item));
|
|
64
|
-
if (card
|
|
116
|
+
if (card && (always || card.contains(card.ownerDocument.activeElement))) setPendingFocus({
|
|
65
117
|
itemId: local.itemId(item),
|
|
66
118
|
columnId,
|
|
67
119
|
source: card
|
|
@@ -84,7 +136,7 @@ function Board(props) {
|
|
|
84
136
|
setDragging(null);
|
|
85
137
|
setOverColumn(null);
|
|
86
138
|
if (!item || !from || from === column.id || !accepted) return;
|
|
87
|
-
prepareFocus(item, column.id);
|
|
139
|
+
prepareFocus(item, column.id, void 0, true);
|
|
88
140
|
local.onMove({
|
|
89
141
|
itemId: local.itemId(item),
|
|
90
142
|
from,
|
|
@@ -114,105 +166,166 @@ function Board(props) {
|
|
|
114
166
|
setAnnouncement(`Moved to ${target.label}`);
|
|
115
167
|
};
|
|
116
168
|
return (() => {
|
|
117
|
-
var _el$ = _tmpl$(), _el$
|
|
118
|
-
insert(_el
|
|
169
|
+
var _el$3 = _tmpl$3(), _el$4 = _el$3.firstChild;
|
|
170
|
+
insert(_el$3, createComponent(Index, {
|
|
119
171
|
get each() {
|
|
120
172
|
return local.columns;
|
|
121
173
|
},
|
|
122
174
|
children: (column) => {
|
|
123
|
-
const items = () => byColumn().get(column.id) ?? [];
|
|
175
|
+
const items = () => byColumn().get(column().id) ?? [];
|
|
176
|
+
const collapsed = () => Boolean(local.collapseEmpty) && column().collapsible !== false && items().length === 0;
|
|
177
|
+
const over = () => overColumn() === column().id;
|
|
124
178
|
return (() => {
|
|
125
|
-
var _el$
|
|
126
|
-
_el$
|
|
179
|
+
var _el$5 = _tmpl$8();
|
|
180
|
+
_el$5.addEventListener("drop", (event) => {
|
|
127
181
|
event.preventDefault();
|
|
128
|
-
drop(column);
|
|
182
|
+
drop(column());
|
|
183
|
+
});
|
|
184
|
+
_el$5.addEventListener("dragleave", (event) => {
|
|
185
|
+
if (event.currentTarget.contains(event.relatedTarget)) return;
|
|
186
|
+
setOverColumn((current) => current === column().id ? null : current);
|
|
129
187
|
});
|
|
130
|
-
_el$
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (accepts(column)) event.preventDefault();
|
|
188
|
+
_el$5.addEventListener("dragover", (event) => {
|
|
189
|
+
setOverColumn(column().id);
|
|
190
|
+
if (accepts(column())) event.preventDefault();
|
|
134
191
|
});
|
|
135
|
-
insert(_el$5, (
|
|
136
|
-
insert(_el$4, createComponent(Show, {
|
|
192
|
+
insert(_el$5, createComponent(Show, {
|
|
137
193
|
get when() {
|
|
138
|
-
return
|
|
194
|
+
return !collapsed();
|
|
139
195
|
},
|
|
140
|
-
get
|
|
141
|
-
var _el$6 = _tmpl$2();
|
|
142
|
-
insert(_el$6, () => column.meta);
|
|
143
|
-
return _el$6;
|
|
144
|
-
}
|
|
145
|
-
}), null);
|
|
146
|
-
insert(_el$7, createComponent(For, {
|
|
147
|
-
get each() {
|
|
148
|
-
return items();
|
|
149
|
-
},
|
|
150
|
-
children: (item) => {
|
|
151
|
-
const isDragging = () => {
|
|
152
|
-
const current = dragging();
|
|
153
|
-
return Boolean(current && local.itemId(current) === local.itemId(item));
|
|
154
|
-
};
|
|
196
|
+
get fallback() {
|
|
155
197
|
return (() => {
|
|
156
|
-
var _el$
|
|
157
|
-
_el$
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
};
|
|
163
|
-
_el$
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
cardElements.set(id, element);
|
|
171
|
-
onCleanup(() => {
|
|
172
|
-
if (cardElements.get(id) === element) cardElements.delete(id);
|
|
173
|
-
});
|
|
174
|
-
}, _el$9);
|
|
175
|
-
setAttribute(_el$9, "draggable", true);
|
|
176
|
-
insert(_el$9, () => local.children(item, { dragging: isDragging() }));
|
|
177
|
-
effect(() => className(_el$9, cn("rounded-md border border-border bg-card text-sm shadow-xs", cardDragState[isDragging() ? "dragging" : "idle"])));
|
|
178
|
-
return _el$9;
|
|
198
|
+
var _el$1 = _tmpl$9(), _el$10 = _el$1.firstChild;
|
|
199
|
+
insert(_el$1, createComponent(BoardColumnDot, { get tone() {
|
|
200
|
+
return column().tone;
|
|
201
|
+
} }), _el$10);
|
|
202
|
+
insert(_el$1, createComponent(BoardColumnCount, { get count() {
|
|
203
|
+
return column().count;
|
|
204
|
+
} }), _el$10);
|
|
205
|
+
insert(_el$10, () => column().label);
|
|
206
|
+
effect(() => className(_el$10, cn(headingVariants({
|
|
207
|
+
size: "subsection",
|
|
208
|
+
leading: "none",
|
|
209
|
+
tone: "muted"
|
|
210
|
+
}), "text-vertical")));
|
|
211
|
+
return _el$1;
|
|
179
212
|
})();
|
|
180
|
-
}
|
|
181
|
-
}), null);
|
|
182
|
-
insert(_el$7, createComponent(Show, {
|
|
183
|
-
get when() {
|
|
184
|
-
return items().length === 0;
|
|
185
213
|
},
|
|
186
214
|
get children() {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
215
|
+
return [(() => {
|
|
216
|
+
var _el$6 = _tmpl$5(), _el$7 = _el$6.firstChild;
|
|
217
|
+
insert(_el$6, createComponent(BoardColumnDot, { get tone() {
|
|
218
|
+
return column().tone;
|
|
219
|
+
} }), _el$7);
|
|
220
|
+
insert(_el$7, () => column().label);
|
|
221
|
+
insert(_el$6, createComponent(BoardColumnCount, { get count() {
|
|
222
|
+
return column().count;
|
|
223
|
+
} }), null);
|
|
224
|
+
insert(_el$6, createComponent(Show, {
|
|
225
|
+
get when() {
|
|
226
|
+
return column().meta;
|
|
227
|
+
},
|
|
228
|
+
get children() {
|
|
229
|
+
var _el$8 = _tmpl$4();
|
|
230
|
+
insert(_el$8, () => column().meta);
|
|
231
|
+
return _el$8;
|
|
232
|
+
}
|
|
233
|
+
}), null);
|
|
234
|
+
effect(() => className(_el$7, cn(headingVariants({
|
|
235
|
+
size: "subsection",
|
|
236
|
+
leading: "none",
|
|
237
|
+
tone: "foreground"
|
|
238
|
+
}), "truncate")));
|
|
239
|
+
return _el$6;
|
|
240
|
+
})(), (() => {
|
|
241
|
+
var _el$9 = _tmpl$7();
|
|
242
|
+
insert(_el$9, createComponent(For, {
|
|
243
|
+
get each() {
|
|
244
|
+
return items();
|
|
245
|
+
},
|
|
246
|
+
children: (item) => {
|
|
247
|
+
const isDragging = () => {
|
|
248
|
+
const current = dragging();
|
|
249
|
+
return Boolean(current && local.itemId(current) === local.itemId(item));
|
|
250
|
+
};
|
|
251
|
+
return (() => {
|
|
252
|
+
var _el$11 = _tmpl$0();
|
|
253
|
+
_el$11.$$keydown = (event) => {
|
|
254
|
+
if (!(event.ctrlKey || event.metaKey)) return;
|
|
255
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
256
|
+
event.preventDefault();
|
|
257
|
+
moveByKeyboard(item, event.key === "ArrowRight" ? 1 : -1, event.currentTarget);
|
|
258
|
+
};
|
|
259
|
+
_el$11.addEventListener("dragend", () => {
|
|
260
|
+
setDragging(null);
|
|
261
|
+
setOverColumn(null);
|
|
262
|
+
});
|
|
263
|
+
_el$11.addEventListener("dragstart", (event) => {
|
|
264
|
+
event.dataTransfer?.setData("text/plain", local.itemId(item));
|
|
265
|
+
if (event.dataTransfer) event.dataTransfer.effectAllowed = "move";
|
|
266
|
+
setDragging(() => item);
|
|
267
|
+
});
|
|
268
|
+
use((element) => {
|
|
269
|
+
const id = local.itemId(item);
|
|
270
|
+
cardElements.set(id, element);
|
|
271
|
+
onCleanup(() => {
|
|
272
|
+
if (cardElements.get(id) === element) cardElements.delete(id);
|
|
273
|
+
});
|
|
274
|
+
}, _el$11);
|
|
275
|
+
setAttribute(_el$11, "draggable", true);
|
|
276
|
+
insert(_el$11, () => local.children(item, { dragging: isDragging() }));
|
|
277
|
+
effect(() => className(_el$11, cn("relative shrink-0 cursor-grab rounded-md border border-border bg-card text-sm shadow-xs outline-none transition-colors hover:bg-surface-hover focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle active:cursor-grabbing", cardDragState[isDragging() ? "dragging" : "idle"])));
|
|
278
|
+
return _el$11;
|
|
279
|
+
})();
|
|
280
|
+
}
|
|
281
|
+
}), null);
|
|
282
|
+
insert(_el$9, createComponent(Show, {
|
|
283
|
+
get when() {
|
|
284
|
+
return items().length === 0;
|
|
285
|
+
},
|
|
286
|
+
get children() {
|
|
287
|
+
var _el$0 = _tmpl$6();
|
|
288
|
+
insert(_el$0, () => local.emptyColumn?.(column()) ?? "Nothing here");
|
|
289
|
+
return _el$0;
|
|
290
|
+
}
|
|
291
|
+
}), null);
|
|
292
|
+
return _el$9;
|
|
293
|
+
})()];
|
|
190
294
|
}
|
|
191
|
-
})
|
|
295
|
+
}));
|
|
192
296
|
effect((_p$) => {
|
|
193
|
-
var _v$3 = cn("flex
|
|
194
|
-
|
|
195
|
-
|
|
297
|
+
var _v$3 = cn("flex shrink-0 flex-col rounded-lg border border-border bg-muted/40 transition-colors", {
|
|
298
|
+
"w-72": !collapsed(),
|
|
299
|
+
"w-10 items-center": collapsed(),
|
|
300
|
+
"border-dashed border-ring": accepts(column()) && !over(),
|
|
301
|
+
"border-ring bg-primary-subtle": accepts(column()) && over(),
|
|
302
|
+
"border-dashed opacity-60": over() && !accepts(column()),
|
|
303
|
+
"opacity-50": column().disabled
|
|
304
|
+
}), _v$4 = column().label, _v$5 = collapsed() ? "" : void 0;
|
|
305
|
+
_v$3 !== _p$.e && className(_el$5, _p$.e = _v$3);
|
|
306
|
+
_v$4 !== _p$.t && setAttribute(_el$5, "aria-label", _p$.t = _v$4);
|
|
307
|
+
_v$5 !== _p$.a && setAttribute(_el$5, "data-collapsed", _p$.a = _v$5);
|
|
196
308
|
return _p$;
|
|
197
309
|
}, {
|
|
198
310
|
e: void 0,
|
|
199
|
-
t: void 0
|
|
311
|
+
t: void 0,
|
|
312
|
+
a: void 0
|
|
200
313
|
});
|
|
201
|
-
return _el$
|
|
314
|
+
return _el$5;
|
|
202
315
|
})();
|
|
203
316
|
}
|
|
204
|
-
}), _el$
|
|
205
|
-
insert(_el$
|
|
317
|
+
}), _el$4);
|
|
318
|
+
insert(_el$4, announcement);
|
|
206
319
|
effect((_p$) => {
|
|
207
|
-
var _v$ = cn("flex min-h-0 gap-
|
|
208
|
-
_v$ !== _p$.e && className(_el
|
|
209
|
-
_v$2 !== _p$.t && setAttribute(_el
|
|
320
|
+
var _v$ = cn("flex min-h-0 gap-3 overflow-x-auto pb-2", local.class), _v$2 = local.label ?? "Board";
|
|
321
|
+
_v$ !== _p$.e && className(_el$3, _p$.e = _v$);
|
|
322
|
+
_v$2 !== _p$.t && setAttribute(_el$3, "aria-label", _p$.t = _v$2);
|
|
210
323
|
return _p$;
|
|
211
324
|
}, {
|
|
212
325
|
e: void 0,
|
|
213
326
|
t: void 0
|
|
214
327
|
});
|
|
215
|
-
return _el
|
|
328
|
+
return _el$3;
|
|
216
329
|
})();
|
|
217
330
|
}
|
|
218
331
|
var boardCardTitleVariants = cva("truncate font-medium text-foreground", {
|
|
@@ -225,23 +338,48 @@ var boardCardTitleVariants = cva("truncate font-medium text-foreground", {
|
|
|
225
338
|
/** The card's title line, at the size a board card uses. */
|
|
226
339
|
function BoardCardTitle(props) {
|
|
227
340
|
return (() => {
|
|
228
|
-
var _el$
|
|
229
|
-
insert(_el$
|
|
230
|
-
effect(() => className(_el$
|
|
231
|
-
return _el$
|
|
341
|
+
var _el$12 = _tmpl$1();
|
|
342
|
+
insert(_el$12, () => props.children);
|
|
343
|
+
effect(() => className(_el$12, cn(boardCardTitleVariants({ size: props.size }), props.class)));
|
|
344
|
+
return _el$12;
|
|
232
345
|
})();
|
|
233
346
|
}
|
|
234
347
|
/** A card's padding, so every card in an application is the same shape. */
|
|
235
348
|
function BoardCardBody(props) {
|
|
236
349
|
return (() => {
|
|
237
|
-
var _el$
|
|
238
|
-
insert(_el$
|
|
239
|
-
effect(() => className(_el$
|
|
240
|
-
return _el$
|
|
350
|
+
var _el$13 = _tmpl$10();
|
|
351
|
+
insert(_el$13, () => props.children);
|
|
352
|
+
effect(() => className(_el$13, cn("grid gap-1.5 p-2.5", props.class)));
|
|
353
|
+
return _el$13;
|
|
354
|
+
})();
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* The card's open action: its title, as a real button whose hit area stretches
|
|
358
|
+
* over the whole card. A card is one target to a pointer — clicking anywhere on
|
|
359
|
+
* it opens it — while assistive technology still meets a named button rather
|
|
360
|
+
* than a clickable `article`. Other controls on the card sit above the stretched
|
|
361
|
+
* area by being positioned (`class="relative"`), so they keep their own click.
|
|
362
|
+
*/
|
|
363
|
+
function BoardCardTrigger(props) {
|
|
364
|
+
const [local, rest] = splitProps(props, ["class", "type"]);
|
|
365
|
+
return (() => {
|
|
366
|
+
var _el$14 = _tmpl$11();
|
|
367
|
+
spread(_el$14, mergeProps({
|
|
368
|
+
get type() {
|
|
369
|
+
return local.type ?? "button";
|
|
370
|
+
},
|
|
371
|
+
get ["class"]() {
|
|
372
|
+
return cn(textVariants({
|
|
373
|
+
variant: "label",
|
|
374
|
+
tone: "foreground"
|
|
375
|
+
}), "min-w-0 flex-1 truncate rounded-sm text-start outline-none", "after:absolute after:inset-0 after:rounded-md", "focus-visible:ring-3 focus-visible:ring-primary-subtle", local.class);
|
|
376
|
+
}
|
|
377
|
+
}, rest), false, false);
|
|
378
|
+
return _el$14;
|
|
241
379
|
})();
|
|
242
380
|
}
|
|
243
381
|
delegateEvents(["keydown"]);
|
|
244
382
|
//#endregion
|
|
245
|
-
export { Board, BoardCardBody, BoardCardTitle, boardCardTitleVariants };
|
|
383
|
+
export { Board, BoardCardBody, BoardCardTitle, BoardCardTrigger, boardCardTitleVariants };
|
|
246
384
|
|
|
247
385
|
//# sourceMappingURL=board.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"board.js","names":["createEffect","createMemo","createSignal","For","onCleanup","Show","splitProps","JSX","cva","VariantProps","cn","BoardColumn","Readonly","id","label","meta","Element","disabled","BoardMove","itemId","from","to","BoardProps","columns","items","T","item","itemColumn","canDrop","onMove","move","children","state","dragging","emptyColumn","column","class","cardDragState","idle","const","Board","props","local","setDragging","overColumn","setOverColumn","announcement","setAnnouncement","cardElements","Map","HTMLElement","pendingFocus","setPendingFocus","columnId","source","cancelOnPointer","pending","document","ownerDocument","cancelOnFocus","event","FocusEvent","contains","target","Node","addEventListener","removeEventListener","moved","find","queueMicrotask","get","isConnected","focus","prepareFocus","card","activeElement","byColumn","grouped","set","push","accepts","Boolean","drop","accepted","moveByKeyboard","direction","index","findIndex","ordered","slice","toReversed","_el$","_tmpl$","_el$2","firstChild","_$insert","_$createComponent","each","_el$3","_tmpl$4","_el$4","_el$5","_el$7","nextSibling","preventDefault","current","when","_el$6","_tmpl$2","isDragging","_el$9","_tmpl$5","$$keydown","ctrlKey","metaKey","key","currentTarget","_$use","element","delete","_$setAttribute","_$effect","_$className","length","_el$8","_tmpl$3","_p$","_v$3","_v$4","e","t","undefined","_v$","_v$2","boardCardTitleVariants","variants","size","sm","md","defaultVariants","BoardCardTitleProps","BoardCardTitle","_el$0","_tmpl$6","BoardCardBody","_el$1","_tmpl$7","_$delegateEvents","_$createComponent","_$className","_$setAttribute","_$delegateEvents"],"sources":["../../../../src/components/ui/board/board.tsx"],"sourcesContent":["import {\n createEffect,\n createMemo,\n createSignal,\n For,\n onCleanup,\n Show,\n splitProps,\n type JSX,\n} from 'solid-js'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\n\n/**\n * Board.\n *\n * Columns of cards, with drag between them — the shape a task tracker, a CRM\n * pipeline, a support queue and a release plan all share. It is generic in the\n * one place that matters: the *column ids are the caller's*, and so is the rule\n * that decides which moves are legal. The component knows nothing about tasks.\n *\n * The transitions are a predicate rather than a derived table because the legal\n * moves in a real product are not \"any column to any column\". A task that is\n * `completed` may be archived but not re-queued; a lead may become a customer but\n * not a stranger again. A board that let you drop anything anywhere would encode\n * a state machine in the UI that the server rejects — so `canDrop` is required,\n * and a column that cannot receive the dragged card renders as unavailable rather\n * than silently accepting a drop that will fail.\n *\n * Three input methods, because a drag-only board is unusable by keyboard:\n * dragging with the pointer, `Ctrl`/`Cmd` + arrow keys to move a focused card\n * between columns, and whatever the caller wires into `actions`. The card is\n * focusable and its move is announced through a live region, so the board is\n * operable without a mouse.\n *\n * The card is rendered by the caller through `children`, given the item and a set\n * of drag props. That is deliberate: a card's contents are domain — a title, a\n * priority tag, an assignee — and a board that rendered them itself could only\n * ever serve one product.\n */\n\nexport type BoardColumn = Readonly<{\n id: string\n label: string\n /** A count or a limit, shown beside the label. */\n meta?: JSX.Element\n /** Dim the column and refuse drops — a lane that is closed or read-only. */\n disabled?: boolean\n}>\n\nexport type BoardMove = Readonly<{\n itemId: string\n from: string\n to: string\n}>\n\nexport type BoardProps<T> = {\n columns: readonly BoardColumn[]\n items: readonly T[]\n /** The item's stable id. */\n itemId: (item: T) => string\n /** The id of the column the item currently sits in. */\n itemColumn: (item: T) => string\n /** Whether `item` may move from `from` to `to`. Required: see the note above. */\n canDrop: (item: T, from: string, to: string) => boolean\n onMove: (move: BoardMove) => void\n /** The card body. `dragging` is true while this card is the one being dragged. */\n children: (item: T, state: { dragging: boolean }) => JSX.Element\n /** Shown when a column has no items. */\n emptyColumn?: (column: BoardColumn) => JSX.Element\n /** The board's accessible name. Defaults to \"Board\". */\n label?: string\n class?: string\n}\n\nconst cardDragState = {\n idle: '',\n dragging: 'opacity-40',\n} as const\n\nexport function Board<T>(props: BoardProps<T>) {\n const [local] = splitProps(props, [\n 'columns',\n 'items',\n 'itemId',\n 'itemColumn',\n 'canDrop',\n 'onMove',\n 'children',\n 'emptyColumn',\n 'label',\n 'class',\n ])\n\n // The dragged item, not its id: `canDrop` takes the item itself, and the\n // pointer may leave the card before it is dropped.\n const [dragging, setDragging] = createSignal<T | null>(null)\n const [overColumn, setOverColumn] = createSignal<string | null>(null)\n const [announcement, setAnnouncement] = createSignal('')\n const cardElements = new Map<string, HTMLElement>()\n const [pendingFocus, setPendingFocus] = createSignal<{\n itemId: string\n columnId: string\n source: HTMLElement\n } | null>(null)\n const cancelOnPointer = () => setPendingFocus(null)\n\n // A controlled move can settle after a server response. Restore only the\n // focus that belonged to the moved card; another focus action cancels it.\n createEffect(() => {\n const pending = pendingFocus()\n if (!pending) return\n const document = pending.source.ownerDocument\n const cancelOnFocus = (event: FocusEvent) => {\n if (!pending.source.contains(event.target as Node)) setPendingFocus(null)\n }\n document.addEventListener('focusin', cancelOnFocus)\n document.addEventListener('pointerdown', cancelOnPointer)\n onCleanup(() => {\n document.removeEventListener('focusin', cancelOnFocus)\n document.removeEventListener('pointerdown', cancelOnPointer)\n })\n })\n\n createEffect(() => {\n const pending = pendingFocus()\n if (!pending) return\n const moved = local.items.find((item) => local.itemId(item) === pending.itemId)\n if (!moved || local.itemColumn(moved) !== pending.columnId) return\n queueMicrotask(() => {\n if (pendingFocus() !== pending) return\n const target = cardElements.get(pending.itemId)\n setPendingFocus(null)\n if (target?.isConnected) target.focus()\n })\n })\n\n const prepareFocus = (item: T, columnId: string, source?: HTMLElement) => {\n const card = source ?? cardElements.get(local.itemId(item))\n if (card?.contains(card.ownerDocument.activeElement)) {\n setPendingFocus({ itemId: local.itemId(item), columnId, source: card })\n }\n }\n\n const byColumn = createMemo(() => {\n const grouped = new Map<string, T[]>()\n for (const column of local.columns) grouped.set(column.id, [])\n for (const item of local.items) grouped.get(local.itemColumn(item))?.push(item)\n return grouped\n })\n\n const accepts = (column: BoardColumn) => {\n const item = dragging()\n return Boolean(\n item && !column.disabled && local.canDrop(item, local.itemColumn(item), column.id)\n )\n }\n\n const drop = (column: BoardColumn) => {\n const item = dragging()\n const from = item ? local.itemColumn(item) : null\n const accepted = accepts(column)\n setDragging(null)\n setOverColumn(null)\n if (!item || !from || from === column.id || !accepted) return\n prepareFocus(item, column.id)\n local.onMove({ itemId: local.itemId(item), from, to: column.id })\n }\n\n /**\n * Keyboard move. `Ctrl`/`Cmd` plus an arrow is the convention for \"reorder this\n * thing within its container\" that does not collide with scrolling or with the\n * text caret, and it is the same chord a browser tab or a spreadsheet uses.\n */\n const moveByKeyboard = (item: T, direction: -1 | 1, source: HTMLElement) => {\n const from = local.itemColumn(item)\n const index = local.columns.findIndex((column) => column.id === from)\n if (index < 0) return\n const ordered =\n direction === 1 ? local.columns.slice(index + 1) : local.columns.slice(0, index).toReversed()\n const target = ordered.find(\n (column) => !column.disabled && local.canDrop(item, from, column.id)\n )\n if (!target) {\n setAnnouncement(`No column after ${from} accepts this item`)\n return\n }\n prepareFocus(item, target.id, source)\n local.onMove({ itemId: local.itemId(item), from, to: target.id })\n setAnnouncement(`Moved to ${target.label}`)\n }\n\n return (\n /*\n `role=\"region\"` + `tabindex=\"0\"` because the board scrolls horizontally and a\n keyboard user has to be able to scroll it — axe's `scrollable-region-focusable`.\n It is not enough that the cards are focusable: a board with empty columns, or\n with more columns than fit, has nothing focusable to scroll from.\n */\n <div\n class={cn('flex min-h-0 gap-4 overflow-x-auto pb-2', local.class)}\n role=\"region\"\n aria-label={local.label ?? 'Board'}\n tabindex=\"0\"\n >\n <For each={local.columns}>\n {(column) => {\n const items = () => byColumn().get(column.id) ?? []\n return (\n <section\n class={cn(\n 'flex w-72 shrink-0 flex-col gap-2 rounded-lg border border-border bg-muted/40 p-2',\n accepts(column) && 'border-ring bg-muted',\n overColumn() === column.id && !accepts(column) && 'border-dashed opacity-60',\n column.disabled && 'opacity-50'\n )}\n aria-label={column.label}\n onDragOver={(event) => {\n setOverColumn(column.id)\n if (accepts(column)) event.preventDefault()\n }}\n onDragLeave={() =>\n setOverColumn((current) => (current === column.id ? null : current))\n }\n onDrop={(event) => {\n event.preventDefault()\n drop(column)\n }}\n >\n <header class=\"flex items-center justify-between gap-2 px-1 py-0.5\">\n <h3 class=\"text-xs font-semibold text-foreground\">{column.label}</h3>\n <Show when={column.meta}>\n <span class=\"text-2xs text-muted-foreground\">{column.meta}</span>\n </Show>\n </header>\n <div class=\"flex min-h-16 flex-col gap-2\">\n <For each={items()}>\n {(item) => {\n const isDragging = () => {\n const current = dragging()\n return Boolean(current && local.itemId(current) === local.itemId(item))\n }\n return (\n <article\n ref={(element) => {\n const id = local.itemId(item)\n cardElements.set(id, element)\n onCleanup(() => {\n if (cardElements.get(id) === element) cardElements.delete(id)\n })\n }}\n class={cn(\n 'rounded-md border border-border bg-card text-sm shadow-xs',\n cardDragState[isDragging() ? 'dragging' : 'idle']\n )}\n // A board card is a control that can be moved, so it is\n // focusable and carries the chord it responds to.\n tabindex=\"0\"\n aria-roledescription=\"Draggable card\"\n draggable={true}\n onDragStart={() => setDragging(() => item)}\n onDragEnd={() => {\n setDragging(null)\n setOverColumn(null)\n }}\n onKeyDown={(event) => {\n if (!(event.ctrlKey || event.metaKey)) return\n if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') return\n event.preventDefault()\n moveByKeyboard(\n item,\n event.key === 'ArrowRight' ? 1 : -1,\n event.currentTarget\n )\n }}\n >\n {local.children(item, { dragging: isDragging() })}\n </article>\n )\n }}\n </For>\n <Show when={items().length === 0}>\n <p class=\"rounded-md border border-dashed border-border px-2 py-4 text-center text-2xs text-muted-foreground\">\n {local.emptyColumn?.(column) ?? 'Nothing here'}\n </p>\n </Show>\n </div>\n </section>\n )\n }}\n </For>\n {/*\n The keyboard move's result, announced. A drag speaks for itself — the card\n visibly moves — while a keyboard move happens with the focus elsewhere.\n */}\n <div class=\"visually-hidden\" role=\"status\" aria-live=\"polite\">\n {announcement()}\n </div>\n </div>\n )\n}\n\nexport const boardCardTitleVariants = cva('truncate font-medium text-foreground', {\n variants: { size: { sm: 'text-xs', md: 'text-sm' } },\n defaultVariants: { size: 'md' },\n})\n\nexport type BoardCardTitleProps = { class?: string; children: JSX.Element } & VariantProps<\n typeof boardCardTitleVariants\n>\n\n/** The card's title line, at the size a board card uses. */\nexport function BoardCardTitle(props: BoardCardTitleProps) {\n return (\n <h4 class={cn(boardCardTitleVariants({ size: props.size }), props.class)}>{props.children}</h4>\n )\n}\n\n/** A card's padding, so every card in an application is the same shape. */\nexport function BoardCardBody(props: { class?: string; children: JSX.Element }) {\n return <div class={cn('grid gap-1.5 p-2.5', props.class)}>{props.children}</div>\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"board.js","names":["ComponentProps","createEffect","createMemo","createSignal","For","Index","onCleanup","Show","splitProps","JSX","cva","VariantProps","cn","badgeVariants","headingVariants","textVariants","BoardTone","BoardColumn","Readonly","id","label","count","meta","Element","tone","collapsible","disabled","BoardMove","itemId","from","to","BoardProps","columns","items","T","item","itemColumn","canDrop","onMove","move","children","state","dragging","emptyColumn","column","collapseEmpty","class","cardDragState","idle","const","toneDot","Record","neutral","BoardColumnDot","props","_$createComponent","when","_el$","_tmpl$","_$effect","_$className","BoardColumnCount","undefined","_el$2","_tmpl$2","_$insert","variant","size","Board","local","setDragging","overColumn","setOverColumn","announcement","setAnnouncement","cardElements","Map","HTMLElement","pendingFocus","setPendingFocus","columnId","source","cancelOnPointer","pending","document","ownerDocument","cancelOnFocus","event","FocusEvent","contains","target","Node","addEventListener","removeEventListener","moved","find","queueMicrotask","get","isConnected","focus","prepareFocus","always","card","activeElement","byColumn","grouped","set","push","accepts","Boolean","drop","accepted","moveByKeyboard","direction","index","findIndex","ordered","slice","toReversed","_el$3","_tmpl$3","_el$4","firstChild","each","collapsed","length","over","_el$5","_tmpl$8","preventDefault","currentTarget","relatedTarget","current","fallback","_el$1","_tmpl$9","_el$10","leading","_el$6","_tmpl$5","_el$7","_el$8","_tmpl$4","_el$9","_tmpl$7","isDragging","_el$11","_tmpl$0","$$keydown","ctrlKey","metaKey","key","dataTransfer","setData","effectAllowed","_$use","element","delete","_$setAttribute","_el$0","_tmpl$6","_p$","_v$3","_v$4","_v$5","e","t","a","_v$","_v$2","boardCardTitleVariants","variants","sm","md","defaultVariants","BoardCardTitleProps","BoardCardTitle","_el$12","_tmpl$1","BoardCardBody","_el$13","_tmpl$10","BoardCardTrigger","rest","_el$14","_tmpl$11","_$spread","_$mergeProps","type","_$delegateEvents","_$createComponent","_$className","_$setAttribute","_$mergeProps","_$delegateEvents"],"sources":["../../../../src/components/ui/board/board.tsx"],"sourcesContent":["import {\n type ComponentProps,\n createEffect,\n createMemo,\n createSignal,\n For,\n Index,\n onCleanup,\n Show,\n splitProps,\n type JSX,\n} from 'solid-js'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\nimport { badgeVariants } from '../badge/badge'\nimport { headingVariants, textVariants } from '../typography'\n\n/**\n * Board.\n *\n * Columns of cards, with drag between them — the shape a task tracker, a CRM\n * pipeline, a support queue and a release plan all share. It is generic in the\n * one place that matters: the *column ids are the caller's*, and so is the rule\n * that decides which moves are legal. The component knows nothing about tasks.\n *\n * The transitions are a predicate rather than a derived table because the legal\n * moves in a real product are not \"any column to any column\". A task that is\n * `completed` may be archived but not re-queued; a lead may become a customer but\n * not a stranger again. A board that let you drop anything anywhere would encode\n * a state machine in the UI that the server rejects — so `canDrop` is required,\n * and a column that cannot receive the dragged card renders as unavailable rather\n * than silently accepting a drop that will fail.\n *\n * Three input methods, because a drag-only board is unusable by keyboard:\n * dragging with the pointer, `Ctrl`/`Cmd` + arrow keys to move a focused card\n * between columns, and whatever the caller wires into `actions`. The card is\n * focusable and its move is announced through a live region, so the board is\n * operable without a mouse.\n *\n * The card is rendered by the caller through `children`, given the item and a set\n * of drag props. That is deliberate: a card's contents are domain — a title, a\n * priority tag, an assignee — and a board that rendered them itself could only\n * ever serve one product.\n *\n * `collapseEmpty` folds a column with no cards to a strip one line of text wide,\n * its label turned on its side. A board of seven lanes where three are empty\n * otherwise spends half its width on nothing, and the lanes with work in them\n * are the ones that need the room. A folded lane is still a full-height drop\n * target and still accepts a keyboard move, so nothing about operating the\n * board changes; it does not unfold under a drag, because a lane that grows\n * under the pointer moves every lane after it and the drop lands somewhere else.\n *\n * Give the board a height (`class=\"h-full\"`) and each lane scrolls on its own;\n * leave it unconstrained and lanes grow with their cards and the page scrolls.\n */\n\n/**\n * A lane's identifying colour, drawn as a dot before its label. The chart hues,\n * in the order the token set gives them, because a lane colour tells lanes apart\n * like a series does; it carries no status. `neutral` is for a lane that should\n * not draw the eye — a backlog, an archive.\n */\nexport type BoardTone =\n | 'neutral'\n | 'chart-1'\n | 'chart-2'\n | 'chart-3'\n | 'chart-4'\n | 'chart-5'\n | 'chart-6'\n\nexport type BoardColumn = Readonly<{\n id: string\n label: string\n /** The number of cards, shown as an accent count beside the label. */\n count?: number\n /** A limit or any other note, shown after the count. */\n meta?: JSX.Element\n /** The lane's dot colour. Omitted, the header has no dot. */\n tone?: BoardTone\n /**\n * `false` keeps this lane open when it is empty under `collapseEmpty` — the\n * inbox lane new cards arrive in, which should always show where they land.\n */\n collapsible?: boolean\n /** Dim the column and refuse drops — a lane that is closed or read-only. */\n disabled?: boolean\n}>\n\nexport type BoardMove = Readonly<{\n itemId: string\n from: string\n to: string\n}>\n\nexport type BoardProps<T> = {\n columns: readonly BoardColumn[]\n items: readonly T[]\n /** The item's stable id. */\n itemId: (item: T) => string\n /** The id of the column the item currently sits in. */\n itemColumn: (item: T) => string\n /** Whether `item` may move from `from` to `to`. Required: see the note above. */\n canDrop: (item: T, from: string, to: string) => boolean\n onMove: (move: BoardMove) => void\n /** The card body. `dragging` is true while this card is the one being dragged. */\n children: (item: T, state: { dragging: boolean }) => JSX.Element\n /** Shown when a column has no items. */\n emptyColumn?: (column: BoardColumn) => JSX.Element\n /** The board's accessible name. Defaults to \"Board\". */\n label?: string\n /** Fold columns with no cards to a narrow strip with a sideways label. */\n collapseEmpty?: boolean\n class?: string\n}\n\nconst cardDragState = {\n idle: '',\n dragging: 'opacity-40',\n} as const\n\nconst toneDot: Record<BoardTone, string> = {\n neutral: 'bg-muted-foreground',\n 'chart-1': 'bg-chart-1',\n 'chart-2': 'bg-chart-2',\n 'chart-3': 'bg-chart-3',\n 'chart-4': 'bg-chart-4',\n 'chart-5': 'bg-chart-5',\n 'chart-6': 'bg-chart-6',\n}\n\nfunction BoardColumnDot(props: { tone?: BoardTone }) {\n return (\n <Show when={props.tone}>\n {(tone) => (\n <span aria-hidden=\"true\" class={cn('size-2 shrink-0 rounded-full', toneDot[tone()])} />\n )}\n </Show>\n )\n}\n\nfunction BoardColumnCount(props: { count?: number }) {\n return (\n <Show when={props.count !== undefined}>\n {/* The Badge's classes, not the component: Board stays free of Kobalte. */}\n <span\n class={cn(badgeVariants({ variant: 'subtle', size: 'sm' }), 'tabular-nums')}\n data-slot=\"board-column-count\"\n >\n {props.count}\n </span>\n </Show>\n )\n}\n\nexport function Board<T>(props: BoardProps<T>) {\n const [local] = splitProps(props, [\n 'columns',\n 'items',\n 'itemId',\n 'itemColumn',\n 'canDrop',\n 'onMove',\n 'children',\n 'emptyColumn',\n 'label',\n 'collapseEmpty',\n 'class',\n ])\n\n // The dragged item, not its id: `canDrop` takes the item itself, and the\n // pointer may leave the card before it is dropped.\n const [dragging, setDragging] = createSignal<T | null>(null)\n const [overColumn, setOverColumn] = createSignal<string | null>(null)\n const [announcement, setAnnouncement] = createSignal('')\n const cardElements = new Map<string, HTMLElement>()\n const [pendingFocus, setPendingFocus] = createSignal<{\n itemId: string\n columnId: string\n source: HTMLElement\n } | null>(null)\n const cancelOnPointer = () => setPendingFocus(null)\n\n // A controlled move can settle after a server response. Restore only the\n // focus that belonged to the moved card; another focus action cancels it.\n createEffect(() => {\n const pending = pendingFocus()\n if (!pending) return\n const document = pending.source.ownerDocument\n const cancelOnFocus = (event: FocusEvent) => {\n if (!pending.source.contains(event.target as Node)) setPendingFocus(null)\n }\n document.addEventListener('focusin', cancelOnFocus)\n document.addEventListener('pointerdown', cancelOnPointer)\n onCleanup(() => {\n document.removeEventListener('focusin', cancelOnFocus)\n document.removeEventListener('pointerdown', cancelOnPointer)\n })\n })\n\n createEffect(() => {\n const pending = pendingFocus()\n if (!pending) return\n const moved = local.items.find((item) => local.itemId(item) === pending.itemId)\n if (!moved || local.itemColumn(moved) !== pending.columnId) return\n queueMicrotask(() => {\n if (pendingFocus() !== pending) return\n const target = cardElements.get(pending.itemId)\n setPendingFocus(null)\n if (target?.isConnected) target.focus()\n })\n })\n\n /**\n * `always` is for a pointer drop: dragging a card is a direct act on it, so it\n * ends focused wherever focus was. Chromium also blurs a focused control\n * inside a draggable once the native drag starts, so \"was focus in the card\"\n * cannot be read at drop time.\n */\n const prepareFocus = (item: T, columnId: string, source?: HTMLElement, always = false) => {\n const card = source ?? cardElements.get(local.itemId(item))\n if (card && (always || card.contains(card.ownerDocument.activeElement))) {\n setPendingFocus({ itemId: local.itemId(item), columnId, source: card })\n }\n }\n\n const byColumn = createMemo(() => {\n const grouped = new Map<string, T[]>()\n for (const column of local.columns) grouped.set(column.id, [])\n for (const item of local.items) grouped.get(local.itemColumn(item))?.push(item)\n return grouped\n })\n\n const accepts = (column: BoardColumn) => {\n const item = dragging()\n return Boolean(\n item && !column.disabled && local.canDrop(item, local.itemColumn(item), column.id)\n )\n }\n\n const drop = (column: BoardColumn) => {\n const item = dragging()\n const from = item ? local.itemColumn(item) : null\n const accepted = accepts(column)\n setDragging(null)\n setOverColumn(null)\n if (!item || !from || from === column.id || !accepted) return\n prepareFocus(item, column.id, undefined, true)\n local.onMove({ itemId: local.itemId(item), from, to: column.id })\n }\n\n /**\n * Keyboard move. `Ctrl`/`Cmd` plus an arrow is the convention for \"reorder this\n * thing within its container\" that does not collide with scrolling or with the\n * text caret, and it is the same chord a browser tab or a spreadsheet uses.\n */\n const moveByKeyboard = (item: T, direction: -1 | 1, source: HTMLElement) => {\n const from = local.itemColumn(item)\n const index = local.columns.findIndex((column) => column.id === from)\n if (index < 0) return\n const ordered =\n direction === 1 ? local.columns.slice(index + 1) : local.columns.slice(0, index).toReversed()\n const target = ordered.find(\n (column) => !column.disabled && local.canDrop(item, from, column.id)\n )\n if (!target) {\n setAnnouncement(`No column after ${from} accepts this item`)\n return\n }\n prepareFocus(item, target.id, source)\n local.onMove({ itemId: local.itemId(item), from, to: target.id })\n setAnnouncement(`Moved to ${target.label}`)\n }\n\n return (\n /*\n `role=\"region\"` + `tabindex=\"0\"` because the board scrolls horizontally and a\n keyboard user has to be able to scroll it — axe's `scrollable-region-focusable`.\n It is not enough that the cards are focusable: a board with empty columns, or\n with more columns than fit, has nothing focusable to scroll from.\n */\n <div\n class={cn('flex min-h-0 gap-3 overflow-x-auto pb-2', local.class)}\n role=\"region\"\n aria-label={local.label ?? 'Board'}\n tabindex=\"0\"\n >\n {/*\n Index, not For: callers derive columns (a count, a tone) and hand over\n fresh objects whenever a card moves. Keyed by identity, every lane would\n remount on each move and take the moved card's restored focus with it.\n */}\n <Index each={local.columns}>\n {(column) => {\n const items = () => byColumn().get(column().id) ?? []\n const collapsed = () =>\n Boolean(local.collapseEmpty) && column().collapsible !== false && items().length === 0\n const over = () => overColumn() === column().id\n return (\n <section\n class={cn(\n 'flex shrink-0 flex-col rounded-lg border border-border bg-muted/40 transition-colors',\n {\n 'w-72': !collapsed(),\n 'w-10 items-center': collapsed(),\n 'border-dashed border-ring': accepts(column()) && !over(),\n 'border-ring bg-primary-subtle': accepts(column()) && over(),\n 'border-dashed opacity-60': over() && !accepts(column()),\n 'opacity-50': column().disabled,\n }\n )}\n aria-label={column().label}\n data-collapsed={collapsed() ? '' : undefined}\n onDragOver={(event) => {\n setOverColumn(column().id)\n if (accepts(column())) event.preventDefault()\n }}\n onDragLeave={(event) => {\n // Leaving for a child is not leaving the lane.\n if (event.currentTarget.contains(event.relatedTarget as Node | null)) return\n setOverColumn((current) => (current === column().id ? null : current))\n }}\n onDrop={(event) => {\n event.preventDefault()\n drop(column())\n }}\n >\n <Show\n when={!collapsed()}\n fallback={\n <header class=\"flex flex-col items-center gap-2 py-3\">\n <BoardColumnDot tone={column().tone} />\n <BoardColumnCount count={column().count} />\n <h3\n class={cn(\n headingVariants({ size: 'subsection', leading: 'none', tone: 'muted' }),\n 'text-vertical'\n )}\n >\n {column().label}\n </h3>\n </header>\n }\n >\n <header class=\"flex h-10 shrink-0 items-center gap-2 px-3\">\n <BoardColumnDot tone={column().tone} />\n <h3\n class={cn(\n headingVariants({ size: 'subsection', leading: 'none', tone: 'foreground' }),\n 'truncate'\n )}\n >\n {column().label}\n </h3>\n <BoardColumnCount count={column().count} />\n <Show when={column().meta}>\n <span class=\"ms-auto text-2xs text-muted-foreground\">{column().meta}</span>\n </Show>\n </header>\n <div class=\"flex min-h-16 flex-1 flex-col gap-2 overflow-y-auto px-2 pb-2\">\n <For each={items()}>\n {(item) => {\n const isDragging = () => {\n const current = dragging()\n return Boolean(current && local.itemId(current) === local.itemId(item))\n }\n return (\n <article\n ref={(element) => {\n const id = local.itemId(item)\n cardElements.set(id, element)\n onCleanup(() => {\n if (cardElements.get(id) === element) cardElements.delete(id)\n })\n }}\n class={cn(\n 'relative shrink-0 cursor-grab rounded-md border border-border bg-card text-sm shadow-xs outline-none transition-colors hover:bg-surface-hover focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle active:cursor-grabbing',\n cardDragState[isDragging() ? 'dragging' : 'idle']\n )}\n // A board card is a control that can be moved, so it is\n // focusable and carries the chord it responds to.\n tabindex=\"0\"\n aria-roledescription=\"Draggable card\"\n draggable={true}\n onDragStart={(event) => {\n event.dataTransfer?.setData('text/plain', local.itemId(item))\n if (event.dataTransfer) event.dataTransfer.effectAllowed = 'move'\n setDragging(() => item)\n }}\n onDragEnd={() => {\n setDragging(null)\n setOverColumn(null)\n }}\n onKeyDown={(event) => {\n if (!(event.ctrlKey || event.metaKey)) return\n if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') return\n event.preventDefault()\n moveByKeyboard(\n item,\n event.key === 'ArrowRight' ? 1 : -1,\n event.currentTarget\n )\n }}\n >\n {local.children(item, { dragging: isDragging() })}\n </article>\n )\n }}\n </For>\n <Show when={items().length === 0}>\n <p class=\"rounded-md border border-dashed border-border px-2 py-4 text-center text-2xs text-muted-foreground\">\n {local.emptyColumn?.(column()) ?? 'Nothing here'}\n </p>\n </Show>\n </div>\n </Show>\n </section>\n )\n }}\n </Index>\n {/*\n The keyboard move's result, announced. A drag speaks for itself — the card\n visibly moves — while a keyboard move happens with the focus elsewhere.\n */}\n <div class=\"visually-hidden\" role=\"status\" aria-live=\"polite\">\n {announcement()}\n </div>\n </div>\n )\n}\n\nexport const boardCardTitleVariants = cva('truncate font-medium text-foreground', {\n variants: { size: { sm: 'text-xs', md: 'text-sm' } },\n defaultVariants: { size: 'md' },\n})\n\nexport type BoardCardTitleProps = { class?: string; children: JSX.Element } & VariantProps<\n typeof boardCardTitleVariants\n>\n\n/** The card's title line, at the size a board card uses. */\nexport function BoardCardTitle(props: BoardCardTitleProps) {\n return (\n <h4 class={cn(boardCardTitleVariants({ size: props.size }), props.class)}>{props.children}</h4>\n )\n}\n\n/** A card's padding, so every card in an application is the same shape. */\nexport function BoardCardBody(props: { class?: string; children: JSX.Element }) {\n return <div class={cn('grid gap-1.5 p-2.5', props.class)}>{props.children}</div>\n}\n\n/**\n * The card's open action: its title, as a real button whose hit area stretches\n * over the whole card. A card is one target to a pointer — clicking anywhere on\n * it opens it — while assistive technology still meets a named button rather\n * than a clickable `article`. Other controls on the card sit above the stretched\n * area by being positioned (`class=\"relative\"`), so they keep their own click.\n */\nexport function BoardCardTrigger(props: ComponentProps<'button'>) {\n const [local, rest] = splitProps(props, ['class', 'type'])\n return (\n <button\n type={local.type ?? 'button'}\n data-slot=\"board-card-trigger\"\n class={cn(\n textVariants({ variant: 'label', tone: 'foreground' }),\n 'min-w-0 flex-1 truncate rounded-sm text-start outline-none',\n 'after:absolute after:inset-0 after:rounded-md',\n 'focus-visible:ring-3 focus-visible:ring-primary-subtle',\n local.class\n )}\n {...rest}\n />\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { Board, BoardCardBody, BoardCardTitle, boardCardTitleVariants, type BoardCardTitleProps, type BoardColumn, type BoardMove, type BoardProps, } from './board';
|
|
1
|
+
export { Board, BoardCardBody, BoardCardTitle, BoardCardTrigger, boardCardTitleVariants, type BoardCardTitleProps, type BoardColumn, type BoardMove, type BoardProps, type BoardTone, } from './board';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/board/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/board/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,SAAS,GACf,MAAM,SAAS,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Board, BoardCardBody, BoardCardTitle, boardCardTitleVariants } from "./board.js";
|
|
2
|
-
export { Board, BoardCardBody, BoardCardTitle, boardCardTitleVariants };
|
|
1
|
+
import { Board, BoardCardBody, BoardCardTitle, BoardCardTrigger, boardCardTitleVariants } from "./board.js";
|
|
2
|
+
export { Board, BoardCardBody, BoardCardTitle, BoardCardTrigger, boardCardTitleVariants };
|