@pihanga2/shadcn 0.2.23 → 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.
@@ -1,3 +1,4 @@
1
+ import { default as React } from 'react';
1
2
  export declare const SWIMLANE_CARD = "shad/swimlane";
2
3
  export declare const Swimlane: <S extends import('@pihanga2/core').ReduxState>(p: import('@pihanga2/core').PiMapProps<SwimlaneProps, S, SwimlaneEvents>) => import('@pihanga2/core').PiCardDef;
3
4
  export declare const SWIMLANE_ACTION: {
@@ -22,8 +23,15 @@ export declare const onSwimlaneEventsReceived: <S extends import('@pihanga2/core
22
23
  export declare const onSwimlaneRowsCleared: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core/types').PiRegisterMinimal, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
23
24
  cardID: string;
24
25
  } & SwimlaneRowsClearedEvent>) => void;
25
- /** Run state of a service, drawn on its lifeline. */
26
- export type SwimlaneRunState = "created" | "starting" | "running" | "degraded" | "stopped";
26
+ /**
27
+ * Run state of a service, drawn on its lifeline.
28
+ *
29
+ * `created` … `stopped` describe a long-running service's lifecycle.
30
+ * `in_progress` / `succeeded` / `failed` are first-class outcome states for
31
+ * one-shot work (e.g. a tool call or task) that does not fit that lifecycle —
32
+ * use these instead of borrowing `running` / `stopped` / `degraded`.
33
+ */
34
+ export type SwimlaneRunState = "created" | "starting" | "running" | "degraded" | "stopped" | "in_progress" | "succeeded" | "failed";
27
35
  /**
28
36
  * How a message travels between lanes.
29
37
  * - `sync` – request that expects a reply; opens an activity on the target
@@ -32,11 +40,48 @@ export type SwimlaneRunState = "created" | "starting" | "running" | "degraded" |
32
40
  * - `event` – fire-and-forget; no activity.
33
41
  */
34
42
  export type SwimlaneCallKind = "sync" | "async" | "event";
43
+ /** Row id: either an internal counter value, or a caller-supplied value (see `rowId`). */
44
+ export type SwimlaneRowId = string | number;
35
45
  type SwimlaneEventBase = {
36
46
  /** Epoch ms. Defaults to `Date.now()` at ingest time. */
37
47
  ts?: number;
38
48
  /** Id of an `expect` event that this real event resolves. */
39
49
  fulfils?: string;
50
+ /**
51
+ * Use this as the resulting row's id instead of the model's internal
52
+ * counter. Lets a caller that rebuilds the whole model from scratch on
53
+ * every refresh (e.g. to replay a run, or after a rollback to an earlier
54
+ * point) keep row ids stable across rebuilds, instead of them being
55
+ * renumbered each time.
56
+ *
57
+ * Contract: must be unique among the model's current rows (an id freed by
58
+ * ring-buffer trimming may be reused). If it collides with an existing
59
+ * row, the card falls back to an internal id for that row rather than
60
+ * producing two rows with the same id — check `SwimlaneRow.id` if you
61
+ * need to confirm which id was actually used.
62
+ *
63
+ * Distinct from a `call`/`reply`/`done` event's own `id` (the call id,
64
+ * shared between its call and reply rows) — `rowId` identifies one row.
65
+ */
66
+ rowId?: SwimlaneRowId;
67
+ /**
68
+ * Groups events that belong to one logical step (for example several
69
+ * calls and a state change produced by a single engine tick). Rows are
70
+ * grouped only when adjacent in `rows` (ingest order): the card draws the
71
+ * timestamp for the first row of a run of same-`step` rows and replaces
72
+ * it with a connecting mark on the rest, joining them into one block.
73
+ * Comparison is `===`; omit it to draw every row on its own line as before.
74
+ */
75
+ step?: string | number;
76
+ /**
77
+ * Arbitrary caller data, opaque to the card. Carried onto the row (and,
78
+ * for `call`/`expect` events, the resulting span/pending message) and
79
+ * echoed back verbatim in `onHoverChanged` / `onItemClicked` for that
80
+ * target — so the caller does not need a side table to recover context
81
+ * (e.g. which domain object a row/span id stands for) on every hover or
82
+ * click. Not interpreted or serialised specially by the card.
83
+ */
84
+ meta?: unknown;
40
85
  };
41
86
  /** A service became known. Lanes referenced by calls are also added implicitly. */
