@object-ui/plugin-kanban 3.0.3 → 3.1.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.
Files changed (45) hide show
  1. package/.turbo/turbo-build.log +9 -9
  2. package/CHANGELOG.md +10 -0
  3. package/dist/{KanbanEnhanced-BPIKjTDv.js → KanbanEnhanced-CXDSLlGR.js} +338 -324
  4. package/dist/KanbanImpl-4dgoNPtI.js +350 -0
  5. package/dist/index-CyNcIIS1.js +1077 -0
  6. package/dist/index.js +9 -4
  7. package/dist/index.umd.cjs +4 -4
  8. package/dist/src/CardTemplates.d.ts +25 -0
  9. package/dist/src/CardTemplates.d.ts.map +1 -0
  10. package/dist/src/InlineQuickAdd.d.ts +29 -0
  11. package/dist/src/InlineQuickAdd.d.ts.map +1 -0
  12. package/dist/src/KanbanEnhanced.d.ts +12 -1
  13. package/dist/src/KanbanEnhanced.d.ts.map +1 -1
  14. package/dist/src/KanbanImpl.d.ts +15 -1
  15. package/dist/src/KanbanImpl.d.ts.map +1 -1
  16. package/dist/src/ObjectKanban.d.ts.map +1 -1
  17. package/dist/src/index.d.ts +22 -1
  18. package/dist/src/index.d.ts.map +1 -1
  19. package/dist/src/types.d.ts +97 -1
  20. package/dist/src/types.d.ts.map +1 -1
  21. package/dist/src/useColumnWidths.d.ts +30 -0
  22. package/dist/src/useColumnWidths.d.ts.map +1 -0
  23. package/dist/src/useCrossSwimlaneMove.d.ts +46 -0
  24. package/dist/src/useCrossSwimlaneMove.d.ts.map +1 -0
  25. package/dist/src/useQuickAddReorder.d.ts +28 -0
  26. package/dist/src/useQuickAddReorder.d.ts.map +1 -0
  27. package/package.json +9 -9
  28. package/src/CardTemplates.tsx +123 -0
  29. package/src/InlineQuickAdd.tsx +189 -0
  30. package/src/KanbanEnhanced.tsx +140 -9
  31. package/src/KanbanImpl.tsx +266 -23
  32. package/src/ObjectKanban.tsx +39 -24
  33. package/src/__tests__/KanbanGrouping.test.tsx +164 -0
  34. package/src/__tests__/KanbanSwimlanes.test.tsx +194 -0
  35. package/src/__tests__/ObjectKanbanTitle.test.tsx +93 -0
  36. package/src/__tests__/SwimlanePersistence.test.tsx +159 -0
  37. package/src/__tests__/performance-benchmark.test.tsx +14 -14
  38. package/src/__tests__/phase13-features.test.tsx +387 -0
  39. package/src/index.tsx +49 -6
  40. package/src/types.ts +106 -1
  41. package/src/useColumnWidths.ts +125 -0
  42. package/src/useCrossSwimlaneMove.ts +116 -0
  43. package/src/useQuickAddReorder.ts +107 -0
  44. package/dist/KanbanImpl-BfOKAnJS.js +0 -194
  45. package/dist/index-CWGTi2xn.js +0 -600
