@object-ui/plugin-kanban 3.1.3 → 3.1.5

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.
@@ -1,350 +0,0 @@
1
- import { j as e, P as Q } from "./index-DP2mI15e.js";
2
- import * as p from "react";
3
- import { u as F, a as V, D as ee, c as se, S as _, v as H, b as te, d as re, T as ae, P as ne, e as J, C as ie } from "./sortable.esm-CNNHgHk5.js";
4
- import { Card as oe, CardHeader as le, CardTitle as de, CardDescription as ce, CardContent as ue, Badge as T, ScrollArea as me, Button as fe, Input as xe } from "@object-ui/components";
5
- import { useHasDndProvider as pe, useDnd as ge } from "@object-ui/react";
6
- const E = (...s) => s.filter(Boolean).join(" "), R = "Uncategorized";
7
- function he(s, c) {
8
- if (!c || c.length === 0) return {};
9
- for (const i of c) {
10
- const u = s[i.field];
11
- if (u == null) continue;
12
- let r = !1;
13
- const m = String(u);
14
- switch (i.operator) {
15
- case "equals":
16
- r = m === String(i.value);
17
- break;
18
- case "not_equals":
19
- r = m !== String(i.value);
20
- break;
21
- case "contains":
22
- r = m.toLowerCase().includes(String(i.value).toLowerCase());
23
- break;
24
- case "in":
25
- r = Array.isArray(i.value) && i.value.includes(m);
26
- break;
27
- }
28
- if (r)
29
- return {
30
- ...i.backgroundColor ? { backgroundColor: i.backgroundColor } : {},
31
- ...i.borderColor ? { borderColor: i.borderColor } : {}
32
- };
33
- }
34
- return {};
35
- }
36
- function $({ card: s, onCardClick: c, conditionalFormatting: i }) {
37
- const {
38
- attributes: u,
39
- listeners: r,
40
- setNodeRef: m,
41
- transform: f,
42
- transition: v,
43
- isDragging: g
44
- } = J({ id: s.id }), n = {
45
- transform: ie.Transform.toString(f),
46
- transition: v,
47
- opacity: g ? 0.5 : void 0
48
- }, b = he(s, i);
49
- return /* @__PURE__ */ e.jsx(
50
- "div",
51
- {
52
- ref: m,
53
- style: n,
54
- ...u,
55
- ...r,
56
- role: "listitem",
57
- "aria-label": s.title,
58
- onClick: () => c?.(s),
59
- children: /* @__PURE__ */ e.jsxs(oe, { className: "mb-2 cursor-grab active:cursor-grabbing border-border border-l-4 border-l-primary/40 bg-card/60 hover:border-primary/40 hover:shadow-lg hover:shadow-primary/10 transition-all duration-300 group touch-manipulation", style: b, children: [
60
- s.coverImage && /* @__PURE__ */ e.jsx("div", { className: "w-full h-32 overflow-hidden rounded-t-lg", children: /* @__PURE__ */ e.jsx(
61
- "img",
62
- {
63
- src: s.coverImage,
64
- alt: "",
65
- className: "w-full h-full object-cover",
66
- loading: "lazy"
67
- }
68
- ) }),
69
- /* @__PURE__ */ e.jsxs(le, { className: "p-2 sm:p-4", children: [
70
- /* @__PURE__ */ e.jsx(de, { className: "text-xs sm:text-sm font-medium font-mono tracking-tight text-foreground group-hover:text-primary transition-colors", children: s.title }),
71
- s.description && /* @__PURE__ */ e.jsx(ce, { className: "text-xs text-muted-foreground font-mono line-clamp-2 sm:line-clamp-none", children: s.description })
72
- ] }),
73
- s.badges && s.badges.length > 0 && /* @__PURE__ */ e.jsx(ue, { className: "p-2 sm:p-4 pt-0", children: /* @__PURE__ */ e.jsx("div", { className: "flex flex-wrap gap-1", children: s.badges.map((w, C) => /* @__PURE__ */ e.jsx(T, { variant: w.variant || "default", className: "text-xs", children: w.label }, C)) }) })
74
- ] })
75
- }
76
- );
77
- }
78
- function ve({ columnId: s, onAdd: c }) {
79
- const [i, u] = p.useState(!1), [r, m] = p.useState(""), f = p.useRef(null), v = () => {
80
- const n = r.trim();
81
- n && (c(s, n), m("")), u(!1);
82
- }, g = (n) => {
83
- n.key === "Enter" ? (n.preventDefault(), v()) : n.key === "Escape" && (m(""), u(!1));
84
- };
85
- return i ? /* @__PURE__ */ e.jsx("div", { className: "mt-2 space-y-2", children: /* @__PURE__ */ e.jsx(
86
- xe,
87
- {
88
- ref: f,
89
- value: r,
90
- onChange: (n) => m(n.target.value),
91
- onKeyDown: g,
92
- onBlur: v,
93
- placeholder: "Enter card title...",
94
- className: "text-sm",
95
- autoFocus: !0
96
- }
97
- ) }) : /* @__PURE__ */ e.jsxs(
98
- fe,
99
- {
100
- variant: "ghost",
101
- size: "sm",
102
- className: "w-full mt-2 text-muted-foreground hover:text-foreground",
103
- onClick: () => {
104
- u(!0), setTimeout(() => f.current?.focus(), 0);
105
- },
106
- children: [
107
- /* @__PURE__ */ e.jsx(Q, { className: "h-4 w-4 mr-1" }),
108
- "Add Card"
109
- ]
110
- }
111
- );
112
- }
113
- function be({
114
- column: s,
115
- cards: c,
116
- onCardClick: i,
117
- quickAdd: u,
118
- onQuickAdd: r,
119
- conditionalFormatting: m
120
- }) {
121
- const f = c || [], { setNodeRef: v } = J({
122
- id: s.id,
123
- data: {
124
- type: "column"
125
- }
126
- }), g = s.limit && f.length >= s.limit;
127
- return /* @__PURE__ */ e.jsxs(
128
- "div",
129
- {
130
- ref: v,
131
- role: "group",
132
- "aria-label": s.title,
133
- className: E(
134
- "flex flex-col w-[85vw] sm:w-80 flex-shrink-0 rounded-lg border border-border bg-card/20 backdrop-blur-sm shadow-xl snap-start",
135
- s.className
136
- ),
137
- children: [
138
- /* @__PURE__ */ e.jsx("div", { className: "p-3 sm:p-4 border-b border-border/50 bg-muted/30 rounded-t-lg", children: /* @__PURE__ */ e.jsxs("div", { className: "flex items-center justify-between", children: [
139
- /* @__PURE__ */ e.jsx("h3", { id: `kanban-col-${s.id}`, className: "font-mono text-xs sm:text-sm font-semibold tracking-wider text-primary/90 uppercase truncate", children: s.title }),
140
- /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2", children: [
141
- /* @__PURE__ */ e.jsxs(T, { variant: "secondary", className: "text-xs font-mono tabular-nums", children: [
142
- f.length,
143
- s.limit && ` / ${s.limit}`
144
- ] }),
145
- g && /* @__PURE__ */ e.jsx(T, { variant: "destructive", className: "text-xs", children: "Full" })
146
- ] })
147
- ] }) }),
148
- /* @__PURE__ */ e.jsxs(me, { className: "flex-1 p-4", children: [
149
- /* @__PURE__ */ e.jsx(
150
- _,
151
- {
152
- items: f.map((n) => n.id),
153
- strategy: H,
154
- children: /* @__PURE__ */ e.jsxs("div", { className: "space-y-2", role: "list", "aria-label": `${s.title} cards`, children: [
155
- f.length === 0 && /* @__PURE__ */ e.jsx("div", { className: "flex flex-col items-center justify-center py-8 text-muted-foreground/50", children: /* @__PURE__ */ e.jsx("span", { className: "text-xs font-mono", children: "No cards" }) }),
156
- f.map((n) => /* @__PURE__ */ e.jsx($, { card: n, onCardClick: i, conditionalFormatting: m }, n.id))
157
- ] })
158
- }
159
- ),
160
- u && r && /* @__PURE__ */ e.jsx(ve, { columnId: s.id, onAdd: r })
161
- ] })
162
- ]
163
- }
164
- );
165
- }
166
- function je({ children: s }) {
167
- const c = ge();
168
- return /* @__PURE__ */ e.jsx(e.Fragment, { children: s(c) });
169
- }
170
- function we({ columns: s, onCardMove: c, onCardClick: i, className: u, quickAdd: r, onQuickAdd: m, coverImageField: f, conditionalFormatting: v, swimlaneField: g }) {
171
- return pe() ? /* @__PURE__ */ e.jsx(je, { children: (b) => /* @__PURE__ */ e.jsx(z, { columns: s, onCardMove: c, onCardClick: i, className: u, dnd: b, quickAdd: r, onQuickAdd: m, coverImageField: f, conditionalFormatting: v, swimlaneField: g }) }) : /* @__PURE__ */ e.jsx(z, { columns: s, onCardMove: c, onCardClick: i, className: u, dnd: null, quickAdd: r, onQuickAdd: m, coverImageField: f, conditionalFormatting: v, swimlaneField: g });
172
- }
173
- function z({ columns: s, onCardMove: c, onCardClick: i, className: u, dnd: r, quickAdd: m, onQuickAdd: f, coverImageField: v, conditionalFormatting: g, swimlaneField: n }) {
174
- const [b, w] = p.useState(null), C = n ? `objectui:kanban-collapsed:${n}` : null, [M, U] = p.useState(() => {
175
- if (!C) return /* @__PURE__ */ new Set();
176
- try {
177
- const t = localStorage.getItem(C);
178
- if (t) {
179
- const o = JSON.parse(t);
180
- if (Array.isArray(o)) return new Set(o.filter((a) => typeof a == "string"));
181
- }
182
- } catch {
183
- }
184
- return /* @__PURE__ */ new Set();
185
- }), A = p.useMemo(() => (s || []).map((t) => ({
186
- ...t,
187
- cards: t.cards || []
188
- })), [s]), [x, B] = p.useState(A);
189
- p.useEffect(() => {
190
- B(A);
191
- }, [A]);
192
- const O = p.useMemo(() => {
193
- if (!n) return null;
194
- const t = x.flatMap((a) => a.cards), o = /* @__PURE__ */ new Set();
195
- return t.forEach((a) => {
196
- const l = a[n];
197
- o.add(l != null ? String(l) : R);
198
- }), Array.from(o).sort();
199
- }, [x, n]), q = p.useCallback((t) => {
200
- U((o) => {
201
- const a = new Set(o);
202
- if (a.has(t) ? a.delete(t) : a.add(t), C)
203
- try {
204
- localStorage.setItem(C, JSON.stringify([...a]));
205
- } catch {
206
- }
207
- return a;
208
- });
209
- }, [C]), G = F(
210
- V(ne, {
211
- activationConstraint: {
212
- distance: 5
213
- }
214
- }),
215
- V(ae, {
216
- activationConstraint: {
217
- delay: 200,
218
- tolerance: 5
219
- }
220
- })
221
- ), Z = (t) => {
222
- const { active: o } = t, a = X(o.id);
223
- if (w(a), r && a) {
224
- const l = K(a.id);
225
- l && r.startDrag({ id: a.id, type: "kanban-card", data: a, sourceId: l.id });
226
- }
227
- }, W = (t) => {
228
- const { active: o, over: a } = t;
229
- if (w(null), !a) {
230
- r && r.endDrag();
231
- return;
232
- }
233
- const l = o.id, h = a.id;
234
- if (l === h) {
235
- r && r.endDrag();
236
- return;
237
- }
238
- const d = K(l), y = K(h) || Y(h);
239
- if (!d || !y) {
240
- r && r.endDrag();
241
- return;
242
- }
243
- if (d.id === y.id) {
244
- const N = [...d.cards], S = N.findIndex((j) => j.id === l), L = N.findIndex((j) => j.id === h), P = re(N, S, L);
245
- B(
246
- (j) => j.map(
247
- (D) => D.id === d.id ? { ...D, cards: P } : D
248
- )
249
- );
250
- } else {
251
- const N = [...d.cards], S = [...y.cards], L = N.findIndex((k) => k.id === l), j = h === y.id ? S.length : S.findIndex((k) => k.id === h), [D] = N.splice(L, 1);
252
- S.splice(j, 0, D), B(
253
- (k) => k.map((I) => I.id === d.id ? { ...I, cards: N } : I.id === y.id ? { ...I, cards: S } : I)
254
- ), c && c(l, d.id, y.id, j);
255
- }
256
- r && r.endDrag(y.id);
257
- }, X = p.useCallback(
258
- (t) => {
259
- for (const o of x) {
260
- const a = o.cards.find((l) => l.id === t);
261
- if (a) return a;
262
- }
263
- return null;
264
- },
265
- [x]
266
- ), K = p.useCallback(
267
- (t) => x.find((o) => o.cards.some((a) => a.id === t)) || null,
268
- [x]
269
- ), Y = p.useCallback(
270
- (t) => x.find((o) => o.id === t) || null,
271
- [x]
272
- );
273
- return /* @__PURE__ */ e.jsxs(
274
- ee,
275
- {
276
- sensors: G,
277
- collisionDetection: se,
278
- onDragStart: Z,
279
- onDragEnd: W,
280
- children: [
281
- /* @__PURE__ */ e.jsxs("div", { className: "flex sm:hidden items-center justify-between px-3 pb-2 text-xs text-muted-foreground", children: [
282
- /* @__PURE__ */ e.jsxs("span", { children: [
283
- x.length,
284
- " columns"
285
- ] }),
286
- /* @__PURE__ */ e.jsx("span", { children: "← Swipe to navigate →" })
287
- ] }),
288
- O ? (
289
- /* Swimlane (2D) layout */
290
- /* @__PURE__ */ e.jsxs("div", { className: E("flex flex-col gap-1 p-2 sm:p-4 min-w-0 overflow-hidden", u), role: "region", "aria-label": "Kanban board with swimlanes", children: [
291
- /* @__PURE__ */ e.jsx("div", { className: "flex gap-3 sm:gap-4 pl-36 sm:pl-44 overflow-x-auto", children: x.map((t) => /* @__PURE__ */ e.jsxs("div", { className: "w-[85vw] sm:w-80 flex-shrink-0 text-center", children: [
292
- /* @__PURE__ */ e.jsx("span", { className: "font-mono text-xs sm:text-sm font-semibold tracking-wider text-primary/90 uppercase", children: t.title }),
293
- /* @__PURE__ */ e.jsxs("span", { className: "ml-2 font-mono text-xs text-muted-foreground", children: [
294
- "(",
295
- t.cards.length,
296
- ")"
297
- ] })
298
- ] }, t.id)) }),
299
- O.map((t) => {
300
- const o = M.has(t), a = x.reduce((l, h) => l + h.cards.filter((d) => (d[n] != null ? String(d[n]) : R) === t).length, 0);
301
- return /* @__PURE__ */ e.jsxs("div", { className: "border rounded-lg bg-muted/10", children: [
302
- /* @__PURE__ */ e.jsxs(
303
- "button",
304
- {
305
- className: "w-full flex items-center gap-2 px-3 py-2 text-left hover:bg-muted/30 transition-colors",
306
- onClick: () => q(t),
307
- "aria-expanded": !o,
308
- children: [
309
- /* @__PURE__ */ e.jsx("span", { className: E("transition-transform text-xs", o ? "" : "rotate-90"), children: "▶" }),
310
- /* @__PURE__ */ e.jsx("span", { className: "font-mono text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: t }),
311
- /* @__PURE__ */ e.jsxs("span", { className: "font-mono text-xs text-muted-foreground", children: [
312
- "(",
313
- a,
314
- ")"
315
- ] })
316
- ]
317
- }
318
- ),
319
- !o && /* @__PURE__ */ e.jsx("div", { className: "flex gap-3 sm:gap-4 overflow-x-auto px-2 pb-3 pl-36 sm:pl-44", children: x.map((l) => {
320
- const h = l.cards.filter(
321
- (d) => (d[n] != null ? String(d[n]) : R) === t
322
- );
323
- return /* @__PURE__ */ e.jsx("div", { className: "w-[85vw] sm:w-80 flex-shrink-0 min-h-[60px] rounded-md bg-card/20 p-2", children: /* @__PURE__ */ e.jsx(_, { items: h.map((d) => d.id), strategy: H, children: /* @__PURE__ */ e.jsx("div", { className: "space-y-2", role: "list", "aria-label": `${l.title} - ${t} cards`, children: h.map((d) => /* @__PURE__ */ e.jsx($, { card: d, onCardClick: i, conditionalFormatting: g }, d.id)) }) }) }, l.id);
324
- }) })
325
- ] }, t);
326
- })
327
- ] })
328
- ) : (
329
- /* Standard flat layout */
330
- /* @__PURE__ */ e.jsx("div", { className: E("flex gap-3 sm:gap-4 overflow-x-auto snap-x snap-mandatory p-2 sm:p-4 bg-muted/10 rounded-lg [-webkit-overflow-scrolling:touch] min-w-0", u), role: "region", "aria-label": "Kanban board", children: x.map((t) => /* @__PURE__ */ e.jsx(
331
- be,
332
- {
333
- column: t,
334
- cards: t.cards,
335
- onCardClick: i,
336
- quickAdd: m,
337
- onQuickAdd: f,
338
- conditionalFormatting: g
339
- },
340
- t.id
341
- )) })
342
- ),
343
- /* @__PURE__ */ e.jsx(te, { children: /* @__PURE__ */ e.jsx("div", { "aria-live": "assertive", "aria-label": b ? `Dragging ${b.title}` : void 0, children: b ? /* @__PURE__ */ e.jsx($, { card: b, conditionalFormatting: g }) : null }) })
344
- ]
345
- }
346
- );
347
- }
348
- export {
349
- we as default
350
- };