42
87
  export type SwimlaneLaneEvent = SwimlaneEventBase & {
@@ -44,12 +89,40 @@ export type SwimlaneLaneEvent = SwimlaneEventBase & {
44
89
  lane: string;
45
90
  /** Display name (defaults to `lane`). */
46
91
  label?: string;
92
+ /**
93
+ * Extra class(es) added to this lane's activity bar (the `<g className="swl-act">`
94
+ * drawn on the lifeline while the lane is handling a call), alongside the
95
+ * default `swl-act`/highlight classes. Use this to give different lane
96
+ * *types* their own themed colour via CSS (e.g. `.swl-act-tool rect {
97
+ * fill: var(--my-tool-color); }`) instead of hard-coding colours per lane.
98
+ * Most recent `lane` event for a lane wins, same as `label`/`meta`.
99
+ */
100
+ activityClassName?: string;
101
+ /**
102
+ * Inline style merged onto the activity bar's `<rect>` (fill) and `<path>`
103
+ * (border) elements, for one-off colours that don't warrant a CSS class.
104
+ * Takes precedence over `activityClassName`'s rules for any property it
105
+ * sets. Most recent `lane` event for a lane wins, same as `label`/`meta`.
106
+ */
107
+ activityStyle?: React.CSSProperties;
108
+ /**
109
+ * When `false`, this event still registers the lane (and updates its
110
+ * label/meta/activity style exactly as usual) but produces no row — as if
111
+ * the lane had been present from the start via `createSwimlaneModel({lanes})`.
112
+ * Only has an effect the first time a lane is seen: a later `lane` event
113
+ * for an already-known lane never produces a row regardless of
114
+ * `announce` (same as today), so there is no way to retroactively force a
115
+ * "joined" row to appear for a lane once it is known. Default `true`.
116
+ */
117
+ announce?: boolean;
47
118
  };
48
119
  /** A service changed its run state. */
49
120
  export type SwimlaneStateEvent = SwimlaneEventBase & {
50
121
  type: "state";
51
122
  lane: string;
52
123
  state: SwimlaneRunState;
124
+ /** Draw the "→ state" text beside the dot. Default `true`. */
125
+ showLabel?: boolean;
53
126
  };
54
127
  /** A message between two lanes (or a lane and itself). */
55
128
  export type SwimlaneCallEvent = SwimlaneEventBase & {
@@ -114,7 +187,12 @@ export type SwimlaneRowEvent = Exclude<SwimlaneEvent, SwimlaneExpectEvent> & {
114
187
  * half from `post`.
115
188
  */
116
189
  export type SwimlaneRow = {
117
- id: number;
190
+ /**
191
+ * The event's own `rowId` when it was set and did not collide with an
192
+ * existing row; an internally assigned number otherwise. See
193
+ * `SwimlaneEventBase.rowId`.
194
+ */
195
+ id: SwimlaneRowId;
118
196
  event: SwimlaneRowEvent;
119
197
  pre: SwimlaneLanesSnapshot;
120
198
  post: SwimlaneLanesSnapshot;
@@ -147,6 +225,8 @@ export type SwimlanePending = {
147
225
  label: string;
148
226
  since: number;
149
227
  timeoutMs?: number;
228
+ /** Copied from the originating `call` (implied reply) or `expect` event. */
229
+ meta?: unknown;
150
230
  };
151
231
  /** Lifecycle of a call, used for tooltips and hover payloads. */
152
232
  export type SwimlaneSpan = {
@@ -161,12 +241,20 @@ export type SwimlaneSpan = {
161
241
  result?: string;
162
242
  /** Call whose processing caused this one (explicit `parentId` or inferred). */
163
243
  parent?: string;
244
+ /** Copied from the originating `call` event. */
245
+ meta?: unknown;
164
246
  };
165
247
  export type SwimlaneModel = {
166
248
  /** Lane ids in display (arrival) order. */
167
249
  laneOrder: string[];
168
250
  /** Optional display names. */
169
251
  laneLabels: Record<string, string>;
252
+ /** Caller `meta` from each lane's `lane` event(s), most recent wins. */
253
+ laneMeta: Record<string, unknown>;
254
+ /** `activityClassName` from each lane's `lane` event(s)/seed, most recent wins. */
255
+ laneActivityClassName: Record<string, string>;
256
+ /** `activityStyle` from each lane's `lane` event(s)/seed, most recent wins. */
257
+ laneActivityStyle: Record<string, React.CSSProperties>;
170
258
  /** Current snapshot (== `post` of the last row). */
171
259
  current: SwimlaneLanesSnapshot;
172
260
  rows: SwimlaneRow[];
@@ -211,16 +299,33 @@ export type SwimlaneProps = {
211
299
  * entirely from props — e.g. for replaying a recorded trace or for tests.
212
300
  */
213
301
  now?: number;
302
+ /**
303
+ * Formats the timestamp column (`ts`, epoch ms). Defaults to `formatTs`
304
+ * from `swimlane.model` (local wall-clock `HH:MM:SS.mmm`). Override to
305
+ * show a different clock — e.g. a virtual time derived from `ts`, or both
306
+ * virtual and wall-clock time in one string.
307
+ */
308
+ formatTs?: (ts: number) => string;
309
+ /**
310
+ * Formats the "waiting …" duration (ms) shown on outstanding messages
311
+ * below the "now" line. Defaults to `${(ms / 1000).toFixed(1)}s`.
312
+ */
313
+ formatWait?: (ms: number) => string;
214
314
  className?: string;
315
+ /** Inline styles for the card's root element, alongside `className`. */
316
+ style?: React.CSSProperties;
215
317
  };
216
318
  /** What the pointer is over. */
217
- export type SwimlaneTargetKind = "transition" | "activity" | "state" | "pending";
319
+ export type SwimlaneTargetKind = "transition" | "activity" | "state" | "pending" | "step" | "lane";
218
320
  export type SwimlaneTarget = {
219
321
  kind: SwimlaneTargetKind;
220
- /** Call id (transition/activity/pending) or `state-<rowId>` (state). */
322
+ /**
323
+ * Call id (`transition`/`activity`/`pending`), `state-<rowId>` (`state`),
324
+ * the row's `step` value stringified (`step`), or the lane id (`lane`).
325
+ */
221
326
  id: string;
222
327
  lane?: string;
223
- rowId?: number;
328
+ rowId?: SwimlaneRowId;
224
329
  };
225
330
  export type SwimlaneHoverChangedEvent = {
226
331
  /** New hover target, or `null` when the pointer left all targets. */
@@ -241,6 +346,15 @@ export type SwimlaneHoverChangedEvent = {
241
346
  * that sent the call and receives its reply. That activity is highlighted.
242
347
  */
243
348
  process?: string;
349
+ /** For `target.kind === "step"`: every row belonging to that step. */
350
+ steps?: SwimlaneRow[];
351
+ /**
352
+ * Caller `meta` for the target, if any was set on the originating event:
353
+ * the `call`'s `meta` for `transition`/`activity`/`pending`, the `state`
354
+ * event's `meta` for `state`, the `lane` event's `meta` for `lane`. Not
355
+ * set for `step` (see `steps`, which carries each row's own event/meta).
356
+ */
357
+ meta?: unknown;
244
358
  clientX?: number;
245
359
  clientY?: number;
246
360
  };
@@ -250,6 +364,10 @@ export type SwimlaneItemClickedEvent = {
250
364
  pending?: SwimlanePending;
251
365
  related?: string[];
252
366
  process?: string;
367
+ /** For `target.kind === "step"`: every row belonging to that step. */
368
+ steps?: SwimlaneRow[];
369
+ /** See `SwimlaneHoverChangedEvent.meta`. */
370
+ meta?: unknown;
253
371
  };
254
372
  export type SwimlaneEvents = {
255
373
  onHoverChanged: SwimlaneHoverChangedEvent;
@@ -1 +1 @@
1
- {"version":3,"file":"swimlane.types.js","names":[],"sources":["../../../src/cards/swimlane/swimlane.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n createOnDispatch,\n registerActions,\n} from \"@pihanga2/core\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Card identity\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const SWIMLANE_CARD = \"shad/swimlane\";\n\nexport const Swimlane = createCardDeclaration<SwimlaneProps, SwimlaneEvents>(\n SWIMLANE_CARD,\n);\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Actions EMITTED by the card (user interaction)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const SWIMLANE_ACTION = registerActions(SWIMLANE_CARD, [\n \"hover_changed\",\n \"item_clicked\",\n]);\n\nexport const onSwimlaneHoverChanged = createOnAction<SwimlaneHoverChangedEvent>(\n SWIMLANE_ACTION.HOVER_CHANGED,\n);\n\nexport const onSwimlaneItemClicked = createOnAction<SwimlaneItemClickedEvent>(\n SWIMLANE_ACTION.ITEM_CLICKED,\n);\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Actions CONSUMED by the app (feeding the model).\n//\n// These are not emitted by the card. They are a convenience so that stream\n// adapters (WebSocket, SSE, polling …) can push events with a typed dispatcher\n// and apps can wire the model with a single `registerSwimlaneModel()` call\n// (see swimlane.model.ts).\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const SWIMLANE_DATA_ACTION = registerActions(`${SWIMLANE_CARD}/data`, [\n \"events_received\",\n \"rows_cleared\",\n]);\n\nexport const dispatchSwimlaneEvents =\n createOnDispatch<SwimlaneEventsReceivedEvent>(\n SWIMLANE_DATA_ACTION.EVENTS_RECEIVED,\n );\nexport const dispatchSwimlaneRowsCleared =\n createOnDispatch<SwimlaneRowsClearedEvent>(SWIMLANE_DATA_ACTION.ROWS_CLEARED);\n\nexport const onSwimlaneEventsReceived =\n createOnAction<SwimlaneEventsReceivedEvent>(\n SWIMLANE_DATA_ACTION.EVENTS_RECEIVED,\n );\nexport const onSwimlaneRowsCleared = createOnAction<SwimlaneRowsClearedEvent>(\n SWIMLANE_DATA_ACTION.ROWS_CLEARED,\n);\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Incoming stream events (what a monitored deployment reports)\n// All timestamps are epoch milliseconds; `ts` is filled in on ingest if absent.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Run state of a service, drawn on its lifeline. */\nexport type SwimlaneRunState =\n | \"created\"\n | \"starting\"\n | \"running\"\n | \"degraded\"\n | \"stopped\";\n\n/**\n * How a message travels between lanes.\n * - `sync` – request that expects a reply; opens an activity on the target\n * and automatically creates an *outstanding reply*.\n * - `async` – message that opens an activity on the target, closed by `done`.\n * - `event` – fire-and-forget; no activity.\n */\nexport type SwimlaneCallKind = \"sync\" | \"async\" | \"event\";\n\ntype SwimlaneEventBase = {\n /** Epoch ms. Defaults to `Date.now()` at ingest time. */\n ts?: number;\n /** Id of an `expect` event that this real event resolves. */\n fulfils?: string;\n};\n\n/** A service became known. Lanes referenced by calls are also added implicitly. */\nexport type SwimlaneLaneEvent = SwimlaneEventBase & {\n type: \"lane\";\n lane: string;\n /** Display name (defaults to `lane`). */\n label?: string;\n};\n\n/** A service changed its run state. */\nexport type SwimlaneStateEvent = SwimlaneEventBase & {\n type: \"state\";\n lane: string;\n state: SwimlaneRunState;\n};\n\n/** A message between two lanes (or a lane and itself). */\nexport type SwimlaneCallEvent = SwimlaneEventBase & {\n type: \"call\";\n /** Unique id; replies / `done` refer to it. */\n id: string;\n kind: SwimlaneCallKind;\n from: string;\n to: string;\n label: string;\n /** For `sync`: when the expected reply becomes overdue (ms after `ts`). */\n timeoutMs?: number;\n /**\n * Id of the call whose processing caused this call (like a trace's parent\n * span id). When omitted it is inferred at ingest time as the innermost\n * activity open on the `from` lane — exact for sequential processing, a\n * best guess when one service handles several requests concurrently.\n */\n parentId?: string;\n};\n\n/** Reply to an earlier `sync` call (drawn from callee back to caller). */\nexport type SwimlaneReplyEvent = SwimlaneEventBase & {\n type: \"reply\";\n /** Id of the originating call. */\n id: string;\n ok: boolean;\n label: string;\n};\n\n/** Processing of an earlier `async` call finished (closes the activity). */\nexport type SwimlaneDoneEvent = SwimlaneEventBase & {\n type: \"done\";\n id: string;\n};\n\n/**\n * Announces a message that is KNOWN to arrive later (from → to).\n * Shown as an outstanding ghost row until a real event with `fulfils: id`\n * arrives. Does not create a row itself.\n */\nexport type SwimlaneExpectEvent = SwimlaneEventBase & {\n type: \"expect\";\n id: string;\n from: string;\n to: string;\n label: string;\n timeoutMs?: number;\n};\n\nexport type SwimlaneEvent =\n | SwimlaneLaneEvent\n | SwimlaneStateEvent\n | SwimlaneCallEvent\n | SwimlaneReplyEvent\n | SwimlaneDoneEvent\n | SwimlaneExpectEvent;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Model (lives in the app's Redux state; plain JSON)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type SwimlaneLaneSnapshot = {\n state: SwimlaneRunState;\n /** Ids of calls currently being handled by this lane (stack order). */\n acts: string[];\n};\n\n/** Lane id → snapshot. A lane missing from the record does not exist (yet). */\nexport type SwimlaneLanesSnapshot = Record<string, SwimlaneLaneSnapshot>;\n\n/** A row event is any stream event except `expect` (which never makes a row). */\nexport type SwimlaneRowEvent = Exclude<SwimlaneEvent, SwimlaneExpectEvent> & {\n ts: number;\n};\n\n/**\n * One rendered transition. `pre` / `post` are the lane snapshots before and\n * after the event: the top half of the row is drawn from `pre`, the bottom\n * half from `post`.\n */\nexport type SwimlaneRow = {\n id: number;\n event: SwimlaneRowEvent;\n pre: SwimlaneLanesSnapshot;\n post: SwimlaneLanesSnapshot;\n /** Set when this event replaced an outstanding (expected) message. */\n fulfilled?: string;\n /**\n * For `reply` / `done` rows: the originating call, resolved at ingest time\n * so the row stays drawable after its span has been garbage-collected.\n */\n route?: {from: string; to: string; label: string};\n};\n\n/** An outstanding message projected below the \"now\" line. */\nexport type SwimlaneGhostRow = {\n id: string;\n pending: SwimlanePending;\n pre: SwimlaneLanesSnapshot;\n post: SwimlaneLanesSnapshot;\n};\n\n/** A message that is known to be coming. */\nexport type SwimlanePending = {\n id: string;\n /** `reply` = implied by a sync call; `expect` = announced explicitly. */\n type: \"reply\" | \"expect\";\n from: string;\n to: string;\n label: string;\n since: number;\n timeoutMs?: number;\n};\n\n/** Lifecycle of a call, used for tooltips and hover payloads. */\nexport type SwimlaneSpan = {\n id: string;\n kind: SwimlaneCallKind;\n from: string;\n to: string;\n label: string;\n start: number;\n end?: number;\n status: \"open\" | \"ok\" | \"error\" | \"done\";\n result?: string;\n /** Call whose processing caused this one (explicit `parentId` or inferred). */\n parent?: string;\n};\n\nexport type SwimlaneModel = {\n /** Lane ids in display (arrival) order. */\n laneOrder: string[];\n /** Optional display names. */\n laneLabels: Record<string, string>;\n /** Current snapshot (== `post` of the last row). */\n current: SwimlaneLanesSnapshot;\n rows: SwimlaneRow[];\n pending: SwimlanePending[];\n spans: Record<string, SwimlaneSpan>;\n /** Last assigned row id. */\n seq: number;\n /** Ring-buffer size for `rows`. */\n maxRows: number;\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Card props & events\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type SwimlaneProps = {\n /** The model to render — usually a state selector `(s) => s.swimlane`. */\n model: SwimlaneModel;\n\n /** Show outstanding messages below the \"now\" line. Default `true`. */\n showPending?: boolean;\n\n /**\n * Keep the newest row in view while the user is at the bottom of the\n * scroll container. Scrolling up pauses following. Default `true`.\n */\n autoFollow?: boolean;\n\n /** Show the built-in hover tooltip. Default `true`. */\n showTooltip?: boolean;\n\n /**\n * Highlight a call chain (call, activity, reply, outstanding reply) by id,\n * in addition to whatever the pointer is hovering.\n */\n highlightId?: string;\n\n /** Horizontal distance between lifelines in px. Default 104. */\n laneWidth?: number;\n /** Height of each transition row in px. Default 30. */\n rowHeight?: number;\n /** Height of the header holding the vertical lane names. Default 130. */\n headerHeight?: number;\n /** Width of the left timestamp column in px. Default 92. */\n gutterWidth?: number;\n /** `top` offset for the sticky header (e.g. height of a navbar). Default 0. */\n stickyTop?: number;\n\n /**\n * Clock (epoch ms) used for \"waiting …\" timers and overdue detection of\n * outstanding messages. When omitted the card ticks its own wall clock\n * (4×/s, only while something is outstanding). Pass it to drive the card\n * entirely from props — e.g. for replaying a recorded trace or for tests.\n */\n now?: number;\n\n className?: string;\n};\n\n/** What the pointer is over. */\nexport type SwimlaneTargetKind = \"transition\" | \"activity\" | \"state\" | \"pending\";\n\nexport type SwimlaneTarget = {\n kind: SwimlaneTargetKind;\n /** Call id (transition/activity/pending) or `state-<rowId>` (state). */\n id: string;\n lane?: string;\n rowId?: number;\n};\n\nexport type SwimlaneHoverChangedEvent = {\n /** New hover target, or `null` when the pointer left all targets. */\n target: SwimlaneTarget | null;\n /** Target that was hovered before, if any. */\n previous: SwimlaneTarget | null;\n /** Span details for the new target (when it refers to a call). */\n span?: SwimlaneSpan;\n /** Outstanding message details when `target.kind === \"pending\"`. */\n pending?: SwimlanePending;\n /**\n * Calls made while handling the hovered call (its direct children). Their\n * call and reply transitions are highlighted as well.\n */\n related?: string[];\n /**\n * For a hovered transition: call id of the caller-side process (activity)\n * that sent the call and receives its reply. That activity is highlighted.\n */\n process?: string;\n clientX?: number;\n clientY?: number;\n};\n\nexport type SwimlaneItemClickedEvent = {\n target: SwimlaneTarget;\n span?: SwimlaneSpan;\n pending?: SwimlanePending;\n related?: string[];\n process?: string;\n};\n\nexport type SwimlaneEvents = {\n onHoverChanged: SwimlaneHoverChangedEvent;\n onItemClicked: SwimlaneItemClickedEvent;\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Data-action payloads\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type SwimlaneEventsReceivedEvent = {\n /** Which model to update (apps may show several swimlanes). */\n modelId: string;\n events: SwimlaneEvent[];\n};\n\nexport type SwimlaneRowsClearedEvent = {\n modelId: string;\n};\n\nexport const DEF_LANE_WIDTH = 104;\nexport const DEF_ROW_HEIGHT = 30;\nexport const DEF_HEADER_HEIGHT = 130;\nexport const DEF_GUTTER_WIDTH = 92;\nexport const DEF_MAX_ROWS = 2000;\n"],"mappings":";;AAWA,IAAa,IAAgB,iBAEhB,IAAW,EACtB,CACF,GAMa,IAAkB,EAAgB,GAAe,CAC5D,iBACA,cACF,CAAC,GAEY,IAAyB,EACpC,EAAgB,aAClB,GAEa,IAAwB,EACnC,EAAgB,YAClB,GAWa,IAAuB,EAAgB,GAAG,EAAc,QAAQ,CAC3E,mBACA,cACF,CAAC,GAEY,IACX,EACE,EAAqB,eACvB,GACW,IACX,EAA2C,EAAqB,YAAY,GAEjE,IACX,EACE,EAAqB,eACvB,GACW,IAAwB,EACnC,EAAqB,YACvB,GA4Sa,IAAiB,KACjB,IAAiB,IACjB,IAAoB,KACpB,IAAmB,IACnB,IAAe"}
1
+ {"version":3,"file":"swimlane.types.js","names":[],"sources":["../../../src/cards/swimlane/swimlane.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n createOnDispatch,\n registerActions,\n} from \"@pihanga2/core\";\nimport type React from \"react\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Card identity\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const SWIMLANE_CARD = \"shad/swimlane\";\n\nexport const Swimlane = createCardDeclaration<SwimlaneProps, SwimlaneEvents>(\n SWIMLANE_CARD,\n);\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Actions EMITTED by the card (user interaction)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const SWIMLANE_ACTION = registerActions(SWIMLANE_CARD, [\n \"hover_changed\",\n \"item_clicked\",\n]);\n\nexport const onSwimlaneHoverChanged = createOnAction<SwimlaneHoverChangedEvent>(\n SWIMLANE_ACTION.HOVER_CHANGED,\n);\n\nexport const onSwimlaneItemClicked = createOnAction<SwimlaneItemClickedEvent>(\n SWIMLANE_ACTION.ITEM_CLICKED,\n);\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Actions CONSUMED by the app (feeding the model).\n//\n// These are not emitted by the card. They are a convenience so that stream\n// adapters (WebSocket, SSE, polling …) can push events with a typed dispatcher\n// and apps can wire the model with a single `registerSwimlaneModel()` call\n// (see swimlane.model.ts).\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const SWIMLANE_DATA_ACTION = registerActions(`${SWIMLANE_CARD}/data`, [\n \"events_received\",\n \"rows_cleared\",\n]);\n\nexport const dispatchSwimlaneEvents =\n createOnDispatch<SwimlaneEventsReceivedEvent>(\n SWIMLANE_DATA_ACTION.EVENTS_RECEIVED,\n );\nexport const dispatchSwimlaneRowsCleared =\n createOnDispatch<SwimlaneRowsClearedEvent>(SWIMLANE_DATA_ACTION.ROWS_CLEARED);\n\nexport const onSwimlaneEventsReceived =\n createOnAction<SwimlaneEventsReceivedEvent>(\n SWIMLANE_DATA_ACTION.EVENTS_RECEIVED,\n );\nexport const onSwimlaneRowsCleared = createOnAction<SwimlaneRowsClearedEvent>(\n SWIMLANE_DATA_ACTION.ROWS_CLEARED,\n);\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Incoming stream events (what a monitored deployment reports)\n// All timestamps are epoch milliseconds; `ts` is filled in on ingest if absent.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Run state of a service, drawn on its lifeline.\n *\n * `created` … `stopped` describe a long-running service's lifecycle.\n * `in_progress` / `succeeded` / `failed` are first-class outcome states for\n * one-shot work (e.g. a tool call or task) that does not fit that lifecycle —\n * use these instead of borrowing `running` / `stopped` / `degraded`.\n */\nexport type SwimlaneRunState =\n | \"created\"\n | \"starting\"\n | \"running\"\n | \"degraded\"\n | \"stopped\"\n | \"in_progress\"\n | \"succeeded\"\n | \"failed\";\n\n/**\n * How a message travels between lanes.\n * - `sync` – request that expects a reply; opens an activity on the target\n * and automatically creates an *outstanding reply*.\n * - `async` – message that opens an activity on the target, closed by `done`.\n * - `event` – fire-and-forget; no activity.\n */\nexport type SwimlaneCallKind = \"sync\" | \"async\" | \"event\";\n\n/** Row id: either an internal counter value, or a caller-supplied value (see `rowId`). */\nexport type SwimlaneRowId = string | number;\n\ntype SwimlaneEventBase = {\n /** Epoch ms. Defaults to `Date.now()` at ingest time. */\n ts?: number;\n /** Id of an `expect` event that this real event resolves. */\n fulfils?: string;\n /**\n * Use this as the resulting row's id instead of the model's internal\n * counter. Lets a caller that rebuilds the whole model from scratch on\n * every refresh (e.g. to replay a run, or after a rollback to an earlier\n * point) keep row ids stable across rebuilds, instead of them being\n * renumbered each time.\n *\n * Contract: must be unique among the model's current rows (an id freed by\n * ring-buffer trimming may be reused). If it collides with an existing\n * row, the card falls back to an internal id for that row rather than\n * producing two rows with the same id — check `SwimlaneRow.id` if you\n * need to confirm which id was actually used.\n *\n * Distinct from a `call`/`reply`/`done` event's own `id` (the call id,\n * shared between its call and reply rows) — `rowId` identifies one row.\n */\n rowId?: SwimlaneRowId;\n /**\n * Groups events that belong to one logical step (for example several\n * calls and a state change produced by a single engine tick). Rows are\n * grouped only when adjacent in `rows` (ingest order): the card draws the\n * timestamp for the first row of a run of same-`step` rows and replaces\n * it with a connecting mark on the rest, joining them into one block.\n * Comparison is `===`; omit it to draw every row on its own line as before.\n */\n step?: string | number;\n /**\n * Arbitrary caller data, opaque to the card. Carried onto the row (and,\n * for `call`/`expect` events, the resulting span/pending message) and\n * echoed back verbatim in `onHoverChanged` / `onItemClicked` for that\n * target — so the caller does not need a side table to recover context\n * (e.g. which domain object a row/span id stands for) on every hover or\n * click. Not interpreted or serialised specially by the card.\n */\n meta?: unknown;\n};\n\n/** A service became known. Lanes referenced by calls are also added implicitly. */\nexport type SwimlaneLaneEvent = SwimlaneEventBase & {\n type: \"lane\";\n lane: string;\n /** Display name (defaults to `lane`). */\n label?: string;\n /**\n * Extra class(es) added to this lane's activity bar (the `<g className=\"swl-act\">`\n * drawn on the lifeline while the lane is handling a call), alongside the\n * default `swl-act`/highlight classes. Use this to give different lane\n * *types* their own themed colour via CSS (e.g. `.swl-act-tool rect {\n * fill: var(--my-tool-color); }`) instead of hard-coding colours per lane.\n * Most recent `lane` event for a lane wins, same as `label`/`meta`.\n */\n activityClassName?: string;\n /**\n * Inline style merged onto the activity bar's `<rect>` (fill) and `<path>`\n * (border) elements, for one-off colours that don't warrant a CSS class.\n * Takes precedence over `activityClassName`'s rules for any property it\n * sets. Most recent `lane` event for a lane wins, same as `label`/`meta`.\n */\n activityStyle?: React.CSSProperties;\n /**\n * When `false`, this event still registers the lane (and updates its\n * label/meta/activity style exactly as usual) but produces no row — as if\n * the lane had been present from the start via `createSwimlaneModel({lanes})`.\n * Only has an effect the first time a lane is seen: a later `lane` event\n * for an already-known lane never produces a row regardless of\n * `announce` (same as today), so there is no way to retroactively force a\n * \"joined\" row to appear for a lane once it is known. Default `true`.\n */\n announce?: boolean;\n};\n\n/** A service changed its run state. */\nexport type SwimlaneStateEvent = SwimlaneEventBase & {\n type: \"state\";\n lane: string;\n state: SwimlaneRunState;\n /** Draw the \"→ state\" text beside the dot. Default `true`. */\n showLabel?: boolean;\n};\n\n/** A message between two lanes (or a lane and itself). */\nexport type SwimlaneCallEvent = SwimlaneEventBase & {\n type: \"call\";\n /** Unique id; replies / `done` refer to it. */\n id: string;\n kind: SwimlaneCallKind;\n from: string;\n to: string;\n label: string;\n /** For `sync`: when the expected reply becomes overdue (ms after `ts`). */\n timeoutMs?: number;\n /**\n * Id of the call whose processing caused this call (like a trace's parent\n * span id). When omitted it is inferred at ingest time as the innermost\n * activity open on the `from` lane — exact for sequential processing, a\n * best guess when one service handles several requests concurrently.\n */\n parentId?: string;\n};\n\n/** Reply to an earlier `sync` call (drawn from callee back to caller). */\nexport type SwimlaneReplyEvent = SwimlaneEventBase & {\n type: \"reply\";\n /** Id of the originating call. */\n id: string;\n ok: boolean;\n label: string;\n};\n\n/** Processing of an earlier `async` call finished (closes the activity). */\nexport type SwimlaneDoneEvent = SwimlaneEventBase & {\n type: \"done\";\n id: string;\n};\n\n/**\n * Announces a message that is KNOWN to arrive later (from → to).\n * Shown as an outstanding ghost row until a real event with `fulfils: id`\n * arrives. Does not create a row itself.\n */\nexport type SwimlaneExpectEvent = SwimlaneEventBase & {\n type: \"expect\";\n id: string;\n from: string;\n to: string;\n label: string;\n timeoutMs?: number;\n};\n\nexport type SwimlaneEvent =\n | SwimlaneLaneEvent\n | SwimlaneStateEvent\n | SwimlaneCallEvent\n | SwimlaneReplyEvent\n | SwimlaneDoneEvent\n | SwimlaneExpectEvent;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Model (lives in the app's Redux state; plain JSON)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type SwimlaneLaneSnapshot = {\n state: SwimlaneRunState;\n /** Ids of calls currently being handled by this lane (stack order). */\n acts: string[];\n};\n\n/** Lane id → snapshot. A lane missing from the record does not exist (yet). */\nexport type SwimlaneLanesSnapshot = Record<string, SwimlaneLaneSnapshot>;\n\n/** A row event is any stream event except `expect` (which never makes a row). */\nexport type SwimlaneRowEvent = Exclude<SwimlaneEvent, SwimlaneExpectEvent> & {\n ts: number;\n};\n\n/**\n * One rendered transition. `pre` / `post` are the lane snapshots before and\n * after the event: the top half of the row is drawn from `pre`, the bottom\n * half from `post`.\n */\nexport type SwimlaneRow = {\n /**\n * The event's own `rowId` when it was set and did not collide with an\n * existing row; an internally assigned number otherwise. See\n * `SwimlaneEventBase.rowId`.\n */\n id: SwimlaneRowId;\n event: SwimlaneRowEvent;\n pre: SwimlaneLanesSnapshot;\n post: SwimlaneLanesSnapshot;\n /** Set when this event replaced an outstanding (expected) message. */\n fulfilled?: string;\n /**\n * For `reply` / `done` rows: the originating call, resolved at ingest time\n * so the row stays drawable after its span has been garbage-collected.\n */\n route?: {from: string; to: string; label: string};\n};\n\n/** An outstanding message projected below the \"now\" line. */\nexport type SwimlaneGhostRow = {\n id: string;\n pending: SwimlanePending;\n pre: SwimlaneLanesSnapshot;\n post: SwimlaneLanesSnapshot;\n};\n\n/** A message that is known to be coming. */\nexport type SwimlanePending = {\n id: string;\n /** `reply` = implied by a sync call; `expect` = announced explicitly. */\n type: \"reply\" | \"expect\";\n from: string;\n to: string;\n label: string;\n since: number;\n timeoutMs?: number;\n /** Copied from the originating `call` (implied reply) or `expect` event. */\n meta?: unknown;\n};\n\n/** Lifecycle of a call, used for tooltips and hover payloads. */\nexport type SwimlaneSpan = {\n id: string;\n kind: SwimlaneCallKind;\n from: string;\n to: string;\n label: string;\n start: number;\n end?: number;\n status: \"open\" | \"ok\" | \"error\" | \"done\";\n result?: string;\n /** Call whose processing caused this one (explicit `parentId` or inferred). */\n parent?: string;\n /** Copied from the originating `call` event. */\n meta?: unknown;\n};\n\nexport type SwimlaneModel = {\n /** Lane ids in display (arrival) order. */\n laneOrder: string[];\n /** Optional display names. */\n laneLabels: Record<string, string>;\n /** Caller `meta` from each lane's `lane` event(s), most recent wins. */\n laneMeta: Record<string, unknown>;\n /** `activityClassName` from each lane's `lane` event(s)/seed, most recent wins. */\n laneActivityClassName: Record<string, string>;\n /** `activityStyle` from each lane's `lane` event(s)/seed, most recent wins. */\n laneActivityStyle: Record<string, React.CSSProperties>;\n /** Current snapshot (== `post` of the last row). */\n current: SwimlaneLanesSnapshot;\n rows: SwimlaneRow[];\n pending: SwimlanePending[];\n spans: Record<string, SwimlaneSpan>;\n /** Last assigned row id. */\n seq: number;\n /** Ring-buffer size for `rows`. */\n maxRows: number;\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Card props & events\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type SwimlaneProps = {\n /** The model to render — usually a state selector `(s) => s.swimlane`. */\n model: SwimlaneModel;\n\n /** Show outstanding messages below the \"now\" line. Default `true`. */\n showPending?: boolean;\n\n /**\n * Keep the newest row in view while the user is at the bottom of the\n * scroll container. Scrolling up pauses following. Default `true`.\n */\n autoFollow?: boolean;\n\n /** Show the built-in hover tooltip. Default `true`. */\n showTooltip?: boolean;\n\n /**\n * Highlight a call chain (call, activity, reply, outstanding reply) by id,\n * in addition to whatever the pointer is hovering.\n */\n highlightId?: string;\n\n /** Horizontal distance between lifelines in px. Default 104. */\n laneWidth?: number;\n /** Height of each transition row in px. Default 30. */\n rowHeight?: number;\n /** Height of the header holding the vertical lane names. Default 130. */\n headerHeight?: number;\n /** Width of the left timestamp column in px. Default 92. */\n gutterWidth?: number;\n /** `top` offset for the sticky header (e.g. height of a navbar). Default 0. */\n stickyTop?: number;\n\n /**\n * Clock (epoch ms) used for \"waiting …\" timers and overdue detection of\n * outstanding messages. When omitted the card ticks its own wall clock\n * (4×/s, only while something is outstanding). Pass it to drive the card\n * entirely from props — e.g. for replaying a recorded trace or for tests.\n */\n now?: number;\n\n /**\n * Formats the timestamp column (`ts`, epoch ms). Defaults to `formatTs`\n * from `swimlane.model` (local wall-clock `HH:MM:SS.mmm`). Override to\n * show a different clock — e.g. a virtual time derived from `ts`, or both\n * virtual and wall-clock time in one string.\n */\n formatTs?: (ts: number) => string;\n\n /**\n * Formats the \"waiting …\" duration (ms) shown on outstanding messages\n * below the \"now\" line. Defaults to `${(ms / 1000).toFixed(1)}s`.\n */\n formatWait?: (ms: number) => string;\n\n className?: string;\n /** Inline styles for the card's root element, alongside `className`. */\n style?: React.CSSProperties;\n};\n\n/** What the pointer is over. */\nexport type SwimlaneTargetKind = \"transition\" | \"activity\" | \"state\" | \"pending\" | \"step\" | \"lane\";\n\nexport type SwimlaneTarget = {\n kind: SwimlaneTargetKind;\n /**\n * Call id (`transition`/`activity`/`pending`), `state-<rowId>` (`state`),\n * the row's `step` value stringified (`step`), or the lane id (`lane`).\n */\n id: string;\n lane?: string;\n rowId?: SwimlaneRowId;\n};\n\nexport type SwimlaneHoverChangedEvent = {\n /** New hover target, or `null` when the pointer left all targets. */\n target: SwimlaneTarget | null;\n /** Target that was hovered before, if any. */\n previous: SwimlaneTarget | null;\n /** Span details for the new target (when it refers to a call). */\n span?: SwimlaneSpan;\n /** Outstanding message details when `target.kind === \"pending\"`. */\n pending?: SwimlanePending;\n /**\n * Calls made while handling the hovered call (its direct children). Their\n * call and reply transitions are highlighted as well.\n */\n related?: string[];\n /**\n * For a hovered transition: call id of the caller-side process (activity)\n * that sent the call and receives its reply. That activity is highlighted.\n */\n process?: string;\n /** For `target.kind === \"step\"`: every row belonging to that step. */\n steps?: SwimlaneRow[];\n /**\n * Caller `meta` for the target, if any was set on the originating event:\n * the `call`'s `meta` for `transition`/`activity`/`pending`, the `state`\n * event's `meta` for `state`, the `lane` event's `meta` for `lane`. Not\n * set for `step` (see `steps`, which carries each row's own event/meta).\n */\n meta?: unknown;\n clientX?: number;\n clientY?: number;\n};\n\nexport type SwimlaneItemClickedEvent = {\n target: SwimlaneTarget;\n span?: SwimlaneSpan;\n pending?: SwimlanePending;\n related?: string[];\n process?: string;\n /** For `target.kind === \"step\"`: every row belonging to that step. */\n steps?: SwimlaneRow[];\n /** See `SwimlaneHoverChangedEvent.meta`. */\n meta?: unknown;\n};\n\nexport type SwimlaneEvents = {\n onHoverChanged: SwimlaneHoverChangedEvent;\n onItemClicked: SwimlaneItemClickedEvent;\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Data-action payloads\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type SwimlaneEventsReceivedEvent = {\n /** Which model to update (apps may show several swimlanes). */\n modelId: string;\n events: SwimlaneEvent[];\n};\n\nexport type SwimlaneRowsClearedEvent = {\n modelId: string;\n};\n\nexport const DEF_LANE_WIDTH = 104;\nexport const DEF_ROW_HEIGHT = 30;\nexport const DEF_HEADER_HEIGHT = 130;\nexport const DEF_GUTTER_WIDTH = 92;\nexport const DEF_MAX_ROWS = 2000;\n"],"mappings":";;AAYA,IAAa,IAAgB,iBAEhB,IAAW,EACtB,CACF,GAMa,IAAkB,EAAgB,GAAe,CAC5D,iBACA,cACF,CAAC,GAEY,IAAyB,EACpC,EAAgB,aAClB,GAEa,IAAwB,EACnC,EAAgB,YAClB,GAWa,IAAuB,EAAgB,GAAG,EAAc,QAAQ,CAC3E,mBACA,cACF,CAAC,GAEY,IACX,EACE,EAAqB,eACvB,GACW,IACX,EAA2C,EAAqB,YAAY,GAEjE,IACX,EACE,EAAqB,eACvB,GACW,IAAwB,EACnC,EAAqB,YACvB,GAuaa,IAAiB,KACjB,IAAiB,IACjB,IAAoB,KACpB,IAAmB,IACnB,IAAe"}