@@ -0,0 +1,1077 @@
1
+ import * as w from "react";
2
+ import M, { useState as T, useEffect as ae, useMemo as V, forwardRef as fe, createElement as G, useCallback as E, Suspense as me } from "react";
3
+ import { buildExpandFields as je, extractRecords as Ce, ComponentRegistry as B } from "@object-ui/core";
4
+ import { useDataScope as Ee, useNavigationOverlay as _e, useSchemaContext as we } from "@object-ui/react";
5
+ import { NavigationOverlay as Ne, Button as Q, Input as oe, Skeleton as pe } from "@object-ui/components";
6
+ var Y = { exports: {} }, D = {};
7
+ var se;
8
+ function Te() {
9
+ if (se) return D;
10
+ se = 1;
11
+ var e = /* @__PURE__ */ Symbol.for("react.transitional.element"), r = /* @__PURE__ */ Symbol.for("react.fragment");
12
+ function n(o, i, a) {
13
+ var l = null;
14
+ if (a !== void 0 && (l = "" + a), i.key !== void 0 && (l = "" + i.key), "key" in i) {
15
+ a = {};
16
+ for (var s in i)
17
+ s !== "key" && (a[s] = i[s]);
18
+ } else a = i;
19
+ return i = a.ref, {
20
+ $$typeof: e,
21
+ type: o,
22
+ key: l,
23
+ ref: i !== void 0 ? i : null,
24
+ props: a
25
+ };
26
+ }
27
+ return D.Fragment = r, D.jsx = n, D.jsxs = n, D;
28
+ }
29
+ var F = {};
30
+ var le;
31
+ function Re() {
32
+ return le || (le = 1, process.env.NODE_ENV !== "production" && (function() {
33
+ function e(t) {
34
+ if (t == null) return null;
35
+ if (typeof t == "function")
36
+ return t.$$typeof === he ? null : t.displayName || t.name || null;
37
+ if (typeof t == "string") return t;
38
+ switch (t) {
39
+ case _:
40
+ return "Fragment";
41
+ case L:
42
+ return "Profiler";
43
+ case S:
44
+ return "StrictMode";
45
+ case b:
46
+ return "Suspense";
47
+ case j:
48
+ return "SuspenseList";
49
+ case A:
50
+ return "Activity";
51
+ }
52
+ if (typeof t == "object")
53
+ switch (typeof t.tag == "number" && console.error(
54
+ "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
55
+ ), t.$$typeof) {
56
+ case R:
57
+ return "Portal";
58
+ case P:
59
+ return t.displayName || "Context";
60
+ case K:
61
+ return (t._context.displayName || "Context") + ".Consumer";
62
+ case q:
63
+ var f = t.render;
64
+ return t = t.displayName, t || (t = f.displayName || f.name || "", t = t !== "" ? "ForwardRef(" + t + ")" : "ForwardRef"), t;
65
+ case v:
66
+ return f = t.displayName || null, f !== null ? f : e(t.type) || "Memo";
67
+ case N:
68
+ f = t._payload, t = t._init;
69
+ try {
70
+ return e(t(f));
71
+ } catch {
72
+ }
73
+ }
74
+ return null;
75
+ }
76
+ function r(t) {
77
+ return "" + t;
78
+ }
79
+ function n(t) {
80
+ try {
81
+ r(t);
82
+ var f = !1;
83
+ } catch {
84
+ f = !0;
85
+ }
86
+ if (f) {
87
+ f = console;
88
+ var y = f.error, k = typeof Symbol == "function" && Symbol.toStringTag && t[Symbol.toStringTag] || t.constructor.name || "Object";
89
+ return y.call(
90
+ f,
91
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
92
+ k
93
+ ), r(t);
94
+ }
95
+ }
96
+ function o(t) {
97
+ if (t === _) return "<>";
98
+ if (typeof t == "object" && t !== null && t.$$typeof === N)
99
+ return "<...>";
100
+ try {
101
+ var f = e(t);
102
+ return f ? "<" + f + ">" : "<...>";
103
+ } catch {
104
+ return "<...>";
105
+ }
106
+ }
107
+ function i() {
108
+ var t = z.A;
109
+ return t === null ? null : t.getOwner();
110
+ }
111
+ function a() {
112
+ return Error("react-stack-top-frame");
113
+ }
114
+ function l(t) {
115
+ if (X.call(t, "key")) {
116
+ var f = Object.getOwnPropertyDescriptor(t, "key").get;
117
+ if (f && f.isReactWarning) return !1;
118
+ }
119
+ return t.key !== void 0;
120
+ }
121
+ function s(t, f) {
122
+ function y() {
123
+ Z || (Z = !0, console.error(
124
+ "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
125
+ f
126
+ ));
127
+ }
128
+ y.isReactWarning = !0, Object.defineProperty(t, "key", {
129
+ get: y,
130
+ configurable: !0
131
+ });
132
+ }
133
+ function d() {
134
+ var t = e(this.type);
135
+ return ee[t] || (ee[t] = !0, console.error(
136
+ "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
137
+ )), t = this.props.ref, t !== void 0 ? t : null;
138
+ }
139
+ function p(t, f, y, k, I, J) {
140
+ var x = y.ref;
141
+ return t = {
142
+ $$typeof: C,
143
+ type: t,
144
+ key: f,
145
+ props: y,
146
+ _owner: k
147
+ }, (x !== void 0 ? x : null) !== null ? Object.defineProperty(t, "ref", {
148
+ enumerable: !1,
149
+ get: d
150
+ }) : Object.defineProperty(t, "ref", { enumerable: !1, value: null }), t._store = {}, Object.defineProperty(t._store, "validated", {
151
+ configurable: !1,
152
+ enumerable: !1,
153
+ writable: !0,
154
+ value: 0
155
+ }), Object.defineProperty(t, "_debugInfo", {
156
+ configurable: !1,
157
+ enumerable: !1,
158
+ writable: !0,
159
+ value: null
160
+ }), Object.defineProperty(t, "_debugStack", {
161
+ configurable: !1,
162
+ enumerable: !1,
163
+ writable: !0,
164
+ value: I
165
+ }), Object.defineProperty(t, "_debugTask", {
166
+ configurable: !1,
167
+ enumerable: !1,
168
+ writable: !0,
169
+ value: J
170
+ }), Object.freeze && (Object.freeze(t.props), Object.freeze(t)), t;
171
+ }
172
+ function g(t, f, y, k, I, J) {
173
+ var x = f.children;
174
+ if (x !== void 0)
175
+ if (k)
176
+ if (ke(x)) {
177
+ for (k = 0; k < x.length; k++)
178
+ c(x[k]);
179
+ Object.freeze && Object.freeze(x);
180
+ } else
181
+ console.error(
182
+ "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
183
+ );
184
+ else c(x);
185
+ if (X.call(f, "key")) {
186
+ x = e(t);
187
+ var O = Object.keys(f).filter(function(xe) {
188
+ return xe !== "key";
189
+ });
190
+ k = 0 < O.length ? "{key: someKey, " + O.join(": ..., ") + ": ...}" : "{key: someKey}", ne[x + k] || (O = 0 < O.length ? "{" + O.join(": ..., ") + ": ...}" : "{}", console.error(
191
+ `A props object containing a "key" prop is being spread into JSX:
192
+ let props = %s;
193
+ <%s {...props} />
194
+ React keys must be passed directly to JSX without using spread:
195
+ let props = %s;
196
+ <%s key={someKey} {...props} />`,
197
+ k,
198
+ x,
199
+ O,
200
+ x
201
+ ), ne[x + k] = !0);
202
+ }
203
+ if (x = null, y !== void 0 && (n(y), x = "" + y), l(f) && (n(f.key), x = "" + f.key), "key" in f) {
204
+ y = {};
205
+ for (var W in f)
206
+ W !== "key" && (y[W] = f[W]);
207
+ } else y = f;
208
+ return x && s(
209
+ y,
210
+ typeof t == "function" ? t.displayName || t.name || "Unknown" : t
211
+ ), p(
212
+ t,
213
+ x,
214
+ y,
215
+ i(),
216
+ I,
217
+ J
218
+ );
219
+ }
220
+ function c(t) {
221
+ m(t) ? t._store && (t._store.validated = 1) : typeof t == "object" && t !== null && t.$$typeof === N && (t._payload.status === "fulfilled" ? m(t._payload.value) && t._payload.value._store && (t._payload.value._store.validated = 1) : t._store && (t._store.validated = 1));
222
+ }
223
+ function m(t) {
224
+ return typeof t == "object" && t !== null && t.$$typeof === C;
225
+ }
226
+ var h = M, C = /* @__PURE__ */ Symbol.for("react.transitional.element"), R = /* @__PURE__ */ Symbol.for("react.portal"), _ = /* @__PURE__ */ Symbol.for("react.fragment"), S = /* @__PURE__ */ Symbol.for("react.strict_mode"), L = /* @__PURE__ */ Symbol.for("react.profiler"), K = /* @__PURE__ */ Symbol.for("react.consumer"), P = /* @__PURE__ */ Symbol.for("react.context"), q = /* @__PURE__ */ Symbol.for("react.forward_ref"), b = /* @__PURE__ */ Symbol.for("react.suspense"), j = /* @__PURE__ */ Symbol.for("react.suspense_list"), v = /* @__PURE__ */ Symbol.for("react.memo"), N = /* @__PURE__ */ Symbol.for("react.lazy"), A = /* @__PURE__ */ Symbol.for("react.activity"), he = /* @__PURE__ */ Symbol.for("react.client.reference"), z = h.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, X = Object.prototype.hasOwnProperty, ke = Array.isArray, U = console.createTask ? console.createTask : function() {
227
+ return null;
228
+ };
229
+ h = {
230
+ react_stack_bottom_frame: function(t) {
231
+ return t();
232
+ }
233
+ };
234
+ var Z, ee = {}, te = h.react_stack_bottom_frame.bind(
235
+ h,
236
+ a
237
+ )(), re = U(o(a)), ne = {};
238
+ F.Fragment = _, F.jsx = function(t, f, y) {
239
+ var k = 1e4 > z.recentlyCreatedOwnerStacks++;
240
+ return g(
241
+ t,
242
+ f,
243
+ y,
244
+ !1,
245
+ k ? Error("react-stack-top-frame") : te,
246
+ k ? U(o(t)) : re
247
+ );
248
+ }, F.jsxs = function(t, f, y) {
249
+ var k = 1e4 > z.recentlyCreatedOwnerStacks++;
250
+ return g(
251
+ t,
252
+ f,
253
+ y,
254
+ !0,
255
+ k ? Error("react-stack-top-frame") : te,
256
+ k ? U(o(t)) : re
257
+ );
258
+ };
259
+ })()), F;
260
+ }
261
+ var ie;
262
+ function Ae() {
263
+ return ie || (ie = 1, process.env.NODE_ENV === "production" ? Y.exports = Te() : Y.exports = Re()), Y.exports;
264
+ }
265
+ var u = Ae();
266
+ const be = ({
267
+ schema: e,
268
+ dataSource: r,
269
+ className: n,
270
+ onRowClick: o,
271
+ onCardClick: i,
272
+ ...a
273
+ }) => {
274
+ const [l, s] = T([]), [d, p] = T(null), [g, c] = T(!1), [m, h] = T(null), C = Ee(e.bind);
275
+ ae(() => {
276
+ let b = !0;
277
+ return (async () => {
278
+ if (!(!r || !e.objectName))
279
+ try {
280
+ const v = await r.getObjectSchema(e.objectName);
281
+ b && p(v);
282
+ } catch (v) {
283
+ console.warn("Failed to fetch object def", v);
284
+ }
285
+ })(), () => {
286
+ b = !1;
287
+ };
288
+ }, [e.objectName, r]), ae(() => {
289
+ let b = !0;
290
+ const j = async () => {
291
+ if (!(!r || typeof r.find != "function" || !e.objectName)) {
292
+ b && c(!0);
293
+ try {
294
+ const v = je(d?.fields), N = await r.find(e.objectName, {
295
+ options: { $top: 100 },
296
+ $filter: e.filter,
297
+ ...v.length > 0 ? { $expand: v } : {}
298
+ }), A = Ce(N);
299
+ console.log(`[ObjectKanban] Extracted data (length: ${A.length})`), b && s(A);
300
+ } catch (v) {
301
+ console.error("[ObjectKanban] Fetch error:", v), b && h(v);
302
+ } finally {
303
+ b && c(!1);
304
+ }
305
+ }
306
+ };
307
+ return e.objectName && !C && !e.data && !a.data && j(), () => {
308
+ b = !1;
309
+ };
310
+ }, [e.objectName, r, C, e.data, e.filter, a.data, d]);
311
+ const R = a.data || C || e.data || l, _ = V(() => {
312
+ if (!Array.isArray(R)) return [];
313
+ let b = e.cardTitle || e.titleField;
314
+ if (!b && d) {
315
+ if (d.titleFormat) {
316
+ const v = /\{(.+?)\}/.exec(d.titleFormat);
317
+ v && (b = v[1]);
318
+ }
319
+ !b && d.NAME_FIELD_KEY && (b = d.NAME_FIELD_KEY);
320
+ }
321
+ const j = ["name", "title", "subject", "label", "display_name"];
322
+ return R.map((v) => {
323
+ let N = b ? v[b] : void 0;
324
+ if (!N) {
325
+ for (const A of j)
326
+ if (v[A]) {
327
+ N = v[A];
328
+ break;
329
+ }
330
+ }
331
+ return {
332
+ ...v,
333
+ // Ensure id exists
334
+ id: v.id || v._id,
335
+ // Map title
336
+ title: N || "Untitled"
337
+ };
338
+ });
339
+ }, [R, e, d]), S = V(() => {
340
+ if (e.columns && e.columns.length > 0)
341
+ if (typeof e.columns[0] == "string") {
342
+ if (!e.groupBy)
343
+ return e.columns.map((b) => ({
344
+ id: b,
345
+ title: b
346
+ }));
347
+ } else
348
+ return e.columns;
349
+ if (e.groupBy && d?.fields?.[e.groupBy]?.options)
350
+ return d.fields[e.groupBy].options.map((b) => ({
351
+ id: b.value,
352
+ title: b.label
353
+ }));
354
+ if (e.groupBy && _.length > 0) {
355
+ const b = new Set(_.map((j) => j[e.groupBy]));
356
+ return Array.from(b).map((j) => ({
357
+ id: String(j),
358
+ title: String(j)
359
+ }));
360
+ }
361
+ return [];
362
+ }, [e.columns, e.groupBy, _, d]), L = e.swimlaneField || e.grouping?.fields?.[0]?.field, K = {
363
+ ...e,
364
+ data: _,
365
+ columns: S,
366
+ className: n || e.className,
367
+ ...L ? { swimlaneField: L } : {}
368
+ }, P = _e({
369
+ navigation: e.navigation,
370
+ objectName: e.objectName,
371
+ onRowClick: o ?? i
372
+ });
373
+ if (m)
374
+ return /* @__PURE__ */ u.jsxs("div", { className: "p-4 border border-destructive/50 rounded bg-destructive/10 text-destructive", children: [
375
+ "Error loading kanban data: ",
376
+ m.message
377
+ ] });
378
+ const q = e.objectName ? `${e.objectName.charAt(0).toUpperCase() + e.objectName.slice(1).replace(/_/g, " ")} Detail` : "Card Details";
379
+ return /* @__PURE__ */ u.jsxs(u.Fragment, { children: [
380
+ /* @__PURE__ */ u.jsx(H, { schema: {
381
+ ...K,
382
+ onCardClick: (b) => {
383
+ P.handleClick(b), i?.(b);
384
+ }
385
+ } }),
386
+ P.isOverlay && /* @__PURE__ */ u.jsx(Ne, { ...P, title: q, children: (b) => /* @__PURE__ */ u.jsx("div", { className: "space-y-3", children: Object.entries(b).map(([j, v]) => /* @__PURE__ */ u.jsxs("div", { className: "flex flex-col", children: [
387
+ /* @__PURE__ */ u.jsx("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wide", children: j.replace(/_/g, " ") }),
388
+ /* @__PURE__ */ u.jsx("span", { className: "text-sm", children: String(v ?? "—") })
389
+ ] }, j)) }) })
390
+ ] });
391
+ };
392
+ const ge = (...e) => e.filter((r, n, o) => !!r && r.trim() !== "" && o.indexOf(r) === n).join(" ").trim();
393
+ const Se = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
394
+ const Oe = (e) => e.replace(
395
+ /^([A-Z])|[\s-_]+(\w)/g,
396
+ (r, n, o) => o ? o.toUpperCase() : n.toLowerCase()
397
+ );
398
+ const ce = (e) => {
399
+ const r = Oe(e);
400
+ return r.charAt(0).toUpperCase() + r.slice(1);
401
+ };
402
+ var Pe = {
403
+ xmlns: "http://www.w3.org/2000/svg",
404
+ width: 24,
405
+ height: 24,
406
+ viewBox: "0 0 24 24",
407
+ fill: "none",
408
+ stroke: "currentColor",
409
+ strokeWidth: 2,
410
+ strokeLinecap: "round",
411
+ strokeLinejoin: "round"
412
+ };
413
+ const De = (e) => {
414
+ for (const r in e)
415
+ if (r.startsWith("aria-") || r === "role" || r === "title")
416
+ return !0;
417
+ return !1;
418
+ };
419
+ const Fe = fe(
420
+ ({
421
+ color: e = "currentColor",
422
+ size: r = 24,
423
+ strokeWidth: n = 2,
424
+ absoluteStrokeWidth: o,
425
+ className: i = "",
426
+ children: a,
427
+ iconNode: l,
428
+ ...s
429
+ }, d) => G(
430
+ "svg",
431
+ {
432
+ ref: d,
433
+ ...Pe,
434
+ width: r,
435
+ height: r,
436
+ stroke: e,
437
+ strokeWidth: o ? Number(n) * 24 / Number(r) : n,
438
+ className: ge("lucide", i),
439
+ ...!a && !De(s) && { "aria-hidden": "true" },
440
+ ...s
441
+ },
442
+ [
443
+ ...l.map(([p, g]) => G(p, g)),
444
+ ...Array.isArray(a) ? a : [a]
445
+ ]
446
+ )
447
+ );
448
+ const $ = (e, r) => {
449
+ const n = fe(
450
+ ({ className: o, ...i }, a) => G(Fe, {
451
+ ref: a,
452
+ iconNode: r,
453
+ className: ge(
454
+ `lucide-${Se(ce(e))}`,
455
+ `lucide-${e}`,
456
+ o
457
+ ),
458
+ ...i
459
+ })
460
+ );
461
+ return n.displayName = ce(e), n;
462
+ };
463
+ const Me = [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]], $e = $("check", Me);
464
+ const Le = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]], Ie = $("chevron-down", Le);
465
+ const Ye = [
466
+ [
467
+ "path",
468
+ {
469
+ d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",
470
+ key: "1oefj6"
471
+ }
472
+ ],
473
+ ["path", { d: "M14 2v5a1 1 0 0 0 1 1h5", key: "wfsgrz" }],
474
+ ["path", { d: "M10 9H8", key: "b1mrlr" }],
475
+ ["path", { d: "M16 13H8", key: "t4e002" }],
476
+ ["path", { d: "M16 17H8", key: "z1uh3a" }]
477
+ ], Ve = $("file-text", Ye);
478
+ const Be = [
479
+ ["path", { d: "M5 12h14", key: "1ays0h" }],
480
+ ["path", { d: "M12 5v14", key: "s699le" }]
481
+ ], ue = $("plus", Be);
482
+ const Ke = [
483
+ ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
484
+ ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
485
+ ], qe = $("x", Ke), ze = (...e) => e.filter(Boolean).join(" "), rt = ({
486
+ columnId: e,
487
+ fields: r,
488
+ onSubmit: n,
489
+ onCancel: o,
490
+ defaultValues: i
491
+ }) => {
492
+ const [a, l] = w.useState(() => {
493
+ const c = {};
494
+ for (const m of r)
495
+ c[m.name] = i?.[m.name] ?? m.defaultValue ?? "";
496
+ return c;
497
+ }), s = w.useRef(null);
498
+ w.useEffect(() => {
499
+ const c = setTimeout(() => s.current?.focus(), 0);
500
+ return () => clearTimeout(c);
501
+ }, []);
502
+ const d = w.useCallback((c, m) => {
503
+ l((h) => ({ ...h, [c]: m }));
504
+ }, []), p = w.useCallback(() => {
505
+ Object.values(a).some(
506
+ (m) => typeof m == "string" ? m.trim().length > 0 : m != null
507
+ ) && n(e, a);
508
+ }, [e, a, n]), g = w.useCallback(
509
+ (c) => {
510
+ c.key === "Enter" ? (c.preventDefault(), p()) : c.key === "Escape" && (c.preventDefault(), o());
511
+ },
512
+ [p, o]
513
+ );
514
+ return /* @__PURE__ */ u.jsxs(
515
+ "div",
516
+ {
517
+ className: "mt-2 rounded-lg border border-primary/30 bg-card p-3 space-y-2 shadow-sm",
518
+ onKeyDown: g,
519
+ role: "form",
520
+ "aria-label": "Quick add card",
521
+ children: [
522
+ r.map((c, m) => /* @__PURE__ */ u.jsxs("div", { className: "space-y-1", children: [
523
+ /* @__PURE__ */ u.jsx(
524
+ "label",
525
+ {
526
+ htmlFor: `qa-${e}-${c.name}`,
527
+ className: "text-xs font-mono text-muted-foreground",
528
+ children: c.label ?? c.name
529
+ }
530
+ ),
531
+ Ue(c, a[c.name], d, m === 0 ? s : void 0, `qa-${e}-${c.name}`)
532
+ ] }, c.name)),
533
+ /* @__PURE__ */ u.jsxs("div", { className: "flex items-center gap-2 pt-1", children: [
534
+ /* @__PURE__ */ u.jsxs(
535
+ Q,
536
+ {
537
+ type: "button",
538
+ size: "sm",
539
+ className: "h-7 text-xs gap-1",
540
+ onClick: p,
541
+ children: [
542
+ /* @__PURE__ */ u.jsx($e, { className: "h-3 w-3" }),
543
+ "Save"
544
+ ]
545
+ }
546
+ ),
547
+ /* @__PURE__ */ u.jsxs(
548
+ Q,
549
+ {
550
+ type: "button",
551
+ variant: "ghost",
552
+ size: "sm",
553
+ className: "h-7 text-xs gap-1",
554
+ onClick: o,
555
+ children: [
556
+ /* @__PURE__ */ u.jsx(qe, { className: "h-3 w-3" }),
557
+ "Cancel"
558
+ ]
559
+ }
560
+ )
561
+ ] })
562
+ ]
563
+ }
564
+ );
565
+ };
566
+ function Ue(e, r, n, o, i) {
567
+ const a = "text-sm h-8";
568
+ switch (e.type) {
569
+ case "select":
570
+ return /* @__PURE__ */ u.jsxs(
571
+ "select",
572
+ {
573
+ ref: o,
574
+ id: i,
575
+ value: r ?? "",
576
+ onChange: (l) => n(e.name, l.target.value),
577
+ className: ze(
578
+ a,
579
+ "w-full rounded-md border border-input bg-background px-2 py-1 text-sm ring-offset-background",
580
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
581
+ ),
582
+ children: [
583
+ /* @__PURE__ */ u.jsx("option", { value: "", children: e.placeholder ?? `Select ${e.label ?? e.name}...` }),
584
+ (e.options ?? []).map((l) => /* @__PURE__ */ u.jsx("option", { value: l.value, children: l.label }, l.value))
585
+ ]
586
+ }
587
+ );
588
+ case "number":
589
+ return /* @__PURE__ */ u.jsx(
590
+ oe,
591
+ {
592
+ ref: o,
593
+ id: i,
594
+ type: "number",
595
+ value: r ?? "",
596
+ onChange: (l) => n(e.name, l.target.value === "" ? "" : Number(l.target.value)),
597
+ placeholder: e.placeholder ?? `Enter ${e.label ?? e.name}...`,
598
+ className: a
599
+ }
600
+ );
601
+ default:
602
+ return /* @__PURE__ */ u.jsx(
603
+ oe,
604
+ {
605
+ ref: o,
606
+ id: i,
607
+ type: "text",
608
+ value: r ?? "",
609
+ onChange: (l) => n(e.name, l.target.value),
610
+ placeholder: e.placeholder ?? `Enter ${e.label ?? e.name}...`,
611
+ className: a
612
+ }
613
+ );
614
+ }
615
+ }
616
+ const Je = (...e) => e.filter(Boolean).join(" "), nt = ({
617
+ templates: e,
618
+ onSelect: r,
619
+ columnId: n
620
+ }) => {
621
+ const [o, i] = w.useState(!1), a = w.useRef(null);
622
+ w.useEffect(() => {
623
+ if (!o) return;
624
+ const s = (d) => {
625
+ a.current && !a.current.contains(d.target) && i(!1);
626
+ };
627
+ return document.addEventListener("mousedown", s), () => document.removeEventListener("mousedown", s);
628
+ }, [o]);
629
+ const l = w.useCallback(
630
+ (s) => {
631
+ s.key === "Escape" && i(!1);
632
+ },
633
+ []
634
+ );
635
+ return /* @__PURE__ */ u.jsxs("div", { ref: a, className: "relative", onKeyDown: l, children: [
636
+ /* @__PURE__ */ u.jsxs(
637
+ Q,
638
+ {
639
+ variant: "ghost",
640
+ size: "sm",
641
+ className: "w-full mt-2 text-muted-foreground hover:text-foreground gap-1",
642
+ onClick: () => i((s) => !s),
643
+ "aria-haspopup": "listbox",
644
+ "aria-expanded": o,
645
+ "aria-label": `Add card to ${n}`,
646
+ children: [
647
+ /* @__PURE__ */ u.jsx(ue, { className: "h-4 w-4" }),
648
+ "Add Card",
649
+ /* @__PURE__ */ u.jsx(Ie, { className: Je("h-3 w-3 transition-transform", o ? "rotate-180" : "") })
650
+ ]
651
+ }
652
+ ),
653
+ o && /* @__PURE__ */ u.jsxs(
654
+ "div",
655
+ {
656
+ className: "absolute z-50 mt-1 w-full rounded-md border border-border bg-popover p-1 shadow-md",
657
+ role: "listbox",
658
+ "aria-label": "Card templates",
659
+ children: [
660
+ /* @__PURE__ */ u.jsxs(
661
+ "button",
662
+ {
663
+ type: "button",
664
+ className: "flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground transition-colors",
665
+ role: "option",
666
+ "aria-selected": !1,
667
+ onClick: () => {
668
+ r(null), i(!1);
669
+ },
670
+ children: [
671
+ /* @__PURE__ */ u.jsx(ue, { className: "h-4 w-4 text-muted-foreground" }),
672
+ /* @__PURE__ */ u.jsx("span", { className: "font-mono text-xs", children: "Custom" })
673
+ ]
674
+ }
675
+ ),
676
+ e.length > 0 && /* @__PURE__ */ u.jsx("div", { className: "my-1 h-px bg-border", role: "separator" }),
677
+ e.map((s) => /* @__PURE__ */ u.jsxs(
678
+ "button",
679
+ {
680
+ type: "button",
681
+ className: "flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground transition-colors",
682
+ role: "option",
683
+ "aria-selected": !1,
684
+ onClick: () => {
685
+ r(s), i(!1);
686
+ },
687
+ children: [
688
+ /* @__PURE__ */ u.jsx(Ve, { className: "h-4 w-4 text-muted-foreground" }),
689
+ /* @__PURE__ */ u.jsx("span", { className: "font-mono text-xs truncate", children: s.name })
690
+ ]
691
+ },
692
+ s.id
693
+ ))
694
+ ]
695
+ }
696
+ )
697
+ ] });
698
+ }, de = "objectui:kanban-column-widths";
699
+ function We(e) {
700
+ try {
701
+ const r = localStorage.getItem(e);
702
+ if (r) {
703
+ const n = JSON.parse(r);
704
+ if (n && typeof n == "object" && !Array.isArray(n))
705
+ return n;
706
+ }
707
+ } catch {
708
+ }
709
+ return {};
710
+ }
711
+ function Ge(e, r) {
712
+ try {
713
+ localStorage.setItem(e, JSON.stringify(r));
714
+ } catch {
715
+ }
716
+ }
717
+ function at({
718
+ columns: e,
719
+ defaultWidth: r = 320,
720
+ minWidth: n = 200,
721
+ maxWidth: o = 600,
722
+ storageKey: i
723
+ }) {
724
+ const a = i ? `${de}:${i}` : de, [l, s] = T(
725
+ () => We(a)
726
+ ), d = E(
727
+ (h) => Math.max(n, Math.min(o, h)),
728
+ [n, o]
729
+ ), p = E(
730
+ (h) => {
731
+ const C = l[h];
732
+ return C != null ? d(C) : r;
733
+ },
734
+ [l, r, d]
735
+ ), g = E(
736
+ (h, C) => {
737
+ const R = d(C);
738
+ s((_) => {
739
+ const S = { ..._, [h]: R };
740
+ return Ge(a, S), S;
741
+ });
742
+ },
743
+ [d, a]
744
+ ), c = E(() => {
745
+ s({});
746
+ try {
747
+ localStorage.removeItem(a);
748
+ } catch {
749
+ }
750
+ }, [a]), m = V(
751
+ () => ({
752
+ defaultWidth: r,
753
+ minWidth: n,
754
+ maxWidth: o,
755
+ overrides: { ...l }
756
+ }),
757
+ [r, n, o, l]
758
+ );
759
+ return { getColumnWidth: p, setColumnWidth: g, resetWidths: c, config: m };
760
+ }
761
+ function ot({
762
+ swimlanes: e,
763
+ onCardMove: r
764
+ }) {
765
+ const [n, o] = T(null), i = V(() => {
766
+ const g = /* @__PURE__ */ new Map();
767
+ for (const c of e)
768
+ g.set(c.id, c);
769
+ return g;
770
+ }, [e]), a = E(
771
+ (g, c) => {
772
+ if (g === c) return !0;
773
+ const m = i.get(c);
774
+ return m ? m.acceptFrom ? m.acceptFrom.includes(g) : !0 : !1;
775
+ },
776
+ [i]
777
+ ), l = E(
778
+ (g, c, m, h) => a(c, m) ? (r?.({ cardId: g, fromSwimlane: c, toSwimlane: m, columnId: h }), o(null), !0) : !1,
779
+ [a, r]
780
+ ), s = E((g) => {
781
+ o(g);
782
+ }, []), d = E(() => {
783
+ o(null);
784
+ }, []);
785
+ return {
786
+ handleCrossSwimlaneMove: l,
787
+ isDraggingAcrossSwimlanes: n !== null,
788
+ startCrossSwimlaneDrag: s,
789
+ endCrossSwimlaneDrag: d,
790
+ canMoveTo: a
791
+ };
792
+ }
793
+ function st({
794
+ cards: e,
795
+ onReorderComplete: r
796
+ }) {
797
+ const [n, o] = T(e), [i, a] = T(!1);
798
+ !Qe(n, e) && !i && o(e);
799
+ const l = E(() => {
800
+ o(e), a(!1);
801
+ }, [e]), s = E(
802
+ (g, c) => {
803
+ o((m) => {
804
+ if (g < 0 || c < 0 || g >= m.length || c >= m.length)
805
+ return m;
806
+ const h = [...m], [C] = h.splice(g, 1);
807
+ return h.splice(c, 0, C), h;
808
+ });
809
+ },
810
+ []
811
+ ), d = E(() => {
812
+ a(!0);
813
+ }, []), p = E(() => {
814
+ a(!1), o((g) => (r?.(g), g));
815
+ }, [r]);
816
+ return {
817
+ reorderedCards: n,
818
+ onReorder: s,
819
+ isDragging: i,
820
+ startDrag: d,
821
+ endDrag: p,
822
+ reset: l
823
+ };
824
+ }
825
+ function Qe(e, r) {
826
+ if (e.length !== r.length) return !1;
827
+ for (let n = 0; n < e.length; n++)
828
+ if (e[n].id !== r[n].id) return !1;
829
+ return !0;
830
+ }
831
+ const He = M.lazy(() => import("./KanbanImpl-4dgoNPtI.js")), ve = M.lazy(() => import("./KanbanEnhanced-CXDSLlGR.js")), H = ({ schema: e }) => {
832
+ const r = M.useMemo(() => {
833
+ const { columns: n = [], data: o, groupBy: i, coverImageField: a } = e, l = (s) => {
834
+ if (!a) return s;
835
+ const d = s[a];
836
+ if (!d) return s;
837
+ const p = typeof d == "string" ? d : d?.url;
838
+ return p ? { ...s, coverImage: p } : s;
839
+ };
840
+ if (o && i && Array.isArray(o)) {
841
+ const s = {};
842
+ n.forEach((p) => {
843
+ p.id && (s[String(p.id).toLowerCase()] = p.id), p.title && (s[String(p.title).toLowerCase()] = p.id);
844
+ });
845
+ const d = o.reduce((p, g) => {
846
+ const c = String(g[i] ?? ""), m = s[c.toLowerCase()] ?? c;
847
+ return p[m] || (p[m] = []), p[m].push(l(g)), p;
848
+ }, {});
849
+ return n.map((p) => ({
850
+ ...p,
851
+ cards: [
852
+ ...(p.cards || []).map(l),
853
+ // Preserve static cards
854
+ ...d[p.id] || []
855
+ // Add dynamic cards
856
+ ]
857
+ }));
858
+ }
859
+ return n.map((s) => ({
860
+ ...s,
861
+ cards: (s.cards || []).map(l)
862
+ }));
863
+ }, [e]);
864
+ return /* @__PURE__ */ u.jsx(me, { fallback: /* @__PURE__ */ u.jsx(pe, { className: "w-full h-[600px]" }), children: /* @__PURE__ */ u.jsx(
865
+ He,
866
+ {
867
+ columns: r,
868
+ onCardMove: e.onCardMove,
869
+ onCardClick: e.onCardClick,
870
+ className: e.className,
871
+ quickAdd: e.quickAdd,
872
+ onQuickAdd: e.onQuickAdd,
873
+ coverImageField: e.coverImageField,
874
+ conditionalFormatting: e.conditionalFormatting,
875
+ swimlaneField: e.swimlaneField
876
+ }
877
+ ) });
878
+ };
879
+ B.register(
880
+ "kanban-ui",
881
+ H,
882
+ {
883
+ namespace: "plugin-kanban",
884
+ label: "Kanban Board",
885
+ icon: "LayoutDashboard",
886
+ category: "plugin",
887
+ inputs: [
888
+ {
889
+ name: "columns",
890
+ type: "array",
891
+ label: "Columns",
892
+ description: "Array of { id, title, cards, limit, className }",
893
+ required: !0
894
+ },
895
+ {
896
+ name: "onCardMove",
897
+ type: "code",
898
+ label: "On Card Move",
899
+ description: "Callback when a card is moved",
900
+ advanced: !0
901
+ },
902
+ {
903
+ name: "className",
904
+ type: "string",
905
+ label: "CSS Class"
906
+ }
907
+ ],
908
+ defaultProps: {
909
+ columns: [
910
+ {
911
+ id: "todo",
912
+ title: "To Do",
913
+ cards: [
914
+ {
915
+ id: "card-1",
916
+ title: "Task 1",
917
+ description: "This is the first task",
918
+ badges: [
919
+ { label: "High Priority", variant: "destructive" },
920
+ { label: "Feature", variant: "default" }
921
+ ]
922
+ },
923
+ {
924
+ id: "card-2",
925
+ title: "Task 2",
926
+ description: "This is the second task",
927
+ badges: [
928
+ { label: "Bug", variant: "destructive" }
929
+ ]
930
+ }
931
+ ]
932
+ },
933
+ {
934
+ id: "in-progress",
935
+ title: "In Progress",
936
+ limit: 3,
937
+ cards: [
938
+ {
939
+ id: "card-3",
940
+ title: "Task 3",
941
+ description: "Currently working on this",
942
+ badges: [
943
+ { label: "In Progress", variant: "default" }
944
+ ]
945
+ }
946
+ ]
947
+ },
948
+ {
949
+ id: "done",
950
+ title: "Done",
951
+ cards: [
952
+ {
953
+ id: "card-4",
954
+ title: "Task 4",
955
+ description: "This task is completed",
956
+ badges: [
957
+ { label: "Completed", variant: "outline" }
958
+ ]
959
+ },
960
+ {
961
+ id: "card-5",
962
+ title: "Task 5",
963
+ description: "Another completed task",
964
+ badges: [
965
+ { label: "Completed", variant: "outline" }
966
+ ]
967
+ }
968
+ ]
969
+ }
970
+ ],
971
+ className: "w-full"
972
+ }
973
+ }
974
+ );
975
+ const lt = {
976
+ kanban: H,
977
+ "kanban-enhanced": ve,
978
+ "object-kanban": be
979
+ };
980
+ B.register(
981
+ "kanban-enhanced",
982
+ ({ schema: e }) => {
983
+ const r = M.useMemo(() => {
984
+ const { columns: n = [], data: o, groupBy: i } = e;
985
+ if (o && i && Array.isArray(o)) {
986
+ const a = o.reduce((l, s) => {
987
+ const d = s[i];
988
+ return l[d] || (l[d] = []), l[d].push(s), l;
989
+ }, {});
990
+ return n.map((l) => ({
991
+ ...l,
992
+ cards: [...l.cards || [], ...a[l.id] || []]
993
+ }));
994
+ }
995
+ return n;
996
+ }, [e]);
997
+ return /* @__PURE__ */ u.jsx(me, { fallback: /* @__PURE__ */ u.jsx(pe, { className: "w-full h-[600px]" }), children: /* @__PURE__ */ u.jsx(
998
+ ve,
999
+ {
1000
+ columns: r,
1001
+ onCardMove: e.onCardMove,
1002
+ onColumnToggle: e.onColumnToggle,
1003
+ enableVirtualScrolling: e.enableVirtualScrolling,
1004
+ virtualScrollThreshold: e.virtualScrollThreshold,
1005
+ className: e.className,
1006
+ quickAdd: e.quickAdd,
1007
+ onQuickAdd: e.onQuickAdd,
1008
+ conditionalFormatting: e.conditionalFormatting
1009
+ }
1010
+ ) });
1011
+ },
1012
+ {
1013
+ namespace: "plugin-kanban",
1014
+ label: "Kanban Board (Enhanced)",
1015
+ icon: "LayoutGrid",
1016
+ category: "plugin",
1017
+ inputs: [
1018
+ { name: "columns", type: "array", label: "Columns", required: !0 },
1019
+ { name: "enableVirtualScrolling", type: "boolean", label: "Virtual Scrolling", defaultValue: !1 },
1020
+ { name: "virtualScrollThreshold", type: "number", label: "Virtual Scroll Threshold", defaultValue: 50 },
1021
+ { name: "onCardMove", type: "code", label: "On Card Move", advanced: !0 },
1022
+ { name: "onColumnToggle", type: "code", label: "On Column Toggle", advanced: !0 },
1023
+ { name: "className", type: "string", label: "CSS Class" }
1024
+ ],
1025
+ defaultProps: {
1026
+ columns: [],
1027
+ enableVirtualScrolling: !1,
1028
+ virtualScrollThreshold: 50,
1029
+ className: "w-full"
1030
+ }
1031
+ }
1032
+ );
1033
+ const ye = ({ schema: e, ...r }) => {
1034
+ const { dataSource: n } = we() || {};
1035
+ return /* @__PURE__ */ u.jsx(be, { schema: e, dataSource: n, ...r });
1036
+ };
1037
+ B.register(
1038
+ "object-kanban",
1039
+ ye,
1040
+ {
1041
+ namespace: "plugin-kanban",
1042
+ label: "Object Kanban",
1043
+ category: "view",
1044
+ inputs: [
1045
+ { name: "objectName", type: "string", label: "Object Name", required: !0 },
1046
+ { name: "columns", type: "array", label: "Columns" }
1047
+ ]
1048
+ }
1049
+ );
1050
+ B.register(
1051
+ "kanban",
1052
+ ye,
1053
+ {
1054
+ namespace: "view",
1055
+ label: "Kanban Board",
1056
+ category: "view",
1057
+ inputs: [
1058
+ { name: "objectName", type: "string", label: "Object Name", required: !0 },
1059
+ { name: "columns", type: "array", label: "Columns" }
1060
+ ]
1061
+ }
1062
+ );
1063
+ export {
1064
+ Ie as C,
1065
+ rt as I,
1066
+ H as K,
1067
+ be as O,
1068
+ ue as P,
1069
+ nt as a,
1070
+ ye as b,
1071
+ $ as c,
1072
+ ot as d,
1073
+ st as e,
1074
+ u as j,
1075
+ lt as k,
1076
+ at as u
1077
+ };