@pihanga2/shadcn 0.2.22 → 0.2.25

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.
@@ -0,0 +1,570 @@
1
+ import "./swimlane.types.js";
2
+ import { describeSwimlaneTarget as e, formatTs as t, projectPending as n, relatedCallIds as r, rowTouches as i, stepKeyOf as a, stepRows as o } from "./swimlane.model.js";
3
+ import './swimlane.css';/* empty css */
4
+ import { memo as s, useEffect as c, useId as l, useLayoutEffect as u, useMemo as d, useRef as f, useState as p } from "react";
5
+ import m from "clsx";
6
+ import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
7
+ //#region src/cards/swimlane/swimlane.component.tsx
8
+ var v = (e, t) => e.gutter + t * e.laneW + e.laneW / 2;
9
+ function y(e, t, n, r, i, a, o, s = null, c = {}, l = {}) {
10
+ n.forEach((n, u) => {
11
+ let d = v(t, u);
12
+ [[
13
+ r,
14
+ 0,
15
+ t.mid
16
+ ], [
17
+ i,
18
+ t.mid,
19
+ t.rowH
20
+ ]].forEach(([t, o, u], f) => {
21
+ let p = t[n];
22
+ p && (e.visuals.push(/* @__PURE__ */ g("line", {
23
+ className: `swl-ll swl-ll-${p.state}`,
24
+ x1: d,
25
+ x2: d,
26
+ y1: o,
27
+ y2: u
28
+ }, `ll-${n}-${f}`)), p.acts.forEach((t, p) => {
29
+ let h = d - 5 + p * 5, v = f === 1 && !r[n]?.acts.includes(t), y = f === 0 && !i[n]?.acts.includes(t), b = `M${h},${o} V${u} M${h + 10},${o} V${u}` + (v ? ` M${h},${o} H${h + 10}` : "") + (y ? ` M${h},${u} H${h + 10}` : ""), x = l[n];
30
+ e.visuals.push(/* @__PURE__ */ _("g", {
31
+ className: m("swl-act", c[n], a === t ? "swl-hl" : s === t && "swl-hl-proc"),
32
+ children: [/* @__PURE__ */ g("rect", {
33
+ x: h,
34
+ y: o,
35
+ width: 10,
36
+ height: u - o,
37
+ style: x
38
+ }), /* @__PURE__ */ g("path", {
39
+ d: b,
40
+ style: x
41
+ })]
42
+ }, `a-${t}-${f}`)), e.hits.push(/* @__PURE__ */ g("rect", {
43
+ className: "swl-hit",
44
+ x: h - 8,
45
+ y: o,
46
+ width: 26,
47
+ height: u - o,
48
+ "data-kind": "activity",
49
+ "data-id": t,
50
+ "data-lane": n
51
+ }, `ha-${t}-${f}`));
52
+ }));
53
+ }), !r[n] && i[n] && e.visuals.push(/* @__PURE__ */ g("rect", {
54
+ className: "swl-lane-head",
55
+ x: d - 16,
56
+ y: t.mid - 5,
57
+ width: 32,
58
+ height: 10,
59
+ rx: 2
60
+ }, `h-${n}`), /* @__PURE__ */ _("text", {
61
+ className: "swl-lbl-muted",
62
+ x: d + 20,
63
+ y: t.mid + 3,
64
+ children: [
65
+ "+ ",
66
+ o[n] ?? n,
67
+ " joined"
68
+ ]
69
+ }, `ht-${n}`));
70
+ });
71
+ }
72
+ function b(e, t, n, r) {
73
+ let i = n(r.from), a = n(r.to);
74
+ if (i < 0 || a < 0) return;
75
+ let o = v(t, i), s = v(t, a), c = m("swl-ar", r.cls, r.hl ? "swl-hl" : r.rel && "swl-hl-rel"), l = `url(#${t.mk}-${r.marker})`, u = {
76
+ "data-kind": r.kind,
77
+ "data-id": r.hitId,
78
+ "data-row": r.rowId
79
+ };
80
+ if (r.from === r.to) {
81
+ let n = `M${o + 6},${t.mid - 9} h26 v16 h-20`;
82
+ e.visuals.push(/* @__PURE__ */ g("path", {
83
+ className: c,
84
+ d: n,
85
+ markerEnd: l
86
+ }, "ar"), /* @__PURE__ */ g("text", {
87
+ className: "swl-lbl",
88
+ x: o + 38,
89
+ y: t.mid + 3,
90
+ children: r.label
91
+ }, "lb")), e.hits.push(/* @__PURE__ */ g("path", {
92
+ className: "swl-hit",
93
+ d: n,
94
+ strokeWidth: 14,
95
+ pointerEvents: "stroke",
96
+ ...u
97
+ }, "hit"));
98
+ return;
99
+ }
100
+ let d = Math.sign(s - o), f = o + d * 6, p = s - d * 6;
101
+ e.visuals.push(/* @__PURE__ */ g("line", {
102
+ className: c,
103
+ x1: f,
104
+ x2: p,
105
+ y1: t.mid,
106
+ y2: t.mid,
107
+ markerEnd: l
108
+ }, "ar"), /* @__PURE__ */ g("text", {
109
+ className: "swl-lbl",
110
+ x: Math.min(f, p) + 8,
111
+ y: t.mid - 5,
112
+ children: r.label
113
+ }, "lb")), e.hits.push(/* @__PURE__ */ g("line", {
114
+ className: "swl-hit",
115
+ x1: f,
116
+ x2: p,
117
+ y1: t.mid,
118
+ y2: t.mid,
119
+ strokeWidth: 16,
120
+ pointerEvents: "stroke",
121
+ ...u
122
+ }, "hit"));
123
+ }
124
+ var x = {
125
+ sync: ["swl-ar-sync", "sync"],
126
+ async: ["swl-ar-async", "async"],
127
+ event: ["swl-ar-event", "event"]
128
+ }, S = s(function({ row: e, g: t, laneOrder: n, laneLabels: r, laneActivityClassName: i, laneActivityStyle: o, width: s, hl: c, rel: l, proc: u, fmtTs: d, grouped: f, stepHl: p }) {
129
+ let h = {
130
+ visuals: [],
131
+ hits: []
132
+ }, S = (e) => n.indexOf(e);
133
+ y(h, t, n, e.pre, e.post, c, r, u, i, o);
134
+ let C = e.event;
135
+ switch (C.type) {
136
+ case "call": {
137
+ let [n, r] = x[C.kind];
138
+ b(h, t, S, {
139
+ from: C.from,
140
+ to: C.to,
141
+ cls: n,
142
+ marker: r,
143
+ label: C.label,
144
+ hitId: C.id,
145
+ kind: "transition",
146
+ rowId: e.id,
147
+ hl: c === C.id,
148
+ rel: l
149
+ });
150
+ break;
151
+ }
152
+ case "reply":
153
+ e.route && b(h, t, S, {
154
+ from: e.route.to,
155
+ to: e.route.from,
156
+ cls: C.ok ? "swl-ar-reply" : "swl-ar-error",
157
+ marker: C.ok ? "reply" : "error",
158
+ label: C.label,
159
+ hitId: C.id,
160
+ kind: "transition",
161
+ rowId: e.id,
162
+ hl: c === C.id,
163
+ rel: l
164
+ });
165
+ break;
166
+ case "done":
167
+ e.route && h.visuals.push(/* @__PURE__ */ _("text", {
168
+ className: "swl-lbl-muted",
169
+ x: v(t, S(e.route.to)) + 14,
170
+ y: t.mid + 3,
171
+ children: ["✓ processed ", e.route.label]
172
+ }, "dn"));
173
+ break;
174
+ case "state": {
175
+ let n = v(t, S(C.lane));
176
+ h.visuals.push(/* @__PURE__ */ g("circle", {
177
+ cx: n,
178
+ cy: t.mid,
179
+ r: 5,
180
+ className: `swl-dot-${C.state}`
181
+ }, "st")), (C.showLabel ?? !0) && h.visuals.push(/* @__PURE__ */ _("text", {
182
+ className: "swl-lbl-muted",
183
+ x: n + 10,
184
+ y: t.mid + 3,
185
+ children: ["→ ", C.state]
186
+ }, "stl")), h.hits.push(/* @__PURE__ */ g("circle", {
187
+ className: "swl-hit",
188
+ cx: n,
189
+ cy: t.mid,
190
+ r: 12,
191
+ "data-kind": "state",
192
+ "data-id": `state-${e.id}`,
193
+ "data-lane": C.lane,
194
+ "data-row": e.id
195
+ }, "sth"));
196
+ break;
197
+ }
198
+ }
199
+ return /* @__PURE__ */ _("svg", {
200
+ className: m("swl-row", e.fulfilled && "swl-arrived", f && "swl-grouped", p && "swl-hl-step"),
201
+ width: s,
202
+ height: t.rowH,
203
+ "data-row": e.id,
204
+ children: [
205
+ f ? /* @__PURE__ */ g("line", {
206
+ className: "swl-ts-tie",
207
+ x1: 6,
208
+ x2: 6,
209
+ y1: 0,
210
+ y2: t.rowH
211
+ }) : /* @__PURE__ */ g("text", {
212
+ className: "swl-ts",
213
+ x: 0,
214
+ y: t.mid + 3,
215
+ children: d(C.ts)
216
+ }),
217
+ e.fulfilled && (() => {
218
+ let e = C.type === "reply" && C.ok === !1;
219
+ return /* @__PURE__ */ _("text", {
220
+ className: m("swl-ok", e && "swl-ok-error"),
221
+ x: t.gutter - 16,
222
+ y: t.mid + 4,
223
+ children: [/* @__PURE__ */ g("title", { children: e ? "replaced an outstanding message (error)" : "replaced an outstanding message" }), e ? "✗" : "✓"]
224
+ });
225
+ })(),
226
+ h.visuals,
227
+ /* @__PURE__ */ g("rect", {
228
+ className: "swl-hit",
229
+ x: 0,
230
+ y: 0,
231
+ width: t.gutter - 2,
232
+ height: t.rowH,
233
+ "data-kind": "step",
234
+ "data-id": a(e),
235
+ "data-row": e.id
236
+ }),
237
+ h.hits
238
+ ]
239
+ });
240
+ }), C = (e) => `${(e / 1e3).toFixed(1)}s`, w = s(function({ row: e, g: t, laneOrder: n, laneLabels: r, laneActivityClassName: i, laneActivityStyle: a, width: o, hl: s, rel: c, proc: l, now: u, formatWait: d = C }) {
241
+ let f = {
242
+ visuals: [],
243
+ hits: []
244
+ }, p = e.pending, h = u - p.since, g = p.timeoutMs != null && h > p.timeoutMs;
245
+ return y(f, t, n, e.pre, e.post, s, r, l, i, a), b(f, t, (e) => n.indexOf(e), {
246
+ from: p.from,
247
+ to: p.to,
248
+ cls: m("swl-ar-ghost", g && "swl-overdue"),
249
+ marker: "ghost",
250
+ label: `⌛ ${p.label}`,
251
+ hitId: p.id,
252
+ kind: "pending",
253
+ hl: s === p.id,
254
+ rel: c
255
+ }), /* @__PURE__ */ _("svg", {
256
+ className: "swl-row swl-ghost",
257
+ width: o,
258
+ height: t.rowH,
259
+ children: [
260
+ /* @__PURE__ */ _("text", {
261
+ className: m("swl-ts", g && "swl-overdue"),
262
+ x: 0,
263
+ y: t.mid + 3,
264
+ children: ["waiting ", d(h)]
265
+ }),
266
+ f.visuals,
267
+ f.hits
268
+ ]
269
+ });
270
+ }), T = s(function({ snap: e, count: t, g: n, laneOrder: r, laneLabels: i, laneActivityClassName: a, laneActivityStyle: o, width: s, proc: c }) {
271
+ let l = {
272
+ visuals: [],
273
+ hits: []
274
+ };
275
+ return y(l, n, r, e, e, null, i, c, a, o), /* @__PURE__ */ _("svg", {
276
+ className: "swl-row swl-now",
277
+ width: s,
278
+ height: n.rowH,
279
+ children: [
280
+ /* @__PURE__ */ g("text", {
281
+ className: "swl-now-lbl",
282
+ x: 0,
283
+ y: n.mid + 3,
284
+ children: "now"
285
+ }),
286
+ l.visuals,
287
+ /* @__PURE__ */ g("line", {
288
+ className: "swl-now-line",
289
+ x1: n.gutter - 6,
290
+ x2: s - 10,
291
+ y1: n.mid,
292
+ y2: n.mid
293
+ }),
294
+ /* @__PURE__ */ _("text", {
295
+ className: "swl-now-lbl",
296
+ x: s - 136,
297
+ y: n.mid - 4,
298
+ children: [
299
+ "▼ ",
300
+ t,
301
+ " outstanding"
302
+ ]
303
+ })
304
+ ]
305
+ });
306
+ });
307
+ function ee(e) {
308
+ let { model: t, hid: r, related: a, procId: o, clock: s, formatWait: l, ...u } = e, [f, m] = p(() => Date.now()), v = s ?? f, y = t.pending.length > 0;
309
+ c(() => {
310
+ if (!y || s != null) return;
311
+ let e = setInterval(() => m(Date.now()), 250);
312
+ return () => clearInterval(e);
313
+ }, [y, s]);
314
+ let { current: b, pending: x } = t, S = d(() => n(b, x), [b, x]);
315
+ return /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g(T, {
316
+ snap: t.current,
317
+ count: t.pending.length,
318
+ proc: o && i({
319
+ pre: t.current,
320
+ post: t.current
321
+ }, void 0, o) ? o : null,
322
+ ...u
323
+ }), S.map((e) => /* @__PURE__ */ g(w, {
324
+ row: e,
325
+ now: v,
326
+ hl: r && i(e, e.pending.id, r) ? r : null,
327
+ rel: a.has(e.pending.id),
328
+ proc: o && i(e, void 0, o) ? o : null,
329
+ formatWait: l,
330
+ ...u
331
+ }, e.id))] });
332
+ }
333
+ function te({ model: e, g: t, headH: n, width: r }) {
334
+ return /* @__PURE__ */ g("svg", {
335
+ width: r,
336
+ height: n,
337
+ children: e.laneOrder.map((r, i) => {
338
+ let a = v(t, i), o = e.current[r], s = n - 24;
339
+ return /* @__PURE__ */ _("g", { children: [
340
+ /* @__PURE__ */ g("text", {
341
+ className: "swl-lane-name",
342
+ x: a + 4,
343
+ y: s,
344
+ transform: `rotate(-90 ${a + 4} ${s})`,
345
+ children: e.laneLabels[r] ?? r
346
+ }),
347
+ /* @__PURE__ */ g("circle", {
348
+ cx: a,
349
+ cy: n - 12,
350
+ r: 5,
351
+ className: `swl-dot-${o?.state}`,
352
+ children: /* @__PURE__ */ g("title", { children: o?.state })
353
+ }),
354
+ o && o.acts.length > 0 && /* @__PURE__ */ g("text", {
355
+ className: "swl-lbl-muted",
356
+ x: a + 9,
357
+ y: n - 8,
358
+ children: o.acts.length
359
+ }),
360
+ /* @__PURE__ */ g("rect", {
361
+ className: "swl-hit",
362
+ x: a - t.laneW / 2,
363
+ y: 0,
364
+ width: t.laneW,
365
+ height: n,
366
+ "data-kind": "lane",
367
+ "data-id": r,
368
+ "data-lane": r
369
+ })
370
+ ] }, r);
371
+ })
372
+ });
373
+ }
374
+ function ne({ mk: e }) {
375
+ let t = (t, n, r) => /* @__PURE__ */ g("marker", {
376
+ id: `${e}-${t}`,
377
+ viewBox: "0 0 10 10",
378
+ refX: 9,
379
+ refY: 5,
380
+ markerWidth: 9,
381
+ markerHeight: 9,
382
+ markerUnits: "userSpaceOnUse",
383
+ orient: "auto-start-reverse",
384
+ children: r ? /* @__PURE__ */ g("path", {
385
+ d: "M1,1 L9,5 L1,9",
386
+ className: n
387
+ }) : /* @__PURE__ */ g("path", {
388
+ d: "M0,0 L10,5 L0,10 z",
389
+ className: n
390
+ })
391
+ });
392
+ return /* @__PURE__ */ g("svg", {
393
+ width: 0,
394
+ height: 0,
395
+ style: { position: "absolute" },
396
+ "aria-hidden": "true",
397
+ children: /* @__PURE__ */ _("defs", { children: [
398
+ t("sync", "swl-mk-sync", !1),
399
+ t("async", "swl-mk-async", !0),
400
+ t("event", "swl-mk-event", !0),
401
+ t("reply", "swl-mk-reply", !0),
402
+ t("error", "swl-mk-error", !1),
403
+ t("ghost", "swl-mk-ghost", !0)
404
+ ] })
405
+ });
406
+ }
407
+ function E(e, t) {
408
+ return t.kind !== "transition" && t.kind !== "pending" ? null : e.spans[t.id]?.parent ?? null;
409
+ }
410
+ function D(e) {
411
+ for (let t = e?.parentElement; t; t = t.parentElement) {
412
+ let e = getComputedStyle(t).overflowY;
413
+ if (e === "auto" || e === "scroll") return t;
414
+ }
415
+ return null;
416
+ }
417
+ var O = (n) => {
418
+ let { cardName: s, model: h, showPending: v = !0, autoFollow: y = !0, showTooltip: b = !0, highlightId: x, laneWidth: C = 104, rowHeight: w = 30, headerHeight: T = 130, gutterWidth: O = 92, stickyTop: re = 0, now: k, formatTs: A = t, formatWait: ie, className: j, style: M, onHoverChanged: N, onItemClicked: ae } = n, P = "swl" + l().replace(/[^a-zA-Z0-9_-]/g, ""), F = d(() => ({
419
+ laneW: C,
420
+ rowH: w,
421
+ gutter: O,
422
+ mid: w / 2,
423
+ mk: P
424
+ }), [
425
+ C,
426
+ w,
427
+ O,
428
+ P
429
+ ]), I = O + h.laneOrder.length * C + 140, L = {
430
+ g: F,
431
+ laneOrder: h.laneOrder,
432
+ laneLabels: h.laneLabels,
433
+ laneActivityClassName: h.laneActivityClassName,
434
+ laneActivityStyle: h.laneActivityStyle,
435
+ width: I,
436
+ fmtTs: A
437
+ }, R = f(null), z = f(null), B = f(h);
438
+ B.current = h;
439
+ let [V, oe] = p(null), H = f(null), U = (e) => {
440
+ let t = e?.closest?.(".swl-hit");
441
+ if (!t) return null;
442
+ let n = t.dataset;
443
+ return {
444
+ kind: n.kind,
445
+ id: n.id,
446
+ lane: n.lane,
447
+ rowId: n.row
448
+ };
449
+ }, W = (e, t) => e === t || !!e && !!t && e.kind === t.kind && e.id === t.id, G = (e) => {
450
+ let t = B.current;
451
+ if (e.kind === "step") return { steps: o(t, e.id) };
452
+ if (e.kind === "lane") return { meta: t.laneMeta[e.id] };
453
+ if (e.kind === "state") {
454
+ let n = t.rows.find((t) => String(t.id) === e.rowId);
455
+ return {
456
+ related: void 0,
457
+ process: void 0,
458
+ meta: n && n.event.type === "state" ? n.event.meta : void 0
459
+ };
460
+ }
461
+ let n = r(t, e.id), i = E(t, e) ?? void 0, a = e.kind === "pending" ? t.pending.find((t) => t.id === e.id) : void 0, s = a ? a.meta : t.spans[e.id]?.meta;
462
+ return e.kind === "pending" ? {
463
+ pending: a,
464
+ span: t.spans[e.id],
465
+ related: n,
466
+ process: i,
467
+ meta: s
468
+ } : {
469
+ span: t.spans[e.id],
470
+ related: n,
471
+ process: i,
472
+ meta: s
473
+ };
474
+ }, K = (e, t) => {
475
+ let n = z.current;
476
+ n && (n.style.left = `${e + 14}px`, n.style.top = `${t + 14}px`);
477
+ }, q = (t, n) => {
478
+ let r = H.current;
479
+ if (W(r, t)) return;
480
+ H.current = t, oe(t);
481
+ let i = z.current;
482
+ i && (t && b ? (i.textContent = e(B.current, t, k ?? Date.now(), A), i.style.display = "block", K(n.clientX, n.clientY)) : i.style.display = "none"), N({
483
+ target: t,
484
+ previous: r,
485
+ ...t ? G(t) : {},
486
+ clientX: n.clientX,
487
+ clientY: n.clientY
488
+ });
489
+ }, se = (e) => {
490
+ let t = U(e.target);
491
+ t && q(t, e);
492
+ }, ce = (e) => {
493
+ let t = U(e.relatedTarget);
494
+ (!t || !W(t, H.current)) && q(t, e);
495
+ }, le = (e) => {
496
+ H.current && b && K(e.clientX, e.clientY);
497
+ }, ue = (e) => {
498
+ let t = U(e.target);
499
+ t && ae({
500
+ target: t,
501
+ ...G(t)
502
+ });
503
+ }, J = V && V.kind !== "state" && V.kind !== "step" && V.kind !== "lane" ? V.id : x ?? null, { spans: Y } = h, X = d(() => new Set(J ? r({ spans: Y }, J) : []), [J, Y]), Z = V ? E(h, V) : null, Q = V?.kind === "step" ? V.id : null, $ = f(!0);
504
+ return c(() => {
505
+ if (!y) return;
506
+ let e = D(R.current), t = e ?? window, n = () => {
507
+ $.current = e ? e.scrollTop + e.clientHeight >= e.scrollHeight - 40 : window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 40;
508
+ };
509
+ return t.addEventListener("scroll", n, { passive: !0 }), () => t.removeEventListener("scroll", n);
510
+ }, [y]), u(() => {
511
+ if (!y || !$.current) return;
512
+ let e = D(R.current);
513
+ e ? e.scrollTop = e.scrollHeight : window.scrollTo(0, document.documentElement.scrollHeight);
514
+ }, [
515
+ y,
516
+ h.rows.length,
517
+ h.pending.length
518
+ ]), /* @__PURE__ */ _("div", {
519
+ ref: R,
520
+ className: m("pihanga-swimlane", j),
521
+ style: M,
522
+ "data-pihanga": s,
523
+ onPointerOver: se,
524
+ onPointerOut: ce,
525
+ onPointerMove: le,
526
+ onClick: ue,
527
+ children: [
528
+ /* @__PURE__ */ g(ne, { mk: P }),
529
+ /* @__PURE__ */ g("div", {
530
+ className: "swl-header",
531
+ style: { top: re },
532
+ children: /* @__PURE__ */ g(te, {
533
+ model: h,
534
+ g: F,
535
+ headH: T,
536
+ width: I
537
+ })
538
+ }),
539
+ /* @__PURE__ */ _("div", {
540
+ className: "swl-rows",
541
+ children: [h.rows.map((e, t) => /* @__PURE__ */ g(S, {
542
+ row: e,
543
+ hl: J && i(e, "id" in e.event ? e.event.id : void 0, J) ? J : null,
544
+ rel: "id" in e.event && e.event.type !== "done" && X.has(e.event.id),
545
+ proc: Z && i(e, void 0, Z) ? Z : null,
546
+ grouped: e.event.step != null && e.event.step === h.rows[t - 1]?.event.step,
547
+ stepHl: Q != null && a(e) === Q,
548
+ ...L
549
+ }, e.id)), v && /* @__PURE__ */ g(ee, {
550
+ model: h,
551
+ hid: J,
552
+ related: X,
553
+ procId: Z,
554
+ clock: k,
555
+ formatWait: ie,
556
+ ...L
557
+ })]
558
+ }),
559
+ /* @__PURE__ */ g("div", {
560
+ ref: z,
561
+ className: "swl-tooltip",
562
+ role: "tooltip"
563
+ })
564
+ ]
565
+ });
566
+ };
567
+ //#endregion
568
+ export { O as SwimlaneComponent };
569
+
570
+ //# sourceMappingURL=swimlane.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swimlane.component.js","names":[],"sources":["../../../src/cards/swimlane/swimlane.component.tsx"],"sourcesContent":["import React, {memo, useEffect, useId, useLayoutEffect, useMemo, useRef, useState} from \"react\";\nimport type {PiCardProps} from \"@pihanga2/core\";\nimport clsx from \"clsx\";\n\nimport {\n DEF_GUTTER_WIDTH,\n DEF_HEADER_HEIGHT,\n DEF_LANE_WIDTH,\n DEF_ROW_HEIGHT,\n type SwimlaneEvents,\n type SwimlaneGhostRow,\n type SwimlaneLanesSnapshot,\n type SwimlaneModel,\n type SwimlaneProps,\n type SwimlaneRow,\n type SwimlaneRowId,\n type SwimlaneTarget,\n type SwimlaneTargetKind,\n} from \"./swimlane.types\";\nimport {\n describeSwimlaneTarget,\n formatTs,\n projectPending,\n relatedCallIds,\n rowTouches,\n stepKeyOf,\n stepRows,\n} from \"./swimlane.model\";\n\nimport \"./swimlane.css\";\n\n/**\n * Real-time swimlane (sequence) diagram.\n *\n * Every transition is its own small, fixed-height SVG in normal document flow,\n * so the page (or nearest scroll container) scrolls — the SVGs never do.\n * Each row draws its top half from the `pre` lane snapshot and its bottom half\n * from `post`, which lets lifelines start, activities open/close and run\n * states change in the middle of a row.\n *\n * Hover/click use one delegated listener on the rows container; hit zones are\n * wide transparent shapes carrying `data-*` attributes.\n */\n\ntype Geo = {laneW: number; rowH: number; gutter: number; mid: number; mk: string};\n\nconst laneX = (g: Geo, i: number) => g.gutter + i * g.laneW + g.laneW / 2;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Drawing helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype Parts = {visuals: React.ReactNode[]; hits: React.ReactNode[]};\n\nfunction drawLanes(\n p: Parts,\n g: Geo,\n laneOrder: string[],\n pre: SwimlaneLanesSnapshot,\n post: SwimlaneLanesSnapshot,\n hl: string | null,\n laneLabels: Record<string, string>,\n /** Activity of the process that sends/receives the hovered transition. */\n proc: string | null = null,\n /** Per-lane extra class for the activity bar (`SwimlaneLaneEvent.activityClassName`). */\n laneActivityClassName: Record<string, string> = {},\n /** Per-lane inline style for the activity bar (`SwimlaneLaneEvent.activityStyle`). */\n laneActivityStyle: Record<string, React.CSSProperties> = {},\n) {\n laneOrder.forEach((l, i) => {\n const x = laneX(g, i);\n const halves: [SwimlaneLanesSnapshot, number, number][] = [\n [pre, 0, g.mid],\n [post, g.mid, g.rowH],\n ];\n halves.forEach(([snap, y1, y2], half) => {\n const s = snap[l];\n if (!s) return;\n p.visuals.push(\n <line key={`ll-${l}-${half}`} className={`swl-ll swl-ll-${s.state}`} x1={x} x2={x} y1={y1} y2={y2} />,\n );\n s.acts.forEach((a, k) => {\n const ax = x - 5 + k * 5;\n // fill + side borders only, so stacked half-row segments read as one\n // bar; caps only where the activity starts / ends inside this row\n const starts = half === 1 && !pre[l]?.acts.includes(a);\n const ends = half === 0 && !post[l]?.acts.includes(a);\n const d =\n `M${ax},${y1} V${y2} M${ax + 10},${y1} V${y2}` +\n (starts ? ` M${ax},${y1} H${ax + 10}` : \"\") +\n (ends ? ` M${ax},${y2} H${ax + 10}` : \"\");\n // `activityStyle` is applied to both the rect (normally filled, not\n // stroked) and the path (normally stroked, not filled) — set `fill`\n // for the bar's background and `stroke` for its border; the same\n // object on both elements is harmless since each only renders with\n // the properties it has a value for.\n const actStyle = laneActivityStyle[l];\n p.visuals.push(\n <g\n key={`a-${a}-${half}`}\n className={clsx(\n \"swl-act\",\n laneActivityClassName[l],\n hl === a ? \"swl-hl\" : proc === a && \"swl-hl-proc\",\n )}\n >\n <rect x={ax} y={y1} width={10} height={y2 - y1} style={actStyle} />\n <path d={d} style={actStyle} />\n </g>,\n );\n p.hits.push(\n <rect\n key={`ha-${a}-${half}`}\n className=\"swl-hit\"\n x={ax - 8}\n y={y1}\n width={26}\n height={y2 - y1}\n data-kind=\"activity\"\n data-id={a}\n data-lane={l}\n />,\n );\n });\n });\n if (!pre[l] && post[l]) {\n p.visuals.push(\n <rect key={`h-${l}`} className=\"swl-lane-head\" x={x - 16} y={g.mid - 5} width={32} height={10} rx={2} />,\n <text key={`ht-${l}`} className=\"swl-lbl-muted\" x={x + 20} y={g.mid + 3}>\n + {laneLabels[l] ?? l} joined\n </text>,\n );\n }\n });\n}\n\nfunction drawArrow(\n p: Parts,\n g: Geo,\n idx: (l: string) => number,\n a: {\n from: string;\n to: string;\n cls: string;\n marker: string;\n label: string;\n hitId: string;\n kind: SwimlaneTargetKind;\n rowId?: SwimlaneRowId;\n hl: boolean;\n /** Secondary highlight: a transition created/received by the hovered process. */\n rel?: boolean;\n },\n) {\n const i1 = idx(a.from);\n const i2 = idx(a.to);\n if (i1 < 0 || i2 < 0) return;\n const x1 = laneX(g, i1);\n const x2 = laneX(g, i2);\n const cls = clsx(\"swl-ar\", a.cls, a.hl ? \"swl-hl\" : a.rel && \"swl-hl-rel\");\n const markerEnd = `url(#${g.mk}-${a.marker})`;\n const hitData = {\"data-kind\": a.kind, \"data-id\": a.hitId, \"data-row\": a.rowId};\n if (a.from === a.to) {\n const d = `M${x1 + 6},${g.mid - 9} h26 v16 h-20`;\n p.visuals.push(\n <path key=\"ar\" className={cls} d={d} markerEnd={markerEnd} />,\n <text key=\"lb\" className=\"swl-lbl\" x={x1 + 38} y={g.mid + 3}>\n {a.label}\n </text>,\n );\n p.hits.push(<path key=\"hit\" className=\"swl-hit\" d={d} strokeWidth={14} pointerEvents=\"stroke\" {...hitData} />);\n return;\n }\n const dir = Math.sign(x2 - x1);\n const sx = x1 + dir * 6;\n const ex = x2 - dir * 6;\n p.visuals.push(\n <line key=\"ar\" className={cls} x1={sx} x2={ex} y1={g.mid} y2={g.mid} markerEnd={markerEnd} />,\n <text key=\"lb\" className=\"swl-lbl\" x={Math.min(sx, ex) + 8} y={g.mid - 5}>\n {a.label}\n </text>,\n );\n // broad hit zone: a 16px thick invisible band over the thin line\n p.hits.push(\n <line\n key=\"hit\"\n className=\"swl-hit\"\n x1={sx}\n x2={ex}\n y1={g.mid}\n y2={g.mid}\n strokeWidth={16}\n pointerEvents=\"stroke\"\n {...hitData}\n />,\n );\n}\n\nconst CALL_STYLE = {\n sync: [\"swl-ar-sync\", \"sync\"],\n async: [\"swl-ar-async\", \"async\"],\n event: [\"swl-ar-event\", \"event\"],\n} as const;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Rows\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype RowCommon = {\n g: Geo;\n laneOrder: string[];\n laneLabels: Record<string, string>;\n /** Per-lane extra class for the activity bar (`SwimlaneLaneEvent.activityClassName`). */\n laneActivityClassName: Record<string, string>;\n /** Per-lane inline style for the activity bar (`SwimlaneLaneEvent.activityStyle`). */\n laneActivityStyle: Record<string, React.CSSProperties>;\n width: number;\n hl: string | null;\n /** True when this row's transition belongs to a child of the highlighted call. */\n rel?: boolean;\n /** Call id of the process (activity) that sends/receives the hovered transition. */\n proc?: string | null;\n /** Formats the timestamp column. Defaults to local wall-clock time. */\n fmtTs: (ts: number) => string;\n};\n\nconst RealRow = memo(function RealRow({\n row, g, laneOrder, laneLabels, laneActivityClassName, laneActivityStyle, width, hl, rel, proc, fmtTs, grouped, stepHl,\n}: RowCommon & {\n row: SwimlaneRow;\n /** Shares `step` with the previous row: draw a tie mark instead of a timestamp. */\n grouped?: boolean;\n /** This row's step is the hovered/clicked/highlighted one. */\n stepHl?: boolean;\n}) {\n const p: Parts = {visuals: [], hits: []};\n const idx = (l: string) => laneOrder.indexOf(l);\n drawLanes(p, g, laneOrder, row.pre, row.post, hl, laneLabels, proc, laneActivityClassName, laneActivityStyle);\n const ev = row.event;\n switch (ev.type) {\n case \"call\": {\n const [cls, marker] = CALL_STYLE[ev.kind];\n drawArrow(p, g, idx, {\n from: ev.from, to: ev.to, cls, marker, label: ev.label,\n hitId: ev.id, kind: \"transition\", rowId: row.id, hl: hl === ev.id, rel,\n });\n break;\n }\n case \"reply\":\n if (row.route) {\n drawArrow(p, g, idx, {\n from: row.route.to, to: row.route.from,\n cls: ev.ok ? \"swl-ar-reply\" : \"swl-ar-error\", marker: ev.ok ? \"reply\" : \"error\",\n label: ev.label, hitId: ev.id, kind: \"transition\", rowId: row.id, hl: hl === ev.id, rel,\n });\n }\n break;\n case \"done\":\n if (row.route) {\n p.visuals.push(\n <text key=\"dn\" className=\"swl-lbl-muted\" x={laneX(g, idx(row.route.to)) + 14} y={g.mid + 3}>\n ✓ processed {row.route.label}\n </text>,\n );\n }\n break;\n case \"state\": {\n const x = laneX(g, idx(ev.lane));\n p.visuals.push(<circle key=\"st\" cx={x} cy={g.mid} r={5} className={`swl-dot-${ev.state}`} />);\n if (ev.showLabel ?? true) {\n p.visuals.push(\n <text key=\"stl\" className=\"swl-lbl-muted\" x={x + 10} y={g.mid + 3}>\n → {ev.state}\n </text>,\n );\n }\n p.hits.push(\n <circle\n key=\"sth\"\n className=\"swl-hit\"\n cx={x}\n cy={g.mid}\n r={12}\n data-kind=\"state\"\n data-id={`state-${row.id}`}\n data-lane={ev.lane}\n data-row={row.id}\n />,\n );\n break;\n }\n }\n return (\n <svg\n className={clsx(\"swl-row\", row.fulfilled && \"swl-arrived\", grouped && \"swl-grouped\", stepHl && \"swl-hl-step\")}\n width={width}\n height={g.rowH}\n data-row={row.id}\n >\n {grouped ? (\n <line className=\"swl-ts-tie\" x1={6} x2={6} y1={0} y2={g.rowH} />\n ) : (\n <text className=\"swl-ts\" x={0} y={g.mid + 3}>\n {fmtTs(ev.ts)}\n </text>\n )}\n {row.fulfilled && (() => {\n const isError = ev.type === \"reply\" && ev.ok === false;\n return (\n <text className={clsx(\"swl-ok\", isError && \"swl-ok-error\")} x={g.gutter - 16} y={g.mid + 4}>\n <title>{isError ? \"replaced an outstanding message (error)\" : \"replaced an outstanding message\"}</title>\n {isError ? \"✗\" : \"✓\"}\n </text>\n );\n })()}\n {p.visuals}\n <rect\n className=\"swl-hit\"\n x={0}\n y={0}\n width={g.gutter - 2}\n height={g.rowH}\n data-kind=\"step\"\n data-id={stepKeyOf(row)}\n data-row={row.id}\n />\n {p.hits}\n </svg>\n );\n});\n\nconst DEF_FORMAT_WAIT = (ms: number) => `${(ms / 1000).toFixed(1)}s`;\n\nconst GhostRow = memo(function GhostRow({\n row, g, laneOrder, laneLabels, laneActivityClassName, laneActivityStyle, width, hl, rel, proc, now,\n formatWait = DEF_FORMAT_WAIT,\n}: RowCommon & {row: SwimlaneGhostRow; now: number; formatWait?: (ms: number) => string}) {\n const p: Parts = {visuals: [], hits: []};\n const pd = row.pending;\n const waited = now - pd.since;\n const overdue = pd.timeoutMs != null && waited > pd.timeoutMs;\n drawLanes(p, g, laneOrder, row.pre, row.post, hl, laneLabels, proc, laneActivityClassName, laneActivityStyle);\n drawArrow(p, g, (l) => laneOrder.indexOf(l), {\n from: pd.from, to: pd.to, cls: clsx(\"swl-ar-ghost\", overdue && \"swl-overdue\"), marker: \"ghost\",\n label: `⌛ ${pd.label}`, hitId: pd.id, kind: \"pending\", hl: hl === pd.id, rel,\n });\n return (\n <svg className=\"swl-row swl-ghost\" width={width} height={g.rowH}>\n <text className={clsx(\"swl-ts\", overdue && \"swl-overdue\")} x={0} y={g.mid + 3}>\n waiting {formatWait(waited)}\n </text>\n {p.visuals}\n {p.hits}\n </svg>\n );\n});\n\nconst NowRow = memo(function NowRow({\n snap, count, g, laneOrder, laneLabels, laneActivityClassName, laneActivityStyle, width, proc,\n}: Omit<RowCommon, \"hl\" | \"rel\"> & {snap: SwimlaneLanesSnapshot; count: number}) {\n const p: Parts = {visuals: [], hits: []};\n drawLanes(p, g, laneOrder, snap, snap, null, laneLabels, proc, laneActivityClassName, laneActivityStyle);\n return (\n <svg className=\"swl-row swl-now\" width={width} height={g.rowH}>\n <text className=\"swl-now-lbl\" x={0} y={g.mid + 3}>now</text>\n {p.visuals}\n <line className=\"swl-now-line\" x1={g.gutter - 6} x2={width - 10} y1={g.mid} y2={g.mid} />\n <text className=\"swl-now-lbl\" x={width - 136} y={g.mid - 4}>▼ {count} outstanding</text>\n </svg>\n );\n});\n\nfunction PendingZone(\n props: Omit<RowCommon, \"hl\" | \"rel\" | \"proc\"> & {\n model: SwimlaneModel;\n hid: string | null;\n related: ReadonlySet<string>;\n procId: string | null;\n clock?: number;\n formatWait?: (ms: number) => string;\n },\n) {\n const {model, hid, related, procId, clock, formatWait, ...common} = props;\n const [tick, setNow] = useState(() => Date.now());\n const now = clock ?? tick;\n const any = model.pending.length > 0;\n useEffect(() => {\n // only the ghost rows tick (for the \"waiting\" timer); a `now` prop disables the ticker\n if (!any || clock != null) return;\n const iv = setInterval(() => setNow(Date.now()), 250);\n return () => clearInterval(iv);\n }, [any, clock]);\n const {current, pending} = model;\n const ghosts = useMemo(() => projectPending(current, pending), [current, pending]);\n return (\n <>\n <NowRow\n snap={model.current}\n count={model.pending.length}\n proc={procId && rowTouches({pre: model.current, post: model.current}, undefined, procId) ? procId : null}\n {...common}\n />\n {ghosts.map((gr) => (\n <GhostRow\n key={gr.id}\n row={gr}\n now={now}\n hl={hid && rowTouches(gr, gr.pending.id, hid) ? hid : null}\n rel={related.has(gr.pending.id)}\n proc={procId && rowTouches(gr, undefined, procId) ? procId : null}\n formatWait={formatWait}\n {...common}\n />\n ))}\n </>\n );\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Header\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction Header({model, g, headH, width}: {model: SwimlaneModel; g: Geo; headH: number; width: number}) {\n return (\n <svg width={width} height={headH}>\n {model.laneOrder.map((l, i) => {\n const x = laneX(g, i);\n const s = model.current[l];\n const y = headH - 24;\n return (\n <g key={l}>\n <text className=\"swl-lane-name\" x={x + 4} y={y} transform={`rotate(-90 ${x + 4} ${y})`}>\n {model.laneLabels[l] ?? l}\n </text>\n <circle cx={x} cy={headH - 12} r={5} className={`swl-dot-${s?.state}`}>\n <title>{s?.state}</title>\n </circle>\n {s && s.acts.length > 0 && (\n <text className=\"swl-lbl-muted\" x={x + 9} y={headH - 8}>\n {s.acts.length}\n </text>\n )}\n <rect\n className=\"swl-hit\"\n x={x - g.laneW / 2}\n y={0}\n width={g.laneW}\n height={headH}\n data-kind=\"lane\"\n data-id={l}\n data-lane={l}\n />\n </g>\n );\n })}\n </svg>\n );\n}\n\nfunction Defs({mk}: {mk: string}) {\n const m = (id: string, cls: string, open: boolean) => (\n <marker\n id={`${mk}-${id}`}\n viewBox=\"0 0 10 10\"\n refX={9}\n refY={5}\n markerWidth={9}\n markerHeight={9}\n markerUnits=\"userSpaceOnUse\"\n orient=\"auto-start-reverse\"\n >\n {open ? <path d=\"M1,1 L9,5 L1,9\" className={cls} /> : <path d=\"M0,0 L10,5 L0,10 z\" className={cls} />}\n </marker>\n );\n return (\n <svg width={0} height={0} style={{position: \"absolute\"}} aria-hidden=\"true\">\n <defs>\n {m(\"sync\", \"swl-mk-sync\", false)}\n {m(\"async\", \"swl-mk-async\", true)}\n {m(\"event\", \"swl-mk-event\", true)}\n {m(\"reply\", \"swl-mk-reply\", true)}\n {m(\"error\", \"swl-mk-error\", false)}\n {m(\"ghost\", \"swl-mk-ghost\", true)}\n </defs>\n </svg>\n );\n}\n\n/**\n * For a hovered transition (call / reply arrow, or outstanding reply): the\n * call id of the caller-side activity that sent it / receives the reply.\n */\nfunction processOf(m: Pick<SwimlaneModel, \"spans\">, t: SwimlaneTarget): string | null {\n if (t.kind !== \"transition\" && t.kind !== \"pending\") return null;\n return m.spans[t.id]?.parent ?? null;\n}\n\nfunction scrollParent(el: HTMLElement | null): HTMLElement | null {\n for (let e = el?.parentElement; e; e = e.parentElement) {\n const oy = getComputedStyle(e).overflowY;\n if (oy === \"auto\" || oy === \"scroll\") return e;\n }\n return null; // → window\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Card\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const SwimlaneComponent = (props: PiCardProps<SwimlaneProps, SwimlaneEvents>): React.ReactNode => {\n const {\n cardName,\n model,\n showPending = true,\n autoFollow = true,\n showTooltip = true,\n highlightId,\n laneWidth = DEF_LANE_WIDTH,\n rowHeight = DEF_ROW_HEIGHT,\n headerHeight = DEF_HEADER_HEIGHT,\n gutterWidth = DEF_GUTTER_WIDTH,\n stickyTop = 0,\n now: clock,\n formatTs: fmtTs = formatTs,\n formatWait,\n className,\n style,\n onHoverChanged,\n onItemClicked,\n } = props;\n\n const mk = \"swl\" + useId().replace(/[^a-zA-Z0-9_-]/g, \"\");\n const g = useMemo<Geo>(\n () => ({laneW: laneWidth, rowH: rowHeight, gutter: gutterWidth, mid: rowHeight / 2, mk}),\n [laneWidth, rowHeight, gutterWidth, mk],\n );\n const width = gutterWidth + model.laneOrder.length * laneWidth + 140; // + room for labels\n const common = {\n g,\n laneOrder: model.laneOrder,\n laneLabels: model.laneLabels,\n laneActivityClassName: model.laneActivityClassName,\n laneActivityStyle: model.laneActivityStyle,\n width,\n fmtTs,\n };\n\n const rootRef = useRef<HTMLDivElement>(null);\n const tipRef = useRef<HTMLDivElement>(null);\n const modelRef = useRef(model);\n modelRef.current = model;\n\n // ── hover / click (event delegation) ─────────────────────────────────────\n const [hovered, setHovered] = useState<SwimlaneTarget | null>(null);\n const hoveredRef = useRef<SwimlaneTarget | null>(null);\n\n const targetOf = (el: Element | null): SwimlaneTarget | null => {\n const hit = (el as HTMLElement | null)?.closest?.(\".swl-hit\") as SVGElement | null;\n if (!hit) return null;\n const d = hit.dataset;\n return {\n kind: d.kind as SwimlaneTargetKind,\n id: d.id!,\n lane: d.lane,\n // DOM dataset values are always strings; row ids may be numbers\n // (internal) or caller-chosen strings/numbers (see `SwimlaneRowId`),\n // so `rowId` is compared against `String(row.id)` rather than parsed.\n rowId: d.row,\n };\n };\n const same = (a: SwimlaneTarget | null, b: SwimlaneTarget | null) =>\n a === b || (!!a && !!b && a.kind === b.kind && a.id === b.id);\n\n const details = (t: SwimlaneTarget) => {\n const m = modelRef.current;\n if (t.kind === \"step\") return {steps: stepRows(m, t.id)};\n if (t.kind === \"lane\") return {meta: m.laneMeta[t.id]};\n if (t.kind === \"state\") {\n const r = m.rows.find((x) => String(x.id) === t.rowId);\n const meta = r && r.event.type === \"state\" ? r.event.meta : undefined;\n return {related: undefined, process: undefined, meta};\n }\n const related = relatedCallIds(m, t.id);\n const process = processOf(m, t) ?? undefined;\n const pending = t.kind === \"pending\" ? m.pending.find((p) => p.id === t.id) : undefined;\n const meta = pending ? pending.meta : m.spans[t.id]?.meta;\n return t.kind === \"pending\"\n ? {pending, span: m.spans[t.id], related, process, meta}\n : {span: m.spans[t.id], related, process, meta};\n };\n\n const placeTip = (x: number, y: number) => {\n const tip = tipRef.current;\n if (tip) {\n tip.style.left = `${x + 14}px`;\n tip.style.top = `${y + 14}px`;\n }\n };\n\n const changeHover = (next: SwimlaneTarget | null, e: React.PointerEvent) => {\n const prev = hoveredRef.current;\n if (same(prev, next)) return; // e.g. same activity continuing in the next row\n hoveredRef.current = next;\n setHovered(next);\n const tip = tipRef.current;\n if (tip) {\n if (next && showTooltip) {\n tip.textContent = describeSwimlaneTarget(modelRef.current, next, clock ?? Date.now(), fmtTs);\n tip.style.display = \"block\";\n placeTip(e.clientX, e.clientY);\n } else {\n tip.style.display = \"none\";\n }\n }\n onHoverChanged({\n target: next,\n previous: prev,\n ...(next ? details(next) : {}),\n clientX: e.clientX,\n clientY: e.clientY,\n });\n };\n\n const onOver = (e: React.PointerEvent) => {\n const t = targetOf(e.target as Element);\n if (t) changeHover(t, e);\n };\n const onOut = (e: React.PointerEvent) => {\n const t = targetOf(e.relatedTarget as Element | null);\n if (!t || !same(t, hoveredRef.current)) changeHover(t, e);\n };\n const onMove = (e: React.PointerEvent) => {\n if (hoveredRef.current && showTooltip) placeTip(e.clientX, e.clientY);\n };\n const onClick = (e: React.MouseEvent) => {\n const t = targetOf(e.target as Element);\n if (t) onItemClicked({target: t, ...details(t)});\n };\n\n // ── highlighting: only rows touching the chain get a new `hl` prop ───────\n const hid =\n hovered && hovered.kind !== \"state\" && hovered.kind !== \"step\" && hovered.kind !== \"lane\"\n ? hovered.id\n : highlightId ?? null;\n // children of the highlighted call: transitions the process creates/receives\n const {spans} = model;\n const related = useMemo<ReadonlySet<string>>(\n () => new Set(hid ? relatedCallIds({spans}, hid) : []),\n [hid, spans],\n );\n // hovering a transition: also mark the process on the caller side that sent\n // the call / receives the reply (the parent activity) — only that activity\n const procId = hovered ? processOf(model, hovered) : null;\n // hovering (or clicking) a timestamp: the whole step it belongs to\n const stepId = hovered?.kind === \"step\" ? hovered.id : null;\n\n // ── auto-follow (page or nearest scroll container) ───────────────────────\n const follow = useRef(true);\n useEffect(() => {\n if (!autoFollow) return;\n const sp = scrollParent(rootRef.current);\n const target: HTMLElement | Window = sp ?? window;\n const onScroll = () => {\n follow.current = sp\n ? sp.scrollTop + sp.clientHeight >= sp.scrollHeight - 40\n : window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 40;\n };\n target.addEventListener(\"scroll\", onScroll, {passive: true});\n return () => target.removeEventListener(\"scroll\", onScroll);\n }, [autoFollow]);\n useLayoutEffect(() => {\n if (!autoFollow || !follow.current) return;\n const sp = scrollParent(rootRef.current);\n if (sp) sp.scrollTop = sp.scrollHeight;\n else window.scrollTo(0, document.documentElement.scrollHeight);\n }, [autoFollow, model.rows.length, model.pending.length]);\n\n return (\n <div\n ref={rootRef}\n className={clsx(\"pihanga-swimlane\", className)}\n style={style}\n data-pihanga={cardName}\n onPointerOver={onOver}\n onPointerOut={onOut}\n onPointerMove={onMove}\n onClick={onClick}\n >\n <Defs mk={mk} />\n <div className=\"swl-header\" style={{top: stickyTop}}>\n <Header model={model} g={g} headH={headerHeight} width={width} />\n </div>\n <div className=\"swl-rows\">\n {model.rows.map((r, i) => (\n <RealRow\n key={r.id}\n row={r}\n hl={hid && rowTouches(r, \"id\" in r.event ? r.event.id : undefined, hid) ? hid : null}\n rel={\"id\" in r.event && r.event.type !== \"done\" && related.has(r.event.id)}\n proc={procId && rowTouches(r, undefined, procId) ? procId : null}\n grouped={r.event.step != null && r.event.step === model.rows[i - 1]?.event.step}\n stepHl={stepId != null && stepKeyOf(r) === stepId}\n {...common}\n />\n ))}\n {showPending && (\n <PendingZone\n model={model}\n hid={hid}\n related={related}\n procId={procId}\n clock={clock}\n formatWait={formatWait}\n {...common}\n />\n )}\n </div>\n <div ref={tipRef} className=\"swl-tooltip\" role=\"tooltip\" />\n </div>\n );\n};\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ :root{--swl-sync:oklch(55% .2 260);--swl-async:oklch(55% .22 295);--swl-event:oklch(60% .11 185);--swl-act-fill:oklch(93% .04 255);--swl-hl:oklch(77% .16 70);--swl-starting:oklch(67% .16 60);--swl-degraded:oklch(65% .19 45);--swl-running:oklch(60% .15 150);--swl-in-progress:oklch(60% .17 255);--swl-succeeded:oklch(60% .15 150);--swl-failed:oklch(60% .22 25)}.dark{--swl-sync:oklch(72% .14 260);--swl-async:oklch(74% .14 295);--swl-event:oklch(78% .11 185);--swl-act-fill:oklch(35% .07 255);--swl-hl:oklch(80% .15 75);--swl-starting:oklch(75% .15 65);--swl-degraded:oklch(72% .17 45);--swl-running:oklch(75% .15 150);--swl-in-progress:oklch(72% .15 255);--swl-succeeded:oklch(75% .15 150);--swl-failed:oklch(72% .2 25)}.pihanga-swimlane{width:max-content;min-width:100%;color:var(--foreground);font-size:13px}.pihanga-swimlane .swl-header{z-index:2;background:var(--background);border-bottom:1px solid var(--border);position:sticky}.pihanga-swimlane svg{display:block;overflow:visible}.pihanga-swimlane svg text{fill:var(--foreground)}.pihanga-swimlane .swl-lane-name{font-size:12px;font-weight:600}.pihanga-swimlane .swl-ts{fill:var(--muted-foreground);font:10px ui-monospace,monospace}.pihanga-swimlane .swl-lbl{font-size:11px}.pihanga-swimlane .swl-lbl-muted{fill:var(--muted-foreground);font-size:10px}.pihanga-swimlane .swl-ts-tie{stroke:var(--muted-foreground);stroke-width:1px;stroke-dasharray:2 2;opacity:.5}.pihanga-swimlane .swl-row.swl-hl-step{background:color-mix(in srgb, var(--swl-hl) 12%, transparent)}.pihanga-swimlane .swl-row.swl-hl-step .swl-ts,.pihanga-swimlane .swl-row.swl-hl-step .swl-ts-tie{stroke:var(--swl-hl);fill:var(--swl-hl);opacity:1}.pihanga-swimlane .swl-ll{stroke-width:1.5px}.pihanga-swimlane .swl-ll-created,.pihanga-swimlane .swl-ll-running{stroke:color-mix(in srgb, var(--muted-foreground) 70%, transparent)}.pihanga-swimlane .swl-ll-starting{stroke:var(--swl-starting);stroke-dasharray:4 3}.pihanga-swimlane .swl-ll-degraded{stroke:var(--swl-degraded);stroke-width:3px}.pihanga-swimlane .swl-ll-stopped{stroke:var(--border);stroke-dasharray:1 4}.pihanga-swimlane .swl-ll-in_progress,.pihanga-swimlane .swl-ll-succeeded,.pihanga-swimlane .swl-ll-failed{stroke:color-mix(in srgb, var(--muted-foreground) 70%, transparent)}.pihanga-swimlane .swl-dot-created,.pihanga-swimlane .swl-dot-starting{fill:var(--swl-starting)}.pihanga-swimlane .swl-dot-running{fill:var(--swl-running)}.pihanga-swimlane .swl-dot-degraded{fill:var(--swl-degraded)}.pihanga-swimlane .swl-dot-stopped{fill:var(--border)}.pihanga-swimlane .swl-dot-in_progress{fill:var(--swl-in-progress)}.pihanga-swimlane .swl-dot-succeeded{fill:var(--swl-succeeded)}.pihanga-swimlane .swl-dot-failed{fill:var(--swl-failed)}.pihanga-swimlane .swl-lane-head{fill:var(--background);stroke:var(--muted-foreground)}.pihanga-swimlane .swl-act rect{fill:var(--swl-act-fill);stroke:none}.pihanga-swimlane .swl-act path{fill:none;stroke:var(--swl-sync);stroke-width:1px}.pihanga-swimlane .swl-act.swl-hl rect{fill:var(--swl-hl)}.pihanga-swimlane .swl-act.swl-hl path{stroke:var(--swl-hl)}.pihanga-swimlane .swl-act.swl-hl-proc rect{fill:color-mix(in srgb, var(--swl-hl) 45%, var(--swl-act-fill))}.pihanga-swimlane .swl-act.swl-hl-proc path{stroke:var(--swl-hl);stroke-width:2px}.pihanga-swimlane .swl-ar{fill:none;stroke-width:1.5px}.pihanga-swimlane .swl-ar-sync{stroke:var(--swl-sync)}.pihanga-swimlane .swl-ar-async{stroke:var(--swl-async)}.pihanga-swimlane .swl-ar-event{stroke:var(--swl-event);stroke-dasharray:2 3}.pihanga-swimlane .swl-ar-reply{stroke:var(--muted-foreground);stroke-dasharray:5 3}.pihanga-swimlane .swl-ar-error{stroke:var(--destructive);stroke-dasharray:5 3}.pihanga-swimlane .swl-ar-ghost{stroke:var(--muted-foreground);stroke-dasharray:7 4}.pihanga-swimlane .swl-ar-ghost.swl-overdue{stroke:var(--destructive)}.pihanga-swimlane .swl-ar.swl-hl{stroke:var(--swl-hl);stroke-width:3px}.pihanga-swimlane .swl-ar.swl-hl-rel{stroke:var(--swl-hl);stroke-width:2px}.pihanga-swimlane .swl-mk-sync{fill:var(--swl-sync)}.pihanga-swimlane .swl-mk-async{fill:none;stroke:var(--swl-async);stroke-width:1.5px}.pihanga-swimlane .swl-mk-event{fill:none;stroke:var(--swl-event);stroke-width:1.5px}.pihanga-swimlane .swl-mk-reply,.pihanga-swimlane .swl-mk-ghost{fill:none;stroke:var(--muted-foreground);stroke-width:1.5px}.pihanga-swimlane .swl-mk-error{fill:var(--destructive)}.pihanga-swimlane .swl-ghost{opacity:.55}.pihanga-swimlane .swl-ts.swl-overdue{fill:var(--destructive);font-weight:600}.pihanga-swimlane .swl-now-line{stroke:var(--swl-hl);stroke-width:1.5px;stroke-dasharray:10 4}.pihanga-swimlane text.swl-now-lbl{fill:var(--swl-hl);font-size:11px;font-weight:600}.pihanga-swimlane text.swl-ok{fill:var(--swl-running);font-size:12px;font-weight:700}.pihanga-swimlane text.swl-ok.swl-ok-error{fill:var(--destructive)}.pihanga-swimlane .swl-arrived{animation:1.6s ease-out swl-arrive}@keyframes swl-arrive{0%{background:color-mix(in srgb, var(--swl-hl) 45%, transparent)}to{background:0 0}}.pihanga-swimlane .swl-hit{fill:#0000;stroke:#0000;cursor:pointer}.pihanga-swimlane .swl-hit[data-kind=lane]:hover{fill:color-mix(in srgb, var(--swl-hl) 10%, transparent)}.pihanga-swimlane.swl-debug-hits .swl-hit{fill:color-mix(in srgb, var(--destructive) 10%, transparent);stroke:color-mix(in srgb, var(--destructive) 20%, transparent)}.pihanga-swimlane .swl-tooltip{z-index:50;pointer-events:none;border-radius:calc(var(--radius) - 2px);border:1px solid var(--border);background:var(--popover);max-width:340px;color:var(--popover-foreground);box-shadow:0 4px 12px color-mix(in srgb, var(--foreground) 15%, transparent);padding:6px 8px;font-size:12px;display:none;position:fixed}