@elabs-ai/components-process 4.1.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/dist/core/index.d.ts +801 -3
- package/dist/core/index.js +1334 -0
- package/dist/core/index.js.map +1 -1
- package/dist/index.d.ts +1889 -34
- package/dist/index.js +5512 -196
- package/dist/index.js.map +1 -1
- package/dist/test/index.d.ts +223 -5
- package/dist/test/index.js +346 -191
- package/dist/test/index.js.map +1 -1
- package/package.json +14 -13
- package/src/__contract__/case-table.contract.test.tsx +49 -0
- package/src/__contract__/compare-kpi-strip.contract.test.tsx +49 -0
- package/src/__contract__/conformance-overlay.contract.test.tsx +49 -0
- package/src/__contract__/happy-path-editor.contract.test.tsx +49 -0
- package/src/__contract__/process-kpi-strip.contract.test.tsx +49 -0
- package/src/__contract__/violation-list.contract.test.tsx +49 -0
- package/src/abstraction-controls/abstraction-controls-per-type.test.tsx +80 -0
- package/src/abstraction-controls/abstraction-controls.stories.tsx +43 -1
- package/src/abstraction-controls/abstraction-controls.tsx +198 -5
- package/src/case-table/case-table.stories.tsx +89 -0
- package/src/case-table/case-table.test.tsx +148 -0
- package/src/case-table/case-table.tsx +144 -0
- package/src/case-table/columns.ts +116 -0
- package/src/case-table/index.ts +11 -0
- package/src/case-timeline/case-timeline-model.test.ts +72 -0
- package/src/case-timeline/case-timeline-model.ts +112 -0
- package/src/case-timeline/case-timeline.stories.tsx +94 -0
- package/src/case-timeline/case-timeline.test.tsx +51 -0
- package/src/case-timeline/case-timeline.tsx +109 -0
- package/src/case-timeline/index.ts +9 -0
- package/src/conformance-overlay/conformance-fixture.ts +59 -0
- package/src/conformance-overlay/conformance-legend.tsx +109 -0
- package/src/conformance-overlay/conformance-overlay.stories.tsx +116 -0
- package/src/conformance-overlay/conformance-overlay.test.tsx +88 -0
- package/src/conformance-overlay/conformance-overlay.tsx +107 -0
- package/src/conformance-overlay/conformance-state.test.ts +79 -0
- package/src/conformance-overlay/conformance-state.ts +220 -0
- package/src/conformance-overlay/index.ts +4 -0
- package/src/core/activity-color-scale.test.ts +107 -0
- package/src/core/activity-color-scale.ts +133 -0
- package/src/core/adapters/ocel.test.ts +112 -0
- package/src/core/adapters/ocel.ts +359 -0
- package/src/core/adapters/xes.test.ts +293 -0
- package/src/core/adapters/xes.ts +384 -0
- package/src/core/cases-from-log.test.ts +72 -0
- package/src/core/cases-from-log.ts +85 -0
- package/src/core/conformance.test.ts +80 -0
- package/src/core/conformance.ts +91 -0
- package/src/core/diff-graphs.test.ts +151 -0
- package/src/core/diff-graphs.ts +118 -0
- package/src/core/discover-object-centric-graph.test.ts +94 -0
- package/src/core/discover-object-centric-graph.ts +296 -0
- package/src/core/fixtures/ocel-sample.ts +82 -0
- package/src/core/fixtures/sample.xes +68 -0
- package/src/core/index.ts +113 -0
- package/src/core/reference-model.test.ts +43 -0
- package/src/core/reference-model.ts +116 -0
- package/src/core/replay-timeline.test.ts +161 -0
- package/src/core/replay-timeline.ts +260 -0
- package/src/core/segments.test.ts +185 -0
- package/src/core/segments.ts +153 -0
- package/src/core/token-replay.test.ts +218 -0
- package/src/core/token-replay.ts +456 -0
- package/src/core/types.ts +2 -2
- package/src/dotted-chart/compute-dots.test.ts +176 -0
- package/src/dotted-chart/compute-dots.ts +241 -0
- package/src/dotted-chart/dotted-chart-labels.ts +93 -0
- package/src/dotted-chart/dotted-chart.stories.tsx +182 -0
- package/src/dotted-chart/dotted-chart.test.tsx +135 -0
- package/src/dotted-chart/dotted-chart.tsx +841 -0
- package/src/dotted-chart/index.ts +23 -0
- package/src/dotted-chart/use-element-size.ts +33 -0
- package/src/happy-path-editor/happy-path-editor-context.ts +81 -0
- package/src/happy-path-editor/happy-path-editor.stories.tsx +116 -0
- package/src/happy-path-editor/happy-path-editor.test.tsx +142 -0
- package/src/happy-path-editor/happy-path-editor.tsx +239 -0
- package/src/happy-path-editor/happy-path-step-node.tsx +175 -0
- package/src/happy-path-editor/index.ts +4 -0
- package/src/index.ts +51 -1
- package/src/performance-spectrum/aggregate-segments.test.ts +107 -0
- package/src/performance-spectrum/aggregate-segments.ts +174 -0
- package/src/performance-spectrum/index.ts +25 -0
- package/src/performance-spectrum/performance-spectrum-context.tsx +116 -0
- package/src/performance-spectrum/performance-spectrum.stories.tsx +128 -0
- package/src/performance-spectrum/performance-spectrum.test.tsx +190 -0
- package/src/performance-spectrum/performance-spectrum.tsx +870 -0
- package/src/process-compare/compare-kpi-strip.stories.tsx +48 -0
- package/src/process-compare/compare-kpi-strip.tsx +94 -0
- package/src/process-compare/compare-model.ts +83 -0
- package/src/process-compare/compare-side.tsx +42 -0
- package/src/process-compare/diff-to-graph.ts +104 -0
- package/src/process-compare/index.ts +23 -0
- package/src/process-compare/process-compare.stories.tsx +184 -0
- package/src/process-compare/process-compare.test.tsx +224 -0
- package/src/process-compare/process-compare.tsx +251 -0
- package/src/process-explorer.stories.tsx +1 -1
- package/src/process-filter-bar/index.ts +2 -0
- package/src/process-filter-bar/process-filter-bar.stories.tsx +156 -0
- package/src/process-filter-bar/process-filter-bar.test.tsx +201 -0
- package/src/process-filter-bar/process-filter-bar.tsx +167 -0
- package/src/process-kpi-strip/process-kpi-strip.stories.tsx +47 -0
- package/src/process-kpi-strip/process-kpi-strip.test.tsx +67 -0
- package/src/process-kpi-strip/process-kpi-strip.tsx +148 -8
- package/src/process-map/activity-accent.ts +25 -0
- package/src/process-map/index.ts +1 -0
- package/src/process-map/map-model.test.ts +16 -0
- package/src/process-map/map-model.ts +323 -1
- package/src/process-map/object-centric-map.test.tsx +132 -0
- package/src/process-map/process-activity-node.tsx +152 -14
- package/src/process-map/process-map-object-centric.stories.tsx +219 -0
- package/src/process-map/process-map.stories.tsx +64 -0
- package/src/process-map/process-map.tsx +240 -16
- package/src/process-map/process-transition-edge.test.tsx +47 -0
- package/src/process-map/process-transition-edge.tsx +134 -7
- package/src/process-map/use-process-layout.ts +30 -9
- package/src/process-replay/congestion-heat.tsx +107 -0
- package/src/process-replay/index.ts +14 -0
- package/src/process-replay/process-replay.stories.tsx +168 -0
- package/src/process-replay/process-replay.test.tsx +170 -0
- package/src/process-replay/process-replay.tsx +285 -0
- package/src/process-replay/replay-controls.tsx +147 -0
- package/src/process-replay/replay-format.ts +83 -0
- package/src/process-replay/replay-tokens-context.ts +30 -0
- package/src/process-replay/use-controllable-value.ts +30 -0
- package/src/templates-process-explorer.stories.tsx +1304 -0
- package/src/test/contract.test.ts +66 -0
- package/src/test/contract.ts +107 -6
- package/src/test/doubles.test.tsx +87 -1
- package/src/test/doubles.tsx +174 -3
- package/src/test/index.ts +25 -1
- package/src/use-process-explorer/use-process-explorer.test.ts +44 -0
- package/src/use-process-explorer/use-process-explorer.ts +34 -2
- package/src/variant-explorer/coverage-bar.tsx +36 -0
- package/src/variant-explorer/index.ts +16 -0
- package/src/variant-explorer/sequence-chips.tsx +103 -0
- package/src/variant-explorer/variant-explorer-model.ts +42 -0
- package/src/variant-explorer/variant-explorer.stories.tsx +226 -0
- package/src/variant-explorer/variant-explorer.test.tsx +302 -0
- package/src/variant-explorer/variant-explorer.tsx +567 -0
- package/src/variant-explorer/variant-row.tsx +137 -0
- package/src/violation-list/index.ts +2 -0
- package/src/violation-list/violation-list.stories.tsx +73 -0
- package/src/violation-list/violation-list.test.tsx +84 -0
- package/src/violation-list/violation-list.tsx +259 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { Node, Edge, NodeProps, EdgeProps, XYPosition } from '@xyflow/react';
|
|
2
1
|
import * as react from 'react';
|
|
3
|
-
import { HTMLAttributes, KeyboardEvent } from 'react';
|
|
4
|
-
import {
|
|
2
|
+
import { CSSProperties, HTMLAttributes, KeyboardEvent, ReactNode } from 'react';
|
|
3
|
+
import { Node, Edge, NodeProps, EdgeProps, XYPosition } from '@xyflow/react';
|
|
4
|
+
import { LucideIcon } from 'lucide-react';
|
|
5
|
+
import { FlowLayoutDirection, FlowEdgeToken } from '@elabs-ai/components-flow';
|
|
6
|
+
import { ColumnDef } from '@elabs-ai/components-data';
|
|
7
|
+
import { LocaleContextValue } from '@elabs-ai/components-ui';
|
|
5
8
|
|
|
6
9
|
/**
|
|
7
10
|
* The framework-free event-log and process-graph model — RM-049.
|
|
@@ -12,8 +15,8 @@ import { FlowLayoutDirection } from '@elabs-ai/components-flow';
|
|
|
12
15
|
* additive: a required field added here is a breaking change for five items at once.
|
|
13
16
|
*
|
|
14
17
|
* NOTHING in this module — or anywhere under `src/core/` — may import React, React Flow,
|
|
15
|
-
* visx, d3 or an `@elabs-ai/components-*` package. See `.claude/rules/
|
|
16
|
-
* and `pnpm process
|
|
18
|
+
* visx, d3 or an `@elabs-ai/components-*` package. See `.claude/rules/data.md` ("Process
|
|
19
|
+
* mining" section) and `pnpm check --rule process-reuse`.
|
|
17
20
|
*/
|
|
18
21
|
/**
|
|
19
22
|
* One raw row of an event log, before normalization.
|
|
@@ -133,6 +136,380 @@ type FrequencyMode = "absolute" | "absolute_case" | "relative" | "relative_case"
|
|
|
133
136
|
/** Which member of a {@link DurationStats} a performance view reads. */
|
|
134
137
|
type PerformanceAgg = "median" | "mean" | "min" | "max" | "sum" | "p90" | "trimmed_mean";
|
|
135
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Activity colour scale — RM-054.
|
|
141
|
+
*
|
|
142
|
+
* One activity, one colour, across every process view. `ProcessMap` paints the colour as
|
|
143
|
+
* a small accent mark on the activity node; `VariantExplorer` paints it on the sequence
|
|
144
|
+
* chips. Both read the SAME scale instance built from one graph, so "Create Order" is the
|
|
145
|
+
* same swatch in the map and in the variant list.
|
|
146
|
+
*
|
|
147
|
+
* ## The colour budget
|
|
148
|
+
*
|
|
149
|
+
* The chart palette ships twelve series tokens (`--chart-1` … `--chart-12`). The eleven
|
|
150
|
+
* most frequent activities (ranked by the number of cases they occur in) take
|
|
151
|
+
* `--chart-1` … `--chart-11`; every remaining activity shares `--chart-12` and is flagged
|
|
152
|
+
* `pattern: "other"`, which the views render as a hatch so "other" never reads as a
|
|
153
|
+
* twelfth distinct activity. Colour is never the only channel: every view that paints a
|
|
154
|
+
* swatch also prints the activity label (or its two-letter {@link ActivityColorScale.codeFor}
|
|
155
|
+
* code) as text.
|
|
156
|
+
*
|
|
157
|
+
* Pure and framework-free: returns token NAMES, never resolved colours, so a theme switch
|
|
158
|
+
* re-inks every swatch with no recomputation.
|
|
159
|
+
*/
|
|
160
|
+
|
|
161
|
+
/** How many activities get a distinct palette slot before the rest share "other". */
|
|
162
|
+
declare const ACTIVITY_COLOR_SLOTS = 11;
|
|
163
|
+
/** The token every activity outside the top {@link ACTIVITY_COLOR_SLOTS} shares. */
|
|
164
|
+
declare const ACTIVITY_OTHER_TOKEN = "--chart-12";
|
|
165
|
+
/** The colour one activity is painted with. */
|
|
166
|
+
interface ActivityColor {
|
|
167
|
+
/** A CSS custom-property NAME, e.g. `"--chart-3"`. Paint with `var(${token})`. */
|
|
168
|
+
token: string;
|
|
169
|
+
/** Present for the shared "other" bucket — render the hatch, not a flat swatch. */
|
|
170
|
+
pattern?: "other";
|
|
171
|
+
}
|
|
172
|
+
/** One legend entry, in rank order. */
|
|
173
|
+
interface ActivityColorLegendEntry extends ActivityColor {
|
|
174
|
+
activityId: string;
|
|
175
|
+
label: string;
|
|
176
|
+
/** A two-character code unique within the scale, for abbreviated ("DNA strip") chips. */
|
|
177
|
+
code: string;
|
|
178
|
+
}
|
|
179
|
+
/** The shared activity→colour mapping. */
|
|
180
|
+
interface ActivityColorScale {
|
|
181
|
+
/** The colour for an activity. An id the graph never contained is "other". */
|
|
182
|
+
colorFor(activityId: string): ActivityColor;
|
|
183
|
+
/** The two-character code for an activity; derived from the id when it is unknown. */
|
|
184
|
+
codeFor(activityId: string): string;
|
|
185
|
+
/** The activity's display label; the id itself when it is unknown. */
|
|
186
|
+
labelFor(activityId: string): string;
|
|
187
|
+
/** Every activity in the graph, ranked by case count descending, ties by id. */
|
|
188
|
+
legend: ActivityColorLegendEntry[];
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Build the shared colour scale for a graph.
|
|
192
|
+
*
|
|
193
|
+
* Deterministic: the same graph always yields the same assignment, regardless of the
|
|
194
|
+
* order `graph.activities` arrives in. Build it from the FULL (unfiltered, unabstracted)
|
|
195
|
+
* graph so colours stay put while a reader filters or abstracts.
|
|
196
|
+
*/
|
|
197
|
+
declare function activityColorScale(graph: ProcessGraph): ActivityColorScale;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* How an activity's identity colour is painted (RM-054).
|
|
201
|
+
*
|
|
202
|
+
* The ONE place that turns an {@link ActivityColor} into CSS, shared by
|
|
203
|
+
* `ProcessActivityNode`'s accent swatch and `VariantExplorer`'s sequence chips — so the
|
|
204
|
+
* two views cannot drift into painting the same activity differently. Both endpoints are
|
|
205
|
+
* semantic tokens; no literal colour is authored.
|
|
206
|
+
*
|
|
207
|
+
* The shared "other" bucket is a diagonal hatch over a light wash of the same token, so
|
|
208
|
+
* it reads as "one of many" in greyscale too, never as a twelfth distinct activity.
|
|
209
|
+
*/
|
|
210
|
+
|
|
211
|
+
/** Inline style for an accent swatch painted with `color`. */
|
|
212
|
+
declare function activityAccentStyle(color: ActivityColor): CSSProperties;
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Event-log normalization — RM-049.
|
|
216
|
+
*
|
|
217
|
+
* Turns a flat `EventRow[]` into per-case traces of INSTANCES: one entry per real
|
|
218
|
+
* activity execution, carrying a resolved `start` and `end` in epoch milliseconds. Every
|
|
219
|
+
* other module in `/core` consumes the normalized form, so the messy parts of a raw log
|
|
220
|
+
* (three timestamp encodings, lifecycle rows split across two lines, rows arriving out of
|
|
221
|
+
* order) are handled exactly once, here.
|
|
222
|
+
*
|
|
223
|
+
* Deterministic: same rows in, same traces out. No `Date.now()`, no randomness.
|
|
224
|
+
*/
|
|
225
|
+
|
|
226
|
+
/** One activity execution, with both ends resolved to epoch milliseconds. */
|
|
227
|
+
interface NormalizedEvent {
|
|
228
|
+
activity: string;
|
|
229
|
+
/**
|
|
230
|
+
* Start of the execution. Equals `end` for an atomic event — an event with no
|
|
231
|
+
* `lifecycle` pair and no `startTimestamp` has no observed duration, and inventing one
|
|
232
|
+
* would put fabricated numbers into every downstream statistic.
|
|
233
|
+
*/
|
|
234
|
+
start: number;
|
|
235
|
+
/** Completion of the execution. */
|
|
236
|
+
end: number;
|
|
237
|
+
/** `end - start`, never negative (a clock-skewed pair is floored at 0). */
|
|
238
|
+
duration: number;
|
|
239
|
+
resource?: string;
|
|
240
|
+
attributes?: Record<string, string | number | boolean | null>;
|
|
241
|
+
/**
|
|
242
|
+
* True when this instance came from a `lifecycle: "start"` row that never got a
|
|
243
|
+
* matching `"complete"`. Its `end` is provisional (it equals `start`), so a performance
|
|
244
|
+
* view can choose to exclude it.
|
|
245
|
+
*/
|
|
246
|
+
isOpen: boolean;
|
|
247
|
+
}
|
|
248
|
+
/** One case (process instance): its trace, plus the case's own extent. */
|
|
249
|
+
interface NormalizedCase {
|
|
250
|
+
caseId: string;
|
|
251
|
+
/** Instances in ascending `start` order. Never empty. */
|
|
252
|
+
events: NormalizedEvent[];
|
|
253
|
+
/** Earliest `start` in the trace. */
|
|
254
|
+
start: number;
|
|
255
|
+
/** Latest `end` in the trace. */
|
|
256
|
+
end: number;
|
|
257
|
+
/** `end - start` — the case's throughput time. */
|
|
258
|
+
duration: number;
|
|
259
|
+
/** Per-case attributes carried over from `EventLog.caseAttributes`, when present. */
|
|
260
|
+
attributes?: Record<string, unknown>;
|
|
261
|
+
}
|
|
262
|
+
/** A normalized log: cases in first-appearance order, plus totals. */
|
|
263
|
+
interface NormalizedLog {
|
|
264
|
+
cases: NormalizedCase[];
|
|
265
|
+
totals: {
|
|
266
|
+
cases: number;
|
|
267
|
+
events: number;
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
/** A log in either shape. Every derivation entry point accepts both. */
|
|
271
|
+
type AnyLog = EventLog | NormalizedLog;
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Reference model — RM-061.
|
|
275
|
+
*
|
|
276
|
+
* A HAPPY PATH (the prescribed sequence of activities an owner or auditor expects) lifted
|
|
277
|
+
* to the smallest workflow-net-like structure token replay can run against: one place
|
|
278
|
+
* between consecutive steps, one visible transition per step, a silent SKIP transition
|
|
279
|
+
* beside every optional step and a SELF-LOOP transition after every repeatable one.
|
|
280
|
+
*
|
|
281
|
+
* Scope boundary (analysis §9 risk 2): this is deliberately NOT a general Petri-net
|
|
282
|
+
* importer. No BPMN, no parallel gateways, no alignments beyond skip/repeat. A host that
|
|
283
|
+
* needs full alignment-based conformance brings a backend; this module never grows one.
|
|
284
|
+
*
|
|
285
|
+
* Framework-free, deterministic: no React, no `@elabs-ai/components-*` import.
|
|
286
|
+
*/
|
|
287
|
+
/** One prescribed step of a happy path. */
|
|
288
|
+
interface HappyPathStep {
|
|
289
|
+
/** Activity name, matched exactly against `EventRow.activity`. */
|
|
290
|
+
activity: string;
|
|
291
|
+
/** The step may be left out without a deviation (a silent skip arc is added). */
|
|
292
|
+
optional?: boolean;
|
|
293
|
+
/** The step may run several times in a row without a deviation (a self-loop is added). */
|
|
294
|
+
repeatable?: boolean;
|
|
295
|
+
}
|
|
296
|
+
/** A prescribed process: an ordered list of steps. */
|
|
297
|
+
interface HappyPath {
|
|
298
|
+
id: string;
|
|
299
|
+
label: string;
|
|
300
|
+
steps: HappyPathStep[];
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Token-based replay — RM-061.
|
|
305
|
+
*
|
|
306
|
+
* Replays each case of an event log against a {@link ReplayModel} (a lifted happy path)
|
|
307
|
+
* and scores it with the classic produced / consumed / missing / remaining token counts:
|
|
308
|
+
*
|
|
309
|
+
* fitness = ½ · (1 − missing / consumed) + ½ · (1 − remaining / produced)
|
|
310
|
+
*
|
|
311
|
+
* The replay procedure — seed the initial marking, fire an enabled transition per event,
|
|
312
|
+
* enable a disabled one through silent transitions first, force-insert missing tokens
|
|
313
|
+
* only when that fails, then consume the final marking and count what is left over —
|
|
314
|
+
* follows the token-based replay algorithm published in pm4js (BSD-3-Clause, credited in
|
|
315
|
+
* `scripts/attributions.sources.json`). It is re-typed in TypeScript for the restricted
|
|
316
|
+
* nets `liftHappyPath` builds; no pm4js code is copied, and nothing here derives from the
|
|
317
|
+
* AGPL Python reference implementation.
|
|
318
|
+
*
|
|
319
|
+
* Deviation typing is this module's own layer on top of the counts: every forced token
|
|
320
|
+
* (and every unreachable final token) is explained by at least one
|
|
321
|
+
* {@link Deviation}, so a violation list can say WHY a case lost fitness.
|
|
322
|
+
*
|
|
323
|
+
* Scope boundary (analysis §9 risk 2): no alignment search. Replay is greedy and
|
|
324
|
+
* single-pass per trace.
|
|
325
|
+
*
|
|
326
|
+
* Framework-free, deterministic: no React, no `@elabs-ai/components-*` import.
|
|
327
|
+
*/
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Why a case lost fitness.
|
|
331
|
+
*
|
|
332
|
+
* - `undesired` — the activity is not in the model at all.
|
|
333
|
+
* - `skipped` — a required modelled activity was jumped over and never observed in the case.
|
|
334
|
+
* - `wrongOrder` — the activity is modelled but its preceding place was unmarked, and the
|
|
335
|
+
* gap is not explained by an unobserved step (it ran too early, too late, or again).
|
|
336
|
+
* - `wrongStart` — the first event of the case is not one the initial marking enables.
|
|
337
|
+
* - `incomplete` — the case ended before reaching the model's final marking.
|
|
338
|
+
*/
|
|
339
|
+
type DeviationType = "undesired" | "skipped" | "wrongOrder" | "wrongStart" | "incomplete";
|
|
340
|
+
/** One deviation found while replaying a case. */
|
|
341
|
+
interface Deviation {
|
|
342
|
+
type: DeviationType;
|
|
343
|
+
/**
|
|
344
|
+
* The activity the deviation is about: the observed event for `undesired`/`wrongOrder`/
|
|
345
|
+
* `wrongStart`, the missing step for `skipped`, the last observed event for `incomplete`.
|
|
346
|
+
*/
|
|
347
|
+
activity?: string;
|
|
348
|
+
/** The activity the model expected next at that point, when one is determinable. */
|
|
349
|
+
expected?: string;
|
|
350
|
+
/**
|
|
351
|
+
* Zero-based index into the case's ordered trace of the event where the deviation was
|
|
352
|
+
* detected. `incomplete` uses the trace length (the position after the last event).
|
|
353
|
+
*/
|
|
354
|
+
at: number;
|
|
355
|
+
}
|
|
356
|
+
/** Replay result for one case. */
|
|
357
|
+
interface TraceReplayResult {
|
|
358
|
+
caseId: string;
|
|
359
|
+
produced: number;
|
|
360
|
+
consumed: number;
|
|
361
|
+
missing: number;
|
|
362
|
+
remaining: number;
|
|
363
|
+
/** `½(1 − missing/consumed) + ½(1 − remaining/produced)`, in `[0, 1]`. */
|
|
364
|
+
fitness: number;
|
|
365
|
+
deviations: Deviation[];
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Conformance model — RM-061.
|
|
370
|
+
*
|
|
371
|
+
* The log-level result of replaying an event log against a reference model
|
|
372
|
+
* ({@link ConformanceResult}, produced by `tokenReplay`) and the fitness-over-time series a
|
|
373
|
+
* KPI sparkline plots ({@link conformanceRateSeries}).
|
|
374
|
+
*
|
|
375
|
+
* Scope boundary (analysis §9 risk 2): token replay against a lifted happy path only — no
|
|
376
|
+
* alignments, no BPMN import. A host needing either brings a backend.
|
|
377
|
+
*
|
|
378
|
+
* Framework-free, deterministic: no React, no `Date.now()`, no `@elabs-ai/components-*`
|
|
379
|
+
* import.
|
|
380
|
+
*/
|
|
381
|
+
|
|
382
|
+
/** Log-level conformance of an event log against a reference model. */
|
|
383
|
+
interface ConformanceResult {
|
|
384
|
+
/** Mean trace fitness in `[0, 1]`; `0` for an empty log. */
|
|
385
|
+
overallFitness: number;
|
|
386
|
+
/** One result per case, in the log's case order. */
|
|
387
|
+
traces: TraceReplayResult[];
|
|
388
|
+
/** Total deviations per type across all cases; every type is present. */
|
|
389
|
+
deviationCounts: Record<DeviationType, number>;
|
|
390
|
+
/** Deviations charged to each activity. Sums to the total deviation count. */
|
|
391
|
+
perActivity: Record<string, {
|
|
392
|
+
deviations: number;
|
|
393
|
+
}>;
|
|
394
|
+
/**
|
|
395
|
+
* Deviations charged to each OBSERVED directly-follows edge, keyed
|
|
396
|
+
* `source + EDGE_KEY_SEPARATOR + target` — the same key `discoverGraph` gives the edge.
|
|
397
|
+
* Sums to at most the total deviation count.
|
|
398
|
+
*/
|
|
399
|
+
perEdge: Record<string, {
|
|
400
|
+
deviations: number;
|
|
401
|
+
}>;
|
|
402
|
+
}
|
|
403
|
+
/** One point of {@link conformanceRateSeries}. */
|
|
404
|
+
interface ConformanceRatePoint {
|
|
405
|
+
/** `YYYY-MM-DD` (day; for week, the UTC Monday that starts it) or `YYYY-MM` (month). */
|
|
406
|
+
bucket: string;
|
|
407
|
+
/** Mean fitness of the cases that started in this bucket. */
|
|
408
|
+
fitness: number;
|
|
409
|
+
caseCount: number;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Conformance states on the process map — RM-062.
|
|
414
|
+
*
|
|
415
|
+
* Reads a `ConformanceResult` (RM-061's `tokenReplay`) as the three-colour overlay the
|
|
416
|
+
* analysis names (§2): every activity and every observed transition is in the log AND the
|
|
417
|
+
* model (`"both"`), in the log only (`"logOnly"`), or expected by the model but missing
|
|
418
|
+
* from the log (`"modelOnly"`).
|
|
419
|
+
*
|
|
420
|
+
* ## How the state is derived — without the reference model in hand
|
|
421
|
+
*
|
|
422
|
+
* A `ConformanceResult` does not carry the model it was replayed against, and it does not
|
|
423
|
+
* need to: token replay charges an `undesired` deviation to EVERY observed event whose
|
|
424
|
+
* activity the model does not contain, so an observed activity is outside the model
|
|
425
|
+
* exactly when it carries an `undesired` deviation. The rules, in precedence order:
|
|
426
|
+
*
|
|
427
|
+
* | element | state | when |
|
|
428
|
+
* | ---------- | ------------ | ------------------------------------------------------------ |
|
|
429
|
+
* | activity | `logOnly` | at least one `undesired` deviation names it |
|
|
430
|
+
* | activity | `modelOnly` | at least one `skipped` deviation names it (cases jumped it) |
|
|
431
|
+
* | activity | `both` | otherwise |
|
|
432
|
+
* | transition | `logOnly` | deviations are charged to it, or either endpoint is `logOnly` |
|
|
433
|
+
* | transition | `both` | otherwise |
|
|
434
|
+
*
|
|
435
|
+
* A transition is never `modelOnly`: every edge on the map was observed. A model step
|
|
436
|
+
* that NO case ever reached is not on the graph at all, so it cannot be painted here —
|
|
437
|
+
* `ViolationList` still counts the cases that skipped it.
|
|
438
|
+
*
|
|
439
|
+
* ## Never colour alone (WCAG 1.4.1, analysis §5.4)
|
|
440
|
+
*
|
|
441
|
+
* Each state pairs a status tone with a distinct glyph AND a distinct line style —
|
|
442
|
+
* solid circle / hollow triangle / dashed square — so the three read apart in greyscale.
|
|
443
|
+
* {@link CONFORMANCE_STATE_ENCODING} is the one table every surface reads it from.
|
|
444
|
+
*/
|
|
445
|
+
|
|
446
|
+
/** Where an element sits relative to the reference model. */
|
|
447
|
+
type ConformanceState = "both" | "logOnly" | "modelOnly";
|
|
448
|
+
/** Every {@link ConformanceState}, in legend order. */
|
|
449
|
+
declare const CONFORMANCE_STATES: readonly ConformanceState[];
|
|
450
|
+
/** The status tone a state is painted with. */
|
|
451
|
+
type ConformanceTone = "success" | "warning" | "destructive";
|
|
452
|
+
/** The line style a state is drawn with — the second non-colour channel. */
|
|
453
|
+
type ConformanceDash = "solid" | "dotted" | "dashed";
|
|
454
|
+
/** Everything that encodes one state, colour included. */
|
|
455
|
+
interface ConformanceStateEncoding {
|
|
456
|
+
tone: ConformanceTone;
|
|
457
|
+
/** Stable glyph name, mirrored to `data-glyph` so a test can assert distinctness. */
|
|
458
|
+
glyph: "circle" | "triangle" | "square";
|
|
459
|
+
/** Lucide glyph drawn for the state. */
|
|
460
|
+
icon: LucideIcon;
|
|
461
|
+
/** Whether the glyph is filled (`true`) or an outline. */
|
|
462
|
+
filled: boolean;
|
|
463
|
+
dash: ConformanceDash;
|
|
464
|
+
/** SVG `stroke-dasharray` for a transition stroke; `undefined` keeps the edge's own. */
|
|
465
|
+
strokeDasharray: string | undefined;
|
|
466
|
+
/** Mark (fill-rung) utility for a glyph or swatch. */
|
|
467
|
+
markClass: string;
|
|
468
|
+
/** Ink (`-text` rung) utility for coloured text. */
|
|
469
|
+
textClass: string;
|
|
470
|
+
/** Border utilities: the tone's fill rung plus the line style. */
|
|
471
|
+
borderClass: string;
|
|
472
|
+
/** CSS colour reference for a stroke or a `--border` override. */
|
|
473
|
+
colorVar: string;
|
|
474
|
+
}
|
|
475
|
+
/** The single source of truth for how each state looks. */
|
|
476
|
+
declare const CONFORMANCE_STATE_ENCODING: Readonly<Record<ConformanceState, ConformanceStateEncoding>>;
|
|
477
|
+
/** The words for each state. Override through a component's `labels` to localize. */
|
|
478
|
+
interface ConformanceStateLabels {
|
|
479
|
+
both: string;
|
|
480
|
+
logOnly: string;
|
|
481
|
+
modelOnly: string;
|
|
482
|
+
/** The table twin's column header and the legend's title. */
|
|
483
|
+
column: string;
|
|
484
|
+
}
|
|
485
|
+
/** The shipped English words for each state. */
|
|
486
|
+
declare const CONFORMANCE_STATE_DEFAULT_LABELS: Readonly<ConformanceStateLabels>;
|
|
487
|
+
/** Per-element conformance states for one `ConformanceResult`. */
|
|
488
|
+
interface ConformanceStates {
|
|
489
|
+
/** Keyed by activity id. An activity absent here is `"both"`. */
|
|
490
|
+
activities: ReadonlyMap<string, ConformanceState>;
|
|
491
|
+
/**
|
|
492
|
+
* Keyed `source + EDGE_KEY_SEPARATOR + target` — the id `discoverGraph` and the map give
|
|
493
|
+
* the transition. A transition absent here is resolved by {@link transitionConformance}.
|
|
494
|
+
*/
|
|
495
|
+
transitions: ReadonlyMap<string, ConformanceState>;
|
|
496
|
+
}
|
|
497
|
+
/** Derive activity and transition states from a replay result. See this module's docblock. */
|
|
498
|
+
declare function resolveConformanceStates(conformance: ConformanceResult): ConformanceStates;
|
|
499
|
+
/** The state of one activity. */
|
|
500
|
+
declare function activityConformance(states: ConformanceStates, activity: string): ConformanceState;
|
|
501
|
+
/** The state of one observed transition. */
|
|
502
|
+
declare function transitionConformance(states: ConformanceStates, source: string, target: string): ConformanceState;
|
|
503
|
+
/**
|
|
504
|
+
* A map node with its conformance state folded in: `data.conformance` for the glyph and
|
|
505
|
+
* dash, `data-conformance` on React Flow's own node element (additive to
|
|
506
|
+
* `data-selection`), and the state's word appended to the accessible name — so the state
|
|
507
|
+
* reaches assistive technology as text, never as colour.
|
|
508
|
+
*/
|
|
509
|
+
declare function withActivityConformance(node: ProcessMapNode, states: ConformanceStates, labels?: ConformanceStateLabels): ProcessMapNode;
|
|
510
|
+
/** A map edge with its conformance state folded in. See {@link withActivityConformance}. */
|
|
511
|
+
declare function withTransitionConformance(edge: ProcessMapEdge, states: ConformanceStates, labels?: ConformanceStateLabels): ProcessMapEdge;
|
|
512
|
+
|
|
136
513
|
/**
|
|
137
514
|
* Rework detection — RM-050.
|
|
138
515
|
*
|
|
@@ -240,6 +617,83 @@ type FilterSpec =
|
|
|
240
617
|
ids: string[];
|
|
241
618
|
};
|
|
242
619
|
|
|
620
|
+
/** Options for {@link abstractGraph}. Both fractions are `0..1` and both are required. */
|
|
621
|
+
interface AbstractionOptions {
|
|
622
|
+
/** Fraction of activities to KEEP, `0..1`. At least one activity is always kept. */
|
|
623
|
+
activities: number;
|
|
624
|
+
/** Fraction of paths (transitions) to KEEP, `0..1`, over the kept-activity subgraph. */
|
|
625
|
+
paths: number;
|
|
626
|
+
/**
|
|
627
|
+
* Re-add whatever it takes to keep every kept activity reachable from a start activity
|
|
628
|
+
* and able to reach an end activity. Defaults to `true` — an island reads as a broken
|
|
629
|
+
* process, not a simplified one.
|
|
630
|
+
*/
|
|
631
|
+
keepConnected?: boolean;
|
|
632
|
+
/** Hide the MOST frequent instead of the least — the "what is rare here" view. */
|
|
633
|
+
invert?: boolean;
|
|
634
|
+
}
|
|
635
|
+
/** What {@link abstractGraph} returns: a `ProcessGraph` plus what it left out. */
|
|
636
|
+
interface AbstractedGraph extends ProcessGraph {
|
|
637
|
+
hidden: {
|
|
638
|
+
/** Activities present in the input graph and absent from this one. */
|
|
639
|
+
activities: number;
|
|
640
|
+
/** Transitions present in the input graph and absent from this one. */
|
|
641
|
+
paths: number;
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Object-centric directly-follows graph (OC-DFG) discovery — RM-066.
|
|
647
|
+
*
|
|
648
|
+
* An OC-DFG is one directly-follows graph PER OBJECT TYPE, drawn on one canvas: activities
|
|
649
|
+
* shared between types merge into a single node that keeps a per-type breakdown, while
|
|
650
|
+
* edges stay per type — an `order` following and an `item` following are different
|
|
651
|
+
* relations, so they are never summed into one arrow. The merge semantics (per-type
|
|
652
|
+
* projection, shared-activity join, per-type edges) follow pm4js's documented OC-DFG
|
|
653
|
+
* construction; see `ATTRIBUTION.md`. No pm4js code is copied, and nothing here derives
|
|
654
|
+
* from the AGPL Python reference implementation.
|
|
655
|
+
*
|
|
656
|
+
* Built entirely on `discoverGraph` and `abstractGraph`: every per-type number is exactly
|
|
657
|
+
* what the single-case pipeline would print for that type's projection.
|
|
658
|
+
*/
|
|
659
|
+
|
|
660
|
+
/** One object type's share of a merged activity. */
|
|
661
|
+
interface ObjectTypeActivityCounts {
|
|
662
|
+
/** Occurrences in that type's projection (one per event × referenced object). */
|
|
663
|
+
instances: number;
|
|
664
|
+
/** Distinct objects of that type the activity touches. */
|
|
665
|
+
cases: number;
|
|
666
|
+
}
|
|
667
|
+
/** A merged activity: shared across object types, with a per-type breakdown. */
|
|
668
|
+
interface ObjectCentricActivityStats extends Omit<ActivityStats, "instances" | "cases"> {
|
|
669
|
+
/**
|
|
670
|
+
* Distinct OCEL events of this activity across every type — an event that references an
|
|
671
|
+
* order and two items counts once. Falls back to the largest per-type `instances` when
|
|
672
|
+
* the logs carry no `__ocelEventId` (hand-built logs).
|
|
673
|
+
*/
|
|
674
|
+
events: number;
|
|
675
|
+
/** Object type → counts, only for the types this activity occurs in. */
|
|
676
|
+
perType: Record<string, ObjectTypeActivityCounts>;
|
|
677
|
+
}
|
|
678
|
+
/** An object-centric directly-follows graph. */
|
|
679
|
+
interface ObjectCentricGraph {
|
|
680
|
+
/** Merged activities, busiest (by `events`) first, ties by id. */
|
|
681
|
+
activities: ObjectCentricActivityStats[];
|
|
682
|
+
/** Object type → that type's own directly-follows edges. Never merged across types. */
|
|
683
|
+
transitionsByType: Record<string, TransitionStats[]>;
|
|
684
|
+
/** The object types, in the caller's order. */
|
|
685
|
+
objectTypes: string[];
|
|
686
|
+
/** Object type → the full per-type graph the merge was built from. */
|
|
687
|
+
graphsByType: Record<string, ProcessGraph>;
|
|
688
|
+
}
|
|
689
|
+
/** {@link abstractObjectCentricGraph}'s result — what each type's abstraction hid. */
|
|
690
|
+
interface AbstractedObjectCentricGraph extends ObjectCentricGraph {
|
|
691
|
+
hiddenByType: Record<string, {
|
|
692
|
+
activities: number;
|
|
693
|
+
paths: number;
|
|
694
|
+
}>;
|
|
695
|
+
}
|
|
696
|
+
|
|
243
697
|
/**
|
|
244
698
|
* map-model — the pure `ProcessGraph → React Flow nodes/edges` mapping (RM-051).
|
|
245
699
|
*
|
|
@@ -392,6 +846,22 @@ interface ProcessActivityNodeData extends Record<string, unknown> {
|
|
|
392
846
|
/** Repeat executions of this activity across the log; omitted when no rework data. */
|
|
393
847
|
reworkCount?: number;
|
|
394
848
|
selectionState: ProcessSelectionState;
|
|
849
|
+
/**
|
|
850
|
+
* The activity's identity colour from a shared `ActivityColorScale` (RM-054), painted as
|
|
851
|
+
* a small accent swatch — never the card fill, which would fight the metric reading.
|
|
852
|
+
* Absent when the map was given no `colorScale`.
|
|
853
|
+
*/
|
|
854
|
+
accent?: ActivityColor;
|
|
855
|
+
/**
|
|
856
|
+
* Where this activity sits against a reference model (RM-062). Set only when the map
|
|
857
|
+
* was given `conformance`; drives `data-conformance` plus its glyph and dash.
|
|
858
|
+
*/
|
|
859
|
+
conformance?: ConformanceState;
|
|
860
|
+
/**
|
|
861
|
+
* Object-centric — RM-066. One entry per object type this activity occurs in, in the
|
|
862
|
+
* graph's type order. Set only in object-centric mode; drives the per-type chips.
|
|
863
|
+
*/
|
|
864
|
+
objectTypes?: ProcessObjectTypeCount[];
|
|
395
865
|
}
|
|
396
866
|
/** `data` carried by every {@link ProcessMapEdge}. */
|
|
397
867
|
interface ProcessTransitionEdgeData extends Record<string, unknown> {
|
|
@@ -409,6 +879,32 @@ interface ProcessTransitionEdgeData extends Record<string, unknown> {
|
|
|
409
879
|
isSelfLoop: boolean;
|
|
410
880
|
isBackEdge: boolean;
|
|
411
881
|
selectionState: ProcessSelectionState;
|
|
882
|
+
/**
|
|
883
|
+
* This transition's composed accessible name ({@link transitionAriaLabel}), duplicated
|
|
884
|
+
* here from the edge object's own `ariaLabel` (#354). React Flow's `EdgeWrapper` reads
|
|
885
|
+
* `ariaLabel` off the edge OBJECT for the outer, non-focusable `<g>` — it never forwards
|
|
886
|
+
* it to the edge COMPONENT via `EdgeProps` (`@xyflow/react`'s `EdgeProps` type has no
|
|
887
|
+
* `ariaLabel` field) — so `ProcessTransitionEdge`, which only receives `data`, has no
|
|
888
|
+
* other channel to reach it. Read this field, never recompute the name locally, or the
|
|
889
|
+
* canvas and the `TableView` twin (`transitionRows`) can drift apart. Always set by
|
|
890
|
+
* {@link buildProcessMapModel} — optional only because it is filled in a step after the
|
|
891
|
+
* rest of this object (it is itself derived from this object).
|
|
892
|
+
*/
|
|
893
|
+
ariaLabel?: string;
|
|
894
|
+
/**
|
|
895
|
+
* Where this transition sits against a reference model (RM-062). Set only when the map
|
|
896
|
+
* was given `conformance`; drives `data-conformance` plus its glyph and dash.
|
|
897
|
+
*/
|
|
898
|
+
conformance?: ConformanceState;
|
|
899
|
+
/**
|
|
900
|
+
* Object-centric — RM-066. The object type this edge belongs to; per-type edges between
|
|
901
|
+
* the same two activities are drawn side by side (see `parallelIndex`/`parallelCount`).
|
|
902
|
+
*/
|
|
903
|
+
objectType?: ProcessObjectTypeMark;
|
|
904
|
+
/** Object-centric — RM-066. This edge's slot among the per-type edges of its pair. */
|
|
905
|
+
parallelIndex?: number;
|
|
906
|
+
/** Object-centric — RM-066. How many per-type edges join this edge's pair. */
|
|
907
|
+
parallelCount?: number;
|
|
412
908
|
}
|
|
413
909
|
/** A process-map activity node. Register as `nodeTypes={{ "process-activity": … }}`. */
|
|
414
910
|
type ProcessMapNode = Node<ProcessActivityNodeData, "process-activity">;
|
|
@@ -423,6 +919,8 @@ interface ProcessActivityRow {
|
|
|
423
919
|
reworkCount?: number;
|
|
424
920
|
role: string;
|
|
425
921
|
selectionState: ProcessSelectionState;
|
|
922
|
+
/** Object-centric — RM-066. Per-type counts, as printed in the table twin. */
|
|
923
|
+
objectTypes?: string;
|
|
426
924
|
}
|
|
427
925
|
/** One row of the accessible `TableView` twin — transitions half. */
|
|
428
926
|
interface ProcessTransitionRow {
|
|
@@ -433,6 +931,8 @@ interface ProcessTransitionRow {
|
|
|
433
931
|
secondaryLabel?: string;
|
|
434
932
|
shape: string;
|
|
435
933
|
selectionState: ProcessSelectionState;
|
|
934
|
+
/** Object-centric — RM-066. The object type's display name. */
|
|
935
|
+
objectType?: string;
|
|
436
936
|
}
|
|
437
937
|
/** Everything the canvas and the table are both rendered from. */
|
|
438
938
|
interface ProcessMapModel {
|
|
@@ -586,12 +1086,17 @@ interface BuildProcessMapModelOptions {
|
|
|
586
1086
|
* every edge starts `isBackEdge: false` exactly as `discoverGraph` leaves it.
|
|
587
1087
|
*/
|
|
588
1088
|
backEdgeIds?: ReadonlySet<string>;
|
|
1089
|
+
/**
|
|
1090
|
+
* The shared activity colour scale (RM-054). When given, every node carries
|
|
1091
|
+
* `data.accent`, so the map and `VariantExplorer` paint an activity identically.
|
|
1092
|
+
*/
|
|
1093
|
+
colorScale?: ActivityColorScale;
|
|
589
1094
|
}
|
|
590
1095
|
/**
|
|
591
1096
|
* Map a discovered (or abstracted) graph plus a metric choice into everything both the
|
|
592
1097
|
* canvas and the table render. Pure: same inputs, same model, no clock and no DOM.
|
|
593
1098
|
*/
|
|
594
|
-
declare function buildProcessMapModel({ graph, metric, rework, selection, selectionStates, backEdgeIds, }: BuildProcessMapModelOptions): ProcessMapModel;
|
|
1099
|
+
declare function buildProcessMapModel({ graph, metric, rework, selection, selectionStates, backEdgeIds, colorScale, }: BuildProcessMapModelOptions): ProcessMapModel;
|
|
595
1100
|
/**
|
|
596
1101
|
* The word for an activity's position in the process — printed in the table's own column
|
|
597
1102
|
* and folded into the node's accessible name, so "this is where cases start" survives
|
|
@@ -624,31 +1129,67 @@ declare const PROCESS_SELECTION_STATE_MESSAGE_KEYS: Readonly<Partial<Record<Proc
|
|
|
624
1129
|
declare function activityAriaLabel(data: ProcessActivityNodeData): string;
|
|
625
1130
|
/** The accessible name of one transition edge. */
|
|
626
1131
|
declare function transitionAriaLabel(data: ProcessTransitionEdgeData, metricLabel: string): string;
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
1132
|
+
/** How one object type is marked on the map: a name, a text code and a chart colour. */
|
|
1133
|
+
interface ProcessObjectTypeMark {
|
|
1134
|
+
/** The object type's id, as keyed in the `ObjectCentricGraph`. */
|
|
1135
|
+
type: string;
|
|
1136
|
+
/** Display name. */
|
|
1137
|
+
label: string;
|
|
1138
|
+
/** Two-character code printed beside every swatch — the non-colour channel. */
|
|
1139
|
+
code: string;
|
|
1140
|
+
/** A categorical chart token from `objectTypeColorScale` (RM-054's scale, reused). */
|
|
1141
|
+
color: ActivityColor;
|
|
1142
|
+
}
|
|
1143
|
+
/** One object type's share of an activity node. */
|
|
1144
|
+
interface ProcessObjectTypeCount extends ProcessObjectTypeMark {
|
|
1145
|
+
instances: number;
|
|
1146
|
+
/** Distinct objects of this type the activity touches. */
|
|
1147
|
+
cases: number;
|
|
1148
|
+
/** The chip's accessible name, e.g. "order: 2 objects, 3 occurrences". */
|
|
1149
|
+
ariaLabel: string;
|
|
1150
|
+
}
|
|
1151
|
+
/** Every string the object-centric mode composes. Override for a non-English locale. */
|
|
1152
|
+
interface ObjectCentricMapLabels {
|
|
1153
|
+
/** A node chip's accessible name and table text. */
|
|
1154
|
+
typeCount: (type: string, objects: number, occurrences: number) => string;
|
|
1155
|
+
/** Prefixes a per-type edge's accessible name. */
|
|
1156
|
+
edgePrefix: (type: string) => string;
|
|
1157
|
+
/** Activity-table column header. */
|
|
1158
|
+
columnObjectTypes: string;
|
|
1159
|
+
/** Transition-table column header. */
|
|
1160
|
+
columnObjectType: string;
|
|
1161
|
+
/** The canvas legend's title. */
|
|
1162
|
+
legendTitle: string;
|
|
1163
|
+
}
|
|
1164
|
+
/** English defaults for {@link ObjectCentricMapLabels}. */
|
|
1165
|
+
declare const OBJECT_CENTRIC_MAP_DEFAULT_LABELS: Readonly<ObjectCentricMapLabels>;
|
|
1166
|
+
/** The id of one object type's edge: the merged edge id, the separator, the type. */
|
|
1167
|
+
declare function objectCentricEdgeId(source: string, target: string, type: string): string;
|
|
1168
|
+
/** Inputs to {@link buildObjectCentricMapModel}. */
|
|
1169
|
+
interface BuildObjectCentricMapModelOptions extends BuildProcessMapModelOptions {
|
|
634
1170
|
/**
|
|
635
|
-
*
|
|
636
|
-
*
|
|
637
|
-
* process, not a simplified one.
|
|
1171
|
+
* The object-centric graph `graph` was flattened from (`objectCentricProcessGraph`).
|
|
1172
|
+
* Omit — or omit `objectTypeScale` — and this is exactly {@link buildProcessMapModel}.
|
|
638
1173
|
*/
|
|
639
|
-
|
|
640
|
-
/**
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
/** What {@link abstractGraph} returns: a `ProcessGraph` plus what it left out. */
|
|
644
|
-
interface AbstractedGraph extends ProcessGraph {
|
|
645
|
-
hidden: {
|
|
646
|
-
/** Activities present in the input graph and absent from this one. */
|
|
647
|
-
activities: number;
|
|
648
|
-
/** Transitions present in the input graph and absent from this one. */
|
|
649
|
-
paths: number;
|
|
650
|
-
};
|
|
1174
|
+
objectCentric?: ObjectCentricGraph;
|
|
1175
|
+
/** `objectTypeColorScale(objectCentric)`, built once from the FULL graph. */
|
|
1176
|
+
objectTypeScale?: ActivityColorScale;
|
|
1177
|
+
objectCentricLabels?: ObjectCentricMapLabels;
|
|
651
1178
|
}
|
|
1179
|
+
/**
|
|
1180
|
+
* The object-centric process-map model: {@link buildProcessMapModel} over the flattened
|
|
1181
|
+
* graph, then
|
|
1182
|
+
*
|
|
1183
|
+
* - every node gains `data.objectTypes` (one chip per type, each with a text code and a
|
|
1184
|
+
* real accessible name folded into the node's own), and
|
|
1185
|
+
* - every merged edge is replaced by one edge PER OBJECT TYPE — its weight and printed
|
|
1186
|
+
* label read that type's own counts, its label is prefixed with the type's code, and its
|
|
1187
|
+
* stroke is the type's chart token. The edge-value colour ramp is never used here.
|
|
1188
|
+
*
|
|
1189
|
+
* A transition selection may name either a per-type edge or the merged pair; both select
|
|
1190
|
+
* the pair's neighbourhood, and only the named per-type edge reads `"selected"`.
|
|
1191
|
+
*/
|
|
1192
|
+
declare function buildObjectCentricMapModel({ objectCentric, objectTypeScale, objectCentricLabels, ...options }: BuildObjectCentricMapModelOptions): ProcessMapModel;
|
|
652
1193
|
|
|
653
1194
|
/**
|
|
654
1195
|
* The zoom the map refuses to open below, however big the process is.
|
|
@@ -704,11 +1245,66 @@ interface ProcessMapProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSelect
|
|
|
704
1245
|
tableView?: boolean;
|
|
705
1246
|
/** No graph yet. Renders the loading panel rather than an empty canvas. */
|
|
706
1247
|
loading?: boolean;
|
|
1248
|
+
/**
|
|
1249
|
+
* A shared activity colour scale (RM-054, `/core`'s `activityColorScale`). When given,
|
|
1250
|
+
* each activity node shows its identity swatch — the same colour `VariantExplorer`
|
|
1251
|
+
* paints that activity with. Build it once from the FULL graph and hand the same
|
|
1252
|
+
* instance to both views. Omit for today's uncoloured nodes.
|
|
1253
|
+
*/
|
|
1254
|
+
colorScale?: ActivityColorScale;
|
|
1255
|
+
/**
|
|
1256
|
+
* A replay result (RM-061's `tokenReplay`) to overlay (RM-062). When given, every node
|
|
1257
|
+
* and edge carries `data-conformance="both" | "logOnly" | "modelOnly"` — additive to
|
|
1258
|
+
* `data-selection` — painted as a status tone PLUS a glyph and a line style, with the
|
|
1259
|
+
* state's word in the accessible name and a Conformance column in the table twin. Omit
|
|
1260
|
+
* for today's map, unchanged. Usually reached through `ConformanceOverlay`.
|
|
1261
|
+
*/
|
|
1262
|
+
conformance?: ConformanceResult;
|
|
1263
|
+
/**
|
|
1264
|
+
* Object-centric — RM-066. An object-centric graph (`discoverObjectCentricGraph`, e.g.
|
|
1265
|
+
* over `fromOcel(…).logs`) to draw instead of `graph`/`log` — mutually exclusive with
|
|
1266
|
+
* both, and it wins when given together (with a dev-mode console warning). Shared
|
|
1267
|
+
* activities merge into one node carrying a chip per object type; edges are drawn once
|
|
1268
|
+
* per object type in that type's chart colour, side by side. `abstraction` applies to
|
|
1269
|
+
* every type alike; for per-type abstraction pass `abstractObjectCentricGraph(…)`'s
|
|
1270
|
+
* result here instead.
|
|
1271
|
+
*/
|
|
1272
|
+
objectCentric?: ObjectCentricGraph;
|
|
1273
|
+
/** Object-centric — RM-066. Strings the object-centric mode composes. */
|
|
1274
|
+
objectCentricLabels?: ObjectCentricMapLabels;
|
|
707
1275
|
/**
|
|
708
1276
|
* Accessible name for the canvas region. Defaults to the localized
|
|
709
1277
|
* `process.map.label` message.
|
|
710
1278
|
*/
|
|
711
1279
|
label?: string;
|
|
1280
|
+
/**
|
|
1281
|
+
* The smallest zoom the OPENING fit may use. The default keeps activity names legible
|
|
1282
|
+
* and, when the process does not fit at that size, opens on its start. A workspace that
|
|
1283
|
+
* would rather open on the whole picture — a wide canvas, a reader who zooms in on what
|
|
1284
|
+
* matters — lowers it. The reader can always zoom out further by hand.
|
|
1285
|
+
* @default PROCESS_MAP_LEGIBLE_ZOOM
|
|
1286
|
+
*/
|
|
1287
|
+
fitMinZoom?: number;
|
|
1288
|
+
/**
|
|
1289
|
+
* The fraction of the pane the opening fit keeps clear on every side. The default is
|
|
1290
|
+
* generous because transition pills are drawn outside the fitted bounds; a pane that is
|
|
1291
|
+
* short on the axis the process runs along can trade some of it for a larger picture.
|
|
1292
|
+
* @default 0.15
|
|
1293
|
+
*/
|
|
1294
|
+
fitPadding?: number;
|
|
1295
|
+
/**
|
|
1296
|
+
* Re-frames the map whenever this value changes. The map already re-fits when its own
|
|
1297
|
+
* structure or direction changes; it cannot know that the pane around it just changed
|
|
1298
|
+
* shape — a dock opened, a side panel closed. Pass anything that changes when that
|
|
1299
|
+
* happens. Unset: no extra re-fits, the reader's viewport is left alone.
|
|
1300
|
+
*/
|
|
1301
|
+
refitKey?: string | number;
|
|
1302
|
+
/**
|
|
1303
|
+
* The layout engine. `"elk"` lays the map out with `@elabs-ai/components-flow`'s
|
|
1304
|
+
* `layoutFlowElk` — elkjs, an optional peer, loaded lazily on first use; when it is not
|
|
1305
|
+
* installed the map falls back to dagre with a development-only warning. @default "dagre"
|
|
1306
|
+
*/
|
|
1307
|
+
layoutEngine?: "dagre" | "elk";
|
|
712
1308
|
}
|
|
713
1309
|
/**
|
|
714
1310
|
* The process map.
|
|
@@ -718,7 +1314,7 @@ interface ProcessMapProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSelect
|
|
|
718
1314
|
* <ProcessMap log={log} metric={{ node: "absolute_case", edge: "absolute" }} />
|
|
719
1315
|
* ```
|
|
720
1316
|
*/
|
|
721
|
-
declare function ProcessMap({ graph, log, abstraction, metric, rework, selection, selectionStates, onSelect, onFilterIntent, direction, showMiniMap, showLegend, tableView, loading, label, className, ...props }: ProcessMapProps): react.JSX.Element;
|
|
1317
|
+
declare function ProcessMap({ graph, log, abstraction, metric, rework, selection, selectionStates, onSelect, onFilterIntent, direction, showMiniMap, showLegend, tableView, loading, colorScale, conformance, objectCentric, objectCentricLabels, label, layoutEngine, fitMinZoom, fitPadding, refitKey, className, ...props }: ProcessMapProps): react.JSX.Element;
|
|
722
1318
|
|
|
723
1319
|
/** What the node and edge components read while something is hovered. */
|
|
724
1320
|
interface ProcessMapHoverState {
|
|
@@ -829,6 +1425,11 @@ interface UseProcessLayoutOptions {
|
|
|
829
1425
|
direction: FlowLayoutDirection;
|
|
830
1426
|
/** @default {@link DEFAULT_LAYOUT_DEBOUNCE_MS} */
|
|
831
1427
|
debounceMs?: number;
|
|
1428
|
+
/**
|
|
1429
|
+
* Which layout engine runs. `"elk"` calls `layoutFlowElk` (async, lazily loaded, falls
|
|
1430
|
+
* back to dagre when elkjs is not installed) instead of `layoutFlow`. @default "dagre"
|
|
1431
|
+
*/
|
|
1432
|
+
layoutEngine?: "dagre" | "elk";
|
|
832
1433
|
}
|
|
833
1434
|
/** What {@link useProcessLayout} answers. */
|
|
834
1435
|
interface UseProcessLayoutResult {
|
|
@@ -853,7 +1454,7 @@ declare function applyLayoutSnapshot(nodes: ProcessMapNode[], snapshot: ProcessL
|
|
|
853
1454
|
* @see {@link UseProcessLayoutResult.layoutRuns} — the observable proof that a metric-only
|
|
854
1455
|
* change does not re-run dagre.
|
|
855
1456
|
*/
|
|
856
|
-
declare function useProcessLayout({ nodes, edges, structureKey, direction, debounceMs, }: UseProcessLayoutOptions): UseProcessLayoutResult;
|
|
1457
|
+
declare function useProcessLayout({ nodes, edges, structureKey, direction, debounceMs, layoutEngine, }: UseProcessLayoutOptions): UseProcessLayoutResult;
|
|
857
1458
|
|
|
858
1459
|
interface AbstractionControlsProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
|
|
859
1460
|
/** The current abstraction — both fractions, `invert`, and (read-only here) `keepConnected`. */
|
|
@@ -871,7 +1472,36 @@ interface AbstractionControlsProps extends Omit<HTMLAttributes<HTMLDivElement>,
|
|
|
871
1472
|
autoMaxActivities?: number;
|
|
872
1473
|
/** Accessible name for the control group. Default from locale. */
|
|
873
1474
|
label?: string;
|
|
1475
|
+
/**
|
|
1476
|
+
* Object-centric — RM-066. One slider pair per object type, keyed by type, rendered as
|
|
1477
|
+
* collapsible rows under the global pair. A `linked` type (the default) follows the
|
|
1478
|
+
* global sliders proportionally; toggle its link to abstract it on its own. Feed the
|
|
1479
|
+
* result to `abstractObjectCentricGraph`.
|
|
1480
|
+
*/
|
|
1481
|
+
perType?: Readonly<Record<string, ObjectTypeAbstraction>>;
|
|
1482
|
+
/** Object-centric — RM-066. Called with the whole next per-type record. */
|
|
1483
|
+
onPerTypeChange?(next: Record<string, ObjectTypeAbstraction>): void;
|
|
1484
|
+
/** Object-centric — RM-066. Strings for the per-type rows. */
|
|
1485
|
+
perTypeLabels?: ObjectTypeAbstractionLabels;
|
|
1486
|
+
}
|
|
1487
|
+
/** Object-centric — RM-066. One object type's abstraction fractions. */
|
|
1488
|
+
interface ObjectTypeAbstraction {
|
|
1489
|
+
/** Fraction of this type's activities to keep, `0..1`. */
|
|
1490
|
+
activities: number;
|
|
1491
|
+
/** Fraction of this type's paths to keep, `0..1`. */
|
|
1492
|
+
paths: number;
|
|
1493
|
+
/** Follow the global sliders proportionally. @default true */
|
|
1494
|
+
linked?: boolean;
|
|
874
1495
|
}
|
|
1496
|
+
/** Object-centric — RM-066. Strings for the per-type rows. */
|
|
1497
|
+
interface ObjectTypeAbstractionLabels {
|
|
1498
|
+
section: string;
|
|
1499
|
+
link: (type: string) => string;
|
|
1500
|
+
activities: (type: string) => string;
|
|
1501
|
+
paths: (type: string) => string;
|
|
1502
|
+
}
|
|
1503
|
+
/** English defaults for {@link ObjectTypeAbstractionLabels}. */
|
|
1504
|
+
declare const OBJECT_TYPE_ABSTRACTION_DEFAULT_LABELS: Readonly<ObjectTypeAbstractionLabels>;
|
|
875
1505
|
declare const AbstractionControls: react.ForwardRefExoticComponent<AbstractionControlsProps & react.RefAttributes<HTMLDivElement>>;
|
|
876
1506
|
|
|
877
1507
|
/**
|
|
@@ -977,13 +1607,30 @@ interface ProcessKpiStripKpis {
|
|
|
977
1607
|
type ProcessKpiStripTrendKey = keyof ProcessKpiStripKpis | "conformance";
|
|
978
1608
|
interface ProcessKpiStripProps extends HTMLAttributes<HTMLDivElement> {
|
|
979
1609
|
kpis: ProcessKpiStripKpis;
|
|
980
|
-
/**
|
|
981
|
-
|
|
1610
|
+
/**
|
|
1611
|
+
* `0..1`, a replay result (RM-061's `tokenReplay`, whose `overallFitness` the tile
|
|
1612
|
+
* prints — RM-062), or `null`/`undefined` when no conformance model has been fitted.
|
|
1613
|
+
*/
|
|
1614
|
+
conformance?: number | ConformanceResult | null;
|
|
982
1615
|
/** Optional per-tile trend series (oldest -> newest), keyed by KPI. */
|
|
983
1616
|
trends?: Partial<Record<ProcessKpiStripTrendKey, number[]>>;
|
|
1617
|
+
/**
|
|
1618
|
+
* Conformance rate over time (`conformanceRateSeries`), plotted as the conformance
|
|
1619
|
+
* tile's sparkline — the rate-over-time reading (RM-062). Takes precedence over
|
|
1620
|
+
* `trends.conformance`.
|
|
1621
|
+
*/
|
|
1622
|
+
conformanceSeries?: ConformanceRatePoint[];
|
|
984
1623
|
loading?: boolean;
|
|
1624
|
+
/**
|
|
1625
|
+
* How the six numbers are laid out. `"grid"` (default) is the card grid a dashboard page
|
|
1626
|
+
* opens with. `"inline"` is one dense ribbon — label, value and sparkline per cell, divided
|
|
1627
|
+
* by hairlines, scrolling sideways when it runs out of room — for a workspace whose height
|
|
1628
|
+
* belongs to the process map, not to its KPIs. Same numbers, same formats, same sparkline
|
|
1629
|
+
* text alternatives in both.
|
|
1630
|
+
*/
|
|
1631
|
+
layout?: "grid" | "inline";
|
|
985
1632
|
}
|
|
986
|
-
declare function ProcessKpiStrip({ kpis, conformance, trends, loading, className, ...props }: ProcessKpiStripProps): react.JSX.Element;
|
|
1633
|
+
declare function ProcessKpiStrip({ kpis, conformance, trends, conformanceSeries, loading, layout, className, ...props }: ProcessKpiStripProps): react.JSX.Element;
|
|
987
1634
|
|
|
988
1635
|
/**
|
|
989
1636
|
* Off-thread discovery — RM-050.
|
|
@@ -1052,9 +1699,15 @@ interface ProcessExplorerMetricSpec {
|
|
|
1052
1699
|
* variant selection — a case a click on the process map can never produce, but a click on a
|
|
1053
1700
|
* variant row can. The widening is local to this hook's own type alias; it does not touch
|
|
1054
1701
|
* `ProcessFilterIntent` or `ProcessMap`'s menu, which still only ever emits the original four.
|
|
1702
|
+
*
|
|
1703
|
+
* `{ kind: "cases" }` joins it for the same reason: `DottedChart` (RM-059) and
|
|
1704
|
+
* `PerformanceSpectrum` (RM-060) brush a set of case ids, so their `onFilterIntent` can be
|
|
1705
|
+
* wired straight to `applyIntent`.
|
|
1055
1706
|
*/
|
|
1056
1707
|
type FilterIntent = ProcessFilterIntent | Extract<FilterSpec, {
|
|
1057
1708
|
kind: "variant";
|
|
1709
|
+
}> | Extract<FilterSpec, {
|
|
1710
|
+
kind: "cases";
|
|
1058
1711
|
}>;
|
|
1059
1712
|
/** Options for {@link useProcessExplorer}. */
|
|
1060
1713
|
interface ProcessExplorerOptions {
|
|
@@ -1095,6 +1748,17 @@ interface UseProcessExplorerResult {
|
|
|
1095
1748
|
applyIntent(intent: FilterIntent): void;
|
|
1096
1749
|
clearIntent(index: number): void;
|
|
1097
1750
|
intents: FilterIntent[];
|
|
1751
|
+
/**
|
|
1752
|
+
* How many cases EACH active intent alone excludes — parallel to {@link intents} (same
|
|
1753
|
+
* index), for `ProcessFilterBar` (RM-056, #205)'s per-chip "excluded N" count. For intent
|
|
1754
|
+
* `i`, this is the case count filtered by every intent BEFORE `i` minus the case count
|
|
1755
|
+
* filtered by every intent up to and including `i` — so it isolates what `i` itself
|
|
1756
|
+
* removes from the chain, not what the whole chain removes. `[]` when no intents are
|
|
1757
|
+
* active. Computed with one `filterNormalizedLog` call per prefix (`n + 1` calls for `n`
|
|
1758
|
+
* intents, reusing each prefix's count for both the term it ends and the term it starts),
|
|
1759
|
+
* never `n²` — additive field, `intents`/`applyIntent`/`clearIntent` are unchanged.
|
|
1760
|
+
*/
|
|
1761
|
+
excludedByIntent: number[];
|
|
1098
1762
|
filteredLog: EventLog;
|
|
1099
1763
|
/**
|
|
1100
1764
|
* Per-element states the active filter contributes — pass straight into `ProcessMap`'s
|
|
@@ -1150,4 +1814,1195 @@ interface UseProcessExplorerResult {
|
|
|
1150
1814
|
*/
|
|
1151
1815
|
declare function useProcessExplorer(log: EventLog, opts?: ProcessExplorerOptions): UseProcessExplorerResult;
|
|
1152
1816
|
|
|
1153
|
-
|
|
1817
|
+
/**
|
|
1818
|
+
* Pure helpers behind `VariantExplorer` (RM-054) — no React, so the selection semantics
|
|
1819
|
+
* are unit-testable on their own and identical on every render.
|
|
1820
|
+
*/
|
|
1821
|
+
|
|
1822
|
+
/** The optional numeric columns a variant row can show, in display order. */
|
|
1823
|
+
type VariantExplorerColumn = "cases" | "coverage" | "medianDuration";
|
|
1824
|
+
/** Every column, in the order the explorer renders them. */
|
|
1825
|
+
declare const VARIANT_EXPLORER_COLUMNS: readonly VariantExplorerColumn[];
|
|
1826
|
+
/**
|
|
1827
|
+
* The smallest prefix of `variants` whose `cumulativeShare` reaches `target`.
|
|
1828
|
+
*
|
|
1829
|
+
* `variants` is expected in `extractVariants` order (count descending, fully tie-broken),
|
|
1830
|
+
* so the prefix is the set of most frequent paths that together cover `target` of the
|
|
1831
|
+
* cases. Deterministic: the same variants and target always yield the same id list. A
|
|
1832
|
+
* target of `0` or less selects nothing; a target above the last variant's share selects
|
|
1833
|
+
* every variant. A tiny epsilon absorbs float noise in `cumulativeShare` so a `0.5`
|
|
1834
|
+
* target is met by a variant whose share prints as exactly 50 %.
|
|
1835
|
+
*/
|
|
1836
|
+
declare function selectVariantsByCoverage(variants: readonly Variant[], target: number): string[];
|
|
1837
|
+
|
|
1838
|
+
/** Row height in px — fixed, so the virtualizer never has to measure. Matches `h-10`. */
|
|
1839
|
+
declare const VARIANT_EXPLORER_ROW_HEIGHT = 40;
|
|
1840
|
+
/** How a selection change applies: replace the whole selection, or flip these ids. */
|
|
1841
|
+
type VariantSelectMode = "replace" | "toggle";
|
|
1842
|
+
/**
|
|
1843
|
+
* Every user-visible string. `{name}` placeholders are filled at render. Override any
|
|
1844
|
+
* subset through `labels` to localize.
|
|
1845
|
+
*/
|
|
1846
|
+
interface VariantExplorerLabels {
|
|
1847
|
+
/** Accessible name of the list. */
|
|
1848
|
+
list: string;
|
|
1849
|
+
columnVariant: string;
|
|
1850
|
+
columnSequence: string;
|
|
1851
|
+
columnCases: string;
|
|
1852
|
+
columnCoverage: string;
|
|
1853
|
+
columnMedianDuration: string;
|
|
1854
|
+
columnState: string;
|
|
1855
|
+
/** `{rank}`, `{activities}`, `{cases}`, `{coverage}` (a whole percent number). */
|
|
1856
|
+
rowSummary: string;
|
|
1857
|
+
/** `{activities}` — the sequence joined with commas. */
|
|
1858
|
+
sequence: string;
|
|
1859
|
+
activitiesOne: string;
|
|
1860
|
+
activitiesOther: string;
|
|
1861
|
+
casesOne: string;
|
|
1862
|
+
casesOther: string;
|
|
1863
|
+
selected: string;
|
|
1864
|
+
excluded: string;
|
|
1865
|
+
coverageTarget: string;
|
|
1866
|
+
/** `{percent}`, `{count}`. */
|
|
1867
|
+
coverageTargetValue: string;
|
|
1868
|
+
filterToSelected: string;
|
|
1869
|
+
tableCaption: string;
|
|
1870
|
+
loading: string;
|
|
1871
|
+
empty: string;
|
|
1872
|
+
emptyBody: string;
|
|
1873
|
+
}
|
|
1874
|
+
/** The shipped English labels. */
|
|
1875
|
+
declare const VARIANT_EXPLORER_DEFAULT_LABELS: Readonly<VariantExplorerLabels>;
|
|
1876
|
+
/** Props for {@link VariantExplorer}. `onSelect` shadows the DOM handler, so it is omitted. */
|
|
1877
|
+
interface VariantExplorerProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSelect"> {
|
|
1878
|
+
/** Variants in `extractVariants` order (count descending). */
|
|
1879
|
+
variants: Variant[];
|
|
1880
|
+
/** The shared colour scale — hand `ProcessMap` the same instance. */
|
|
1881
|
+
colorScale: ActivityColorScale;
|
|
1882
|
+
/** Tri-state per variant id; an absent key means `"associated"`. */
|
|
1883
|
+
selectionStates?: ProcessSelectionStates;
|
|
1884
|
+
/** Fires with the ids to select and how to apply them. The explorer never filters. */
|
|
1885
|
+
onSelect: (variantIds: string[], mode: VariantSelectMode) => void;
|
|
1886
|
+
/** When given, a button emits `{ kind: "variant", ids }` for the selected variants. */
|
|
1887
|
+
onFilterIntent?: (intent: FilterIntent) => void;
|
|
1888
|
+
/** Numeric columns to show. @default ["cases", "coverage", "medianDuration"] */
|
|
1889
|
+
columns?: VariantExplorerColumn[];
|
|
1890
|
+
/**
|
|
1891
|
+
* Initial coverage target, `0..1`. When given, a slider selects the smallest prefix of
|
|
1892
|
+
* variants whose cumulative share reaches the target (mode `"replace"`).
|
|
1893
|
+
*/
|
|
1894
|
+
coverageTarget?: number;
|
|
1895
|
+
/** "Variant DNA" strip: two-character codes instead of full activity labels. */
|
|
1896
|
+
abbreviate?: boolean;
|
|
1897
|
+
/**
|
|
1898
|
+
* `"swatch"`: each step is one identity block with no text — the densest strip, for a
|
|
1899
|
+
* narrow rail. The strip keeps its accessible name and every block its `title`.
|
|
1900
|
+
* @default "text"
|
|
1901
|
+
*/
|
|
1902
|
+
sequenceDisplay?: "text" | "swatch";
|
|
1903
|
+
/** Render the accessible table twin instead of the list. @default false */
|
|
1904
|
+
tableView?: boolean;
|
|
1905
|
+
/** No variants yet. Renders the loading panel rather than an empty list. */
|
|
1906
|
+
loading?: boolean;
|
|
1907
|
+
/** Override any user-visible string. */
|
|
1908
|
+
labels?: Partial<VariantExplorerLabels>;
|
|
1909
|
+
}
|
|
1910
|
+
/**
|
|
1911
|
+
* The variant explorer.
|
|
1912
|
+
*
|
|
1913
|
+
* @example
|
|
1914
|
+
* ```tsx
|
|
1915
|
+
* const scale = useMemo(() => activityColorScale(fullGraph), [fullGraph]);
|
|
1916
|
+
* <VariantExplorer
|
|
1917
|
+
* variants={explorer.variants}
|
|
1918
|
+
* colorScale={scale}
|
|
1919
|
+
* selectionStates={explorer.selectionStates}
|
|
1920
|
+
* onSelect={(ids) => explorer.applyIntent({ kind: "variant", ids })}
|
|
1921
|
+
* />
|
|
1922
|
+
* ```
|
|
1923
|
+
*/
|
|
1924
|
+
declare const VariantExplorer: react.ForwardRefExoticComponent<VariantExplorerProps & react.RefAttributes<HTMLDivElement>>;
|
|
1925
|
+
|
|
1926
|
+
interface ProcessFilterBarProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
|
|
1927
|
+
/** The active filter chain — `useProcessExplorer`'s own `intents`, in order. */
|
|
1928
|
+
intents: FilterIntent[];
|
|
1929
|
+
/**
|
|
1930
|
+
* How many cases EACH intent alone excludes, parallel to {@link intents} (same index) —
|
|
1931
|
+
* `useProcessExplorer`'s own additive `excludedByIntent` field.
|
|
1932
|
+
*/
|
|
1933
|
+
excludedByIntent: number[];
|
|
1934
|
+
/** The unfiltered case count — the right half of the summary line's "X of Y". */
|
|
1935
|
+
totalCases: number;
|
|
1936
|
+
/** `useProcessExplorer`'s `kpis.cases` — the left half of the summary line's "X of Y". */
|
|
1937
|
+
filteredCases: number;
|
|
1938
|
+
/** What abstraction currently hides — `useProcessExplorer`'s own `hiddenCounts`. */
|
|
1939
|
+
hiddenCounts?: {
|
|
1940
|
+
activities: number;
|
|
1941
|
+
paths: number;
|
|
1942
|
+
};
|
|
1943
|
+
/** Remove one intent by its index into {@link intents} — wire to `clearIntent`. */
|
|
1944
|
+
onRemove(index: number): void;
|
|
1945
|
+
/** Remove every intent at once. */
|
|
1946
|
+
onClearAll(): void;
|
|
1947
|
+
/** Accessible name for the chip row. Default from locale. */
|
|
1948
|
+
label?: string;
|
|
1949
|
+
}
|
|
1950
|
+
/**
|
|
1951
|
+
* Filter chain breadcrumbs: one removable chip per active intent, each carrying how many
|
|
1952
|
+
* cases that intent alone excludes, plus a summary line stating what filtering and
|
|
1953
|
+
* abstraction currently hide.
|
|
1954
|
+
*/
|
|
1955
|
+
declare const ProcessFilterBar: react.ForwardRefExoticComponent<ProcessFilterBarProps & react.RefAttributes<HTMLDivElement>>;
|
|
1956
|
+
|
|
1957
|
+
/**
|
|
1958
|
+
* One case's own summary — its extent, size and path identity, not its trace. The shape
|
|
1959
|
+
* `CaseTable` (case-table/) renders one row per, and `CaseTimeline`'s own model reads a
|
|
1960
|
+
* single case's raw `EventRow[]` separately (a summary row has no per-activity detail to
|
|
1961
|
+
* build a Gantt row from).
|
|
1962
|
+
*/
|
|
1963
|
+
interface CaseRow {
|
|
1964
|
+
caseId: string;
|
|
1965
|
+
/** ISO 8601. Empty string when the case has no resolvable extent — see `normalizeLog`. */
|
|
1966
|
+
start: string;
|
|
1967
|
+
end: string;
|
|
1968
|
+
durationMs: number;
|
|
1969
|
+
eventCount: number;
|
|
1970
|
+
/** Identical to the `id` {@link extractVariants} assigns the SAME case over the SAME log. */
|
|
1971
|
+
variantId: string;
|
|
1972
|
+
/**
|
|
1973
|
+
* Never set here: no conformance model lives in `/core` (`ProcessKpiStrip`'s own
|
|
1974
|
+
* `conformance` prop treats it the same way — a fitted value the HOST supplies, never a
|
|
1975
|
+
* number this package invents). A caller with a conformance result attaches it per row.
|
|
1976
|
+
*/
|
|
1977
|
+
conformance?: "conforming" | "nonConforming" | "unknown";
|
|
1978
|
+
/** Carried over from `EventLog.caseAttributes`, untouched. */
|
|
1979
|
+
attributes?: Record<string, string | number | boolean | null>;
|
|
1980
|
+
}
|
|
1981
|
+
/**
|
|
1982
|
+
* One summary row per case in `log`, in the same first-appearance order `normalizeLog`
|
|
1983
|
+
* produces. `variantId` is sourced from {@link extractVariants} over the identical log —
|
|
1984
|
+
* see the module docblock for why that, and not a direct `variantId(sequence)` call, is
|
|
1985
|
+
* what keeps a `CaseTable` and a variant explorer over the same log always agreeing on
|
|
1986
|
+
* which cases share a path.
|
|
1987
|
+
*
|
|
1988
|
+
* An empty log answers an empty array.
|
|
1989
|
+
*/
|
|
1990
|
+
declare function casesFromLog(log: EventLog): CaseRow[];
|
|
1991
|
+
|
|
1992
|
+
interface CaseTableProps extends HTMLAttributes<HTMLDivElement> {
|
|
1993
|
+
cases: CaseRow[];
|
|
1994
|
+
/** Column configuration over `DataTable`. Defaults to `createCaseTableColumns`'s set. */
|
|
1995
|
+
columns?: ColumnDef<CaseRow>[];
|
|
1996
|
+
/** Fired when a row is activated (click, or Enter/Space on its keyboard activation target). */
|
|
1997
|
+
onCaseOpen?: (caseId: string) => void;
|
|
1998
|
+
/** File name for the CSV export. Default `"cases.csv"`. */
|
|
1999
|
+
exportFileName?: string;
|
|
2000
|
+
loading?: boolean;
|
|
2001
|
+
/** Message shown when there are no cases and not loading. */
|
|
2002
|
+
emptyMessage?: ReactNode;
|
|
2003
|
+
}
|
|
2004
|
+
declare const CaseTable: react.ForwardRefExoticComponent<CaseTableProps & react.RefAttributes<HTMLDivElement>>;
|
|
2005
|
+
|
|
2006
|
+
declare const CASE_TABLE_COLUMN_LABEL_KEYS: {
|
|
2007
|
+
readonly caseId: "process.caseTable.columnCaseId";
|
|
2008
|
+
readonly start: "process.caseTable.columnStart";
|
|
2009
|
+
readonly end: "process.caseTable.columnEnd";
|
|
2010
|
+
readonly duration: "process.caseTable.columnDuration";
|
|
2011
|
+
readonly eventCount: "process.caseTable.columnEventCount";
|
|
2012
|
+
readonly variantId: "process.caseTable.columnVariant";
|
|
2013
|
+
readonly conformance: "process.caseTable.columnConformance";
|
|
2014
|
+
};
|
|
2015
|
+
interface CreateCaseTableColumnsOptions {
|
|
2016
|
+
t: LocaleContextValue["t"];
|
|
2017
|
+
formatDate: LocaleContextValue["formatDate"];
|
|
2018
|
+
}
|
|
2019
|
+
/** The default `CaseTable` column set. Reproduce this shape (or subset it) to customize. */
|
|
2020
|
+
declare function createCaseTableColumns({ t, formatDate, }: CreateCaseTableColumnsOptions): ColumnDef<CaseRow>[];
|
|
2021
|
+
|
|
2022
|
+
interface CaseTimelineGap {
|
|
2023
|
+
start: number;
|
|
2024
|
+
end: number;
|
|
2025
|
+
durationMs: number;
|
|
2026
|
+
}
|
|
2027
|
+
/** One activity EXECUTION in the case's trace. */
|
|
2028
|
+
interface CaseTimelineInstance {
|
|
2029
|
+
/** Stable within one model build — the instance's position in chronological order. */
|
|
2030
|
+
id: string;
|
|
2031
|
+
activity: string;
|
|
2032
|
+
start: number;
|
|
2033
|
+
end: number;
|
|
2034
|
+
resource?: string;
|
|
2035
|
+
/** True for a `lifecycle: "start"` row that never got a matching `"complete"`. */
|
|
2036
|
+
isOpen: boolean;
|
|
2037
|
+
/** True when this instance's interval overlaps another by more than `parallelismThreshold`. */
|
|
2038
|
+
isParallel: boolean;
|
|
2039
|
+
/** Waiting time since the previous instance ended, when there was a gap. */
|
|
2040
|
+
gap?: CaseTimelineGap;
|
|
2041
|
+
}
|
|
2042
|
+
interface CaseTimelineModelOptions {
|
|
2043
|
+
/**
|
|
2044
|
+
* Ms of overlap below which two instances are NOT flagged parallel. Default `0` — any
|
|
2045
|
+
* genuine overlap (however small) counts.
|
|
2046
|
+
*/
|
|
2047
|
+
parallelismThreshold?: number;
|
|
2048
|
+
}
|
|
2049
|
+
/**
|
|
2050
|
+
* One case's trace as `CaseTimelineInstance[]`, in ascending `start` order — empty when
|
|
2051
|
+
* `events` resolves to no case (e.g. every row has an empty `caseId`/`activity`).
|
|
2052
|
+
*/
|
|
2053
|
+
declare function buildCaseTimelineInstances(events: EventRow[], options?: CaseTimelineModelOptions): CaseTimelineInstance[];
|
|
2054
|
+
|
|
2055
|
+
interface CaseTimelineProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSelect">, CaseTimelineModelOptions {
|
|
2056
|
+
caseId: string;
|
|
2057
|
+
/** This case's own events, straight from `core`'s `EventLog.events`. */
|
|
2058
|
+
events: EventRow[];
|
|
2059
|
+
}
|
|
2060
|
+
declare const CaseTimeline: react.ForwardRefExoticComponent<CaseTimelineProps & react.RefAttributes<HTMLDivElement>>;
|
|
2061
|
+
|
|
2062
|
+
/**
|
|
2063
|
+
* Pure model behind `DottedChart` (RM-059) — no React, no canvas, so the row order, the
|
|
2064
|
+
* time transform and the brush enumeration are fixture-testable on their own.
|
|
2065
|
+
*
|
|
2066
|
+
* A dotted chart puts one ROW per case and one DOT per event. `computeDots` groups a log by
|
|
2067
|
+
* case (through `/core`'s `normalizeLog`, so lifecycle pairs and the three timestamp
|
|
2068
|
+
* encodings are resolved exactly once), orders the rows by `sort`, and places every event
|
|
2069
|
+
* on the x axis according to `x`:
|
|
2070
|
+
*
|
|
2071
|
+
* - `absolute` — the event's own start time (epoch ms).
|
|
2072
|
+
* - `relative` — milliseconds since the case's first event.
|
|
2073
|
+
* - `relative_day` — time of day, `0 … 24 h` (UTC), so daily rhythms line up.
|
|
2074
|
+
* - `relative_week` — time of week, `0 … 7 d`, weeks starting Monday 00:00 (UTC).
|
|
2075
|
+
*
|
|
2076
|
+
* The two cyclic modes use UTC on purpose: a chart whose dots move when the reviewer's
|
|
2077
|
+
* machine changes time zone is not a deterministic fixture.
|
|
2078
|
+
*/
|
|
2079
|
+
|
|
2080
|
+
/** How the x axis places an event. */
|
|
2081
|
+
type DottedChartX = "absolute" | "relative" | "relative_day" | "relative_week";
|
|
2082
|
+
/** How case rows are ordered, top to bottom. Every order is ascending and stable. */
|
|
2083
|
+
type DottedChartSort = "start" | "end" | "duration" | "start_day";
|
|
2084
|
+
/** One event, placed on the chart. */
|
|
2085
|
+
interface DottedChartDot {
|
|
2086
|
+
kind: "dot";
|
|
2087
|
+
caseId: string;
|
|
2088
|
+
/** Index of this dot's row in {@link DottedChartModel.rows}. */
|
|
2089
|
+
rowIndex: number;
|
|
2090
|
+
/** The normalized event (activity, start, end, resource, attributes). */
|
|
2091
|
+
event: NormalizedEvent;
|
|
2092
|
+
/** The event's position on the x axis, in the unit `x` implies (always milliseconds). */
|
|
2093
|
+
x: number;
|
|
2094
|
+
}
|
|
2095
|
+
/** One case, placed on the chart. */
|
|
2096
|
+
interface DottedChartRow {
|
|
2097
|
+
kind: "row";
|
|
2098
|
+
caseId: string;
|
|
2099
|
+
/** Position in `rows` — top row is `0`. */
|
|
2100
|
+
index: number;
|
|
2101
|
+
start: number;
|
|
2102
|
+
end: number;
|
|
2103
|
+
duration: number;
|
|
2104
|
+
eventCount: number;
|
|
2105
|
+
firstActivity: string;
|
|
2106
|
+
lastActivity: string;
|
|
2107
|
+
/** This row's dots are `dots.slice(dotStart, dotEnd)`, in time order. */
|
|
2108
|
+
dotStart: number;
|
|
2109
|
+
dotEnd: number;
|
|
2110
|
+
}
|
|
2111
|
+
/** What {@link computeDots} returns. */
|
|
2112
|
+
interface DottedChartModel {
|
|
2113
|
+
x: DottedChartX;
|
|
2114
|
+
sort: DottedChartSort;
|
|
2115
|
+
rows: DottedChartRow[];
|
|
2116
|
+
/** Every dot, grouped by row in `rows` order, each row's dots in time order. */
|
|
2117
|
+
dots: DottedChartDot[];
|
|
2118
|
+
/** The x extent to scale against. Never zero-width. */
|
|
2119
|
+
domain: [number, number];
|
|
2120
|
+
}
|
|
2121
|
+
interface ComputeDotsOptions {
|
|
2122
|
+
x?: DottedChartX;
|
|
2123
|
+
sort?: DottedChartSort;
|
|
2124
|
+
}
|
|
2125
|
+
/**
|
|
2126
|
+
* Build the dotted-chart model for a log.
|
|
2127
|
+
*
|
|
2128
|
+
* Deterministic: the same log and options always yield the same rows, dots and domain.
|
|
2129
|
+
* Events whose start could not be parsed are left out (they have no place on a time axis);
|
|
2130
|
+
* a case left with no placeable event is left out too.
|
|
2131
|
+
*/
|
|
2132
|
+
declare function computeDots(log: AnyLog, options?: ComputeDotsOptions): DottedChartModel;
|
|
2133
|
+
/**
|
|
2134
|
+
* Case ids of the rows a brush covers, in `rows` order.
|
|
2135
|
+
*
|
|
2136
|
+
* A row is covered when its index is in `[firstRow, lastRow]` (inclusive, either order) AND
|
|
2137
|
+
* at least one of its dots lies in the x range `[x0, x1]` (inclusive, either order). The
|
|
2138
|
+
* x test is what makes a brush over an empty stretch of time select nothing.
|
|
2139
|
+
*/
|
|
2140
|
+
declare function casesInBrush(model: DottedChartModel, rowRange: readonly [number, number], xRange: readonly [number, number]): string[];
|
|
2141
|
+
/** One entry of a {@link rankCategoryColors} legend. */
|
|
2142
|
+
interface DottedChartCategory extends ActivityColor {
|
|
2143
|
+
key: string;
|
|
2144
|
+
/** How many dots carry this category. */
|
|
2145
|
+
count: number;
|
|
2146
|
+
}
|
|
2147
|
+
/**
|
|
2148
|
+
* Colour arbitrary category keys (resources, a caller's own grouping) with the SAME budget
|
|
2149
|
+
* `activityColorScale` uses: the {@link ACTIVITY_COLOR_SLOTS} most frequent keys take
|
|
2150
|
+
* `--chart-1 …`, every other key shares {@link ACTIVITY_OTHER_TOKEN} and is flagged
|
|
2151
|
+
* `pattern: "other"`. Ranked by count descending, ties by key. Returns token names only.
|
|
2152
|
+
*/
|
|
2153
|
+
declare function rankCategoryColors(keys: readonly string[]): DottedChartCategory[];
|
|
2154
|
+
|
|
2155
|
+
/**
|
|
2156
|
+
* Every user-visible string `DottedChart` (RM-059) renders. `{name}` placeholders are
|
|
2157
|
+
* filled at render; override any subset through the component's `labels` prop to localize.
|
|
2158
|
+
*/
|
|
2159
|
+
interface DottedChartLabels {
|
|
2160
|
+
/** Accessible name of the plot and its keyboard cursor. */
|
|
2161
|
+
chart: string;
|
|
2162
|
+
/** `{cases}`, `{events}`, `{from}`, `{to}`, `{sort}`, `{colorBy}` — the parallel summary. */
|
|
2163
|
+
summary: string;
|
|
2164
|
+
sortStart: string;
|
|
2165
|
+
sortEnd: string;
|
|
2166
|
+
sortDuration: string;
|
|
2167
|
+
sortStartDay: string;
|
|
2168
|
+
colorByActivity: string;
|
|
2169
|
+
colorByResource: string;
|
|
2170
|
+
colorByCustom: string;
|
|
2171
|
+
/** `{caseId}`, `{events}`, `{duration}`, `{activities}` — spoken for a focused case row. */
|
|
2172
|
+
row: string;
|
|
2173
|
+
/** `{activity}`, `{time}`, `{caseId}` — spoken/shown for one event. */
|
|
2174
|
+
dot: string;
|
|
2175
|
+
/** `{resource}` — appended to a dot tooltip when the event has a resource. */
|
|
2176
|
+
dotResource: string;
|
|
2177
|
+
eventsOne: string;
|
|
2178
|
+
eventsOther: string;
|
|
2179
|
+
casesOne: string;
|
|
2180
|
+
casesOther: string;
|
|
2181
|
+
/** `{count}` more activities past the spoken prefix of a long trace. */
|
|
2182
|
+
moreActivities: string;
|
|
2183
|
+
/** `{cases}` — visible count of the current selection. */
|
|
2184
|
+
selectionCount: string;
|
|
2185
|
+
axisAbsolute: string;
|
|
2186
|
+
axisRelative: string;
|
|
2187
|
+
axisDay: string;
|
|
2188
|
+
axisWeek: string;
|
|
2189
|
+
/** The legend entry every category past the colour budget shares. */
|
|
2190
|
+
other: string;
|
|
2191
|
+
/** Category key for an event that carries no resource. */
|
|
2192
|
+
noResource: string;
|
|
2193
|
+
tableCaption: string;
|
|
2194
|
+
columnCase: string;
|
|
2195
|
+
columnFirstActivity: string;
|
|
2196
|
+
columnLastActivity: string;
|
|
2197
|
+
columnStart: string;
|
|
2198
|
+
columnEnd: string;
|
|
2199
|
+
columnDuration: string;
|
|
2200
|
+
columnEvents: string;
|
|
2201
|
+
columnState: string;
|
|
2202
|
+
selected: string;
|
|
2203
|
+
empty: string;
|
|
2204
|
+
emptyBody: string;
|
|
2205
|
+
}
|
|
2206
|
+
/** The shipped English labels. */
|
|
2207
|
+
declare const DOTTED_CHART_DEFAULT_LABELS: Readonly<DottedChartLabels>;
|
|
2208
|
+
|
|
2209
|
+
/** Dot radius in CSS pixels — a categorical marker, not an area encoding. */
|
|
2210
|
+
declare const DOTTED_CHART_DOT_RADIUS = 2;
|
|
2211
|
+
/** What a brush (or a committed keyboard range) emits. A subset of `/core`'s `FilterSpec`. */
|
|
2212
|
+
type DottedChartFilterIntent = Extract<FilterSpec, {
|
|
2213
|
+
kind: "cases";
|
|
2214
|
+
}>;
|
|
2215
|
+
/** How dots are coloured. A function returns a CATEGORY KEY, never a colour. */
|
|
2216
|
+
type DottedChartColor = "activity" | "resource" | ((row: EventRow) => string);
|
|
2217
|
+
/** A datum under the cursor: a case row (keyboard) or one event dot (pointer). */
|
|
2218
|
+
type DottedChartDatum = DottedChartRow | DottedChartDot;
|
|
2219
|
+
interface DottedChartProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSelect" | "title" | "color"> {
|
|
2220
|
+
log: EventLog;
|
|
2221
|
+
/** How the x axis places an event. @default "absolute" */
|
|
2222
|
+
x?: DottedChartX;
|
|
2223
|
+
/** How case rows are ordered, top to bottom. @default "start" */
|
|
2224
|
+
sort?: DottedChartSort;
|
|
2225
|
+
/**
|
|
2226
|
+
* What colours a dot. `"activity"` reads `colorScale`; `"resource"` and a function rank
|
|
2227
|
+
* their category keys onto the same `--chart-1 …` budget. @default "activity"
|
|
2228
|
+
*/
|
|
2229
|
+
color?: DottedChartColor;
|
|
2230
|
+
/** The shared activity colour scale — hand `ProcessMap` the same instance. Built from `log` when omitted. */
|
|
2231
|
+
colorScale?: ActivityColorScale;
|
|
2232
|
+
/** Case ids to highlight; every other dot dims. */
|
|
2233
|
+
selectedCaseIds?: readonly string[];
|
|
2234
|
+
/** Fires with the case ids a click, brush or keyboard range selects. */
|
|
2235
|
+
onSelect?: (caseIds: string[]) => void;
|
|
2236
|
+
/** Fires once when a brush is released (or a keyboard range committed), with ids in row order. */
|
|
2237
|
+
onFilterIntent?: (intent: DottedChartFilterIntent) => void;
|
|
2238
|
+
/** Card title — write the conclusion, not "Dotted chart". */
|
|
2239
|
+
title?: ReactNode;
|
|
2240
|
+
/** Prose under the title. */
|
|
2241
|
+
description?: ReactNode;
|
|
2242
|
+
/** Body height in CSS pixels (legend + plot + axis). @default 360 */
|
|
2243
|
+
height?: number;
|
|
2244
|
+
/** Render the accessible table twin instead of the plot. @default false */
|
|
2245
|
+
tableView?: boolean;
|
|
2246
|
+
/** No log yet. Renders the frame's skeleton. */
|
|
2247
|
+
loading?: boolean;
|
|
2248
|
+
/** Override any user-visible string. */
|
|
2249
|
+
labels?: Partial<DottedChartLabels>;
|
|
2250
|
+
}
|
|
2251
|
+
/**
|
|
2252
|
+
* The dotted chart.
|
|
2253
|
+
*
|
|
2254
|
+
* @example
|
|
2255
|
+
* ```tsx
|
|
2256
|
+
* const scale = useMemo(() => activityColorScale(fullGraph), [fullGraph]);
|
|
2257
|
+
* <DottedChart
|
|
2258
|
+
* log={explorer.filteredLog}
|
|
2259
|
+
* colorScale={scale}
|
|
2260
|
+
* sort="duration"
|
|
2261
|
+
* onFilterIntent={explorer.applyIntent}
|
|
2262
|
+
* />
|
|
2263
|
+
* ```
|
|
2264
|
+
*/
|
|
2265
|
+
declare const DottedChart: react.ForwardRefExoticComponent<DottedChartProps & react.RefAttributes<HTMLDivElement>>;
|
|
2266
|
+
|
|
2267
|
+
/**
|
|
2268
|
+
* Segment occurrences — RM-060.
|
|
2269
|
+
*
|
|
2270
|
+
* A performance spectrum (ProM's PSM) draws one line per case through a FIXED, chosen
|
|
2271
|
+
* sequence of segments, where a segment is one directly-follows pair `from → to`. That
|
|
2272
|
+
* needs something `TransitionStats` does not carry: the individual, time-ordered
|
|
2273
|
+
* OCCURRENCES of a pair (which case, when it entered, when it left), not one aggregate
|
|
2274
|
+
* across the whole log. Batching, FIFO violations and queue build-up are visible only
|
|
2275
|
+
* in the occurrences.
|
|
2276
|
+
*
|
|
2277
|
+
* ## What an occurrence measures
|
|
2278
|
+
*
|
|
2279
|
+
* `start` is the moment the `from` event COMPLETES and `end` the moment the `to` event
|
|
2280
|
+
* STARTS — the same idle-time reading `discoverGraph` defaults to, so a spectrum row and
|
|
2281
|
+
* the map's edge median agree about one pair. For atomic events (the common case) start
|
|
2282
|
+
* and completion coincide, so this is simply the two event timestamps. Overlapping
|
|
2283
|
+
* (parallel) events would give `end < start`; `end` is clamped to `start`, so `duration`
|
|
2284
|
+
* is never negative and a line never runs backwards.
|
|
2285
|
+
*
|
|
2286
|
+
* Deterministic and framework-free: no React, no `@elabs-ai/components-*`.
|
|
2287
|
+
*/
|
|
2288
|
+
|
|
2289
|
+
/** One row of a spectrum: the directly-follows pair `from → to`. */
|
|
2290
|
+
interface SegmentDefinition {
|
|
2291
|
+
from: string;
|
|
2292
|
+
to: string;
|
|
2293
|
+
/** Display label. Defaults to `"from → to"` in a view. */
|
|
2294
|
+
label?: string;
|
|
2295
|
+
}
|
|
2296
|
+
/** One case passing through one segment. */
|
|
2297
|
+
interface SegmentOccurrence {
|
|
2298
|
+
/** The segment's key — {@link segmentKey}`(from, to)`. */
|
|
2299
|
+
segment: string;
|
|
2300
|
+
caseId: string;
|
|
2301
|
+
/** When the `from` event completed, epoch ms. */
|
|
2302
|
+
start: number;
|
|
2303
|
+
/** When the `to` event started, epoch ms. Never before `start`. */
|
|
2304
|
+
end: number;
|
|
2305
|
+
/** `end - start`, in ms. */
|
|
2306
|
+
duration: number;
|
|
2307
|
+
}
|
|
2308
|
+
/** A duration quartile, `1` = fastest quarter, `4` = slowest. */
|
|
2309
|
+
type DurationQuartile = 1 | 2 | 3 | 4;
|
|
2310
|
+
|
|
2311
|
+
/**
|
|
2312
|
+
* The pure model behind `PerformanceSpectrum` — RM-060.
|
|
2313
|
+
*
|
|
2314
|
+
* Everything here is React-free and unit-tested on its own: grouping occurrences into
|
|
2315
|
+
* rows (with each occurrence's quartile read against ITS OWN segment), the aggregated
|
|
2316
|
+
* mode's time bins, the shared time domain and ticks, and the brush's case lookup. The
|
|
2317
|
+
* component only lays these out and paints them.
|
|
2318
|
+
*/
|
|
2319
|
+
|
|
2320
|
+
/** One occurrence, ready to paint: its quartile is already resolved. */
|
|
2321
|
+
interface SpectrumLine extends SegmentOccurrence {
|
|
2322
|
+
quartile: DurationQuartile;
|
|
2323
|
+
}
|
|
2324
|
+
/** One `binSize` bucket of one row in aggregated mode. */
|
|
2325
|
+
interface SpectrumBin {
|
|
2326
|
+
segment: string;
|
|
2327
|
+
/** Bucket start, epoch ms (inclusive). */
|
|
2328
|
+
start: number;
|
|
2329
|
+
/** Bucket end, epoch ms (exclusive). */
|
|
2330
|
+
end: number;
|
|
2331
|
+
/** Occurrences entering the segment inside the bucket. */
|
|
2332
|
+
count: number;
|
|
2333
|
+
/** Median duration of those occurrences, ms. */
|
|
2334
|
+
medianDuration: number;
|
|
2335
|
+
/** The median of their quartiles, rounded up — the bar's fill. */
|
|
2336
|
+
quartile: DurationQuartile;
|
|
2337
|
+
}
|
|
2338
|
+
/** One spectrum row: a segment and everything drawn in it. */
|
|
2339
|
+
interface SpectrumRow {
|
|
2340
|
+
key: string;
|
|
2341
|
+
definition: SegmentDefinition;
|
|
2342
|
+
/** Sorted by `start`, then `end`, then `caseId` — the keyboard cursor's walk order. */
|
|
2343
|
+
lines: SpectrumLine[];
|
|
2344
|
+
/** Distinct cases with at least one occurrence. */
|
|
2345
|
+
caseCount: number;
|
|
2346
|
+
medianDuration: number;
|
|
2347
|
+
p90Duration: number;
|
|
2348
|
+
}
|
|
2349
|
+
/**
|
|
2350
|
+
* Groups `occurrences` into one row per definition in `order` (duplicates dropped),
|
|
2351
|
+
* resolving each occurrence's quartile against its own segment's distribution.
|
|
2352
|
+
*/
|
|
2353
|
+
declare function buildSpectrumRows(order: readonly SegmentDefinition[], occurrences: readonly SegmentOccurrence[]): SpectrumRow[];
|
|
2354
|
+
/**
|
|
2355
|
+
* The aggregated mode's bars for one row: occurrences bucketed by the time they ENTER the
|
|
2356
|
+
* segment, `binSize` ms wide, aligned to `origin`. Only non-empty buckets are returned,
|
|
2357
|
+
* in time order, so a sparse year at a one-minute bin costs nothing for the empty minutes.
|
|
2358
|
+
*/
|
|
2359
|
+
declare function aggregateSegmentBins(row: SpectrumRow, binSize: number, origin: number): SpectrumBin[];
|
|
2360
|
+
/**
|
|
2361
|
+
* The shared time domain `[min start, max end]` across every row. A degenerate domain
|
|
2362
|
+
* (one instant, or nothing at all) is widened by one second so a scale never divides by 0.
|
|
2363
|
+
*/
|
|
2364
|
+
declare function spectrumDomain(rows: readonly SpectrumRow[]): [number, number];
|
|
2365
|
+
/** `count` evenly spaced tick instants across `domain`, both ends included. */
|
|
2366
|
+
declare function spectrumTicks(domain: readonly [number, number], count?: number): number[];
|
|
2367
|
+
/**
|
|
2368
|
+
* Case ids with at least one occurrence overlapping `[from, to]` (inclusive), in the order
|
|
2369
|
+
* they are first met walking rows top to bottom and each row in time order.
|
|
2370
|
+
*/
|
|
2371
|
+
declare function casesInRange(rows: readonly SpectrumRow[], from: number, to: number): string[];
|
|
2372
|
+
|
|
2373
|
+
/** Every user-visible string `PerformanceSpectrum` renders. `{name}` placeholders fill. */
|
|
2374
|
+
interface PerformanceSpectrumLabels {
|
|
2375
|
+
/** Accessible name of the whole view. */
|
|
2376
|
+
label: string;
|
|
2377
|
+
/** `{from}`, `{to}` — a row's accessible name and default visible label. */
|
|
2378
|
+
segment: string;
|
|
2379
|
+
/** Appended to a selected row's accessible name. */
|
|
2380
|
+
selected: string;
|
|
2381
|
+
/** `{count}`, `{cases}`, `{median}`, `{p90}` — a row's parallel summary. */
|
|
2382
|
+
rowSummary: string;
|
|
2383
|
+
/** `{caseId}`, `{start}`, `{end}`, `{duration}`, `{quartile}` — one line, spoken. */
|
|
2384
|
+
occurrence: string;
|
|
2385
|
+
/** `{start}`, `{end}`, `{count}`, `{median}`, `{quartile}` — one aggregated bar, spoken. */
|
|
2386
|
+
bin: string;
|
|
2387
|
+
tooltipSegment: string;
|
|
2388
|
+
tooltipStart: string;
|
|
2389
|
+
tooltipEnd: string;
|
|
2390
|
+
tooltipDuration: string;
|
|
2391
|
+
tooltipQuartile: string;
|
|
2392
|
+
tooltipCount: string;
|
|
2393
|
+
tooltipMedian: string;
|
|
2394
|
+
/** `{n}` — a quartile's short name. */
|
|
2395
|
+
quartile: string;
|
|
2396
|
+
quartileFastest: string;
|
|
2397
|
+
quartileSlowest: string;
|
|
2398
|
+
/** Heading of the colour key. */
|
|
2399
|
+
legend: string;
|
|
2400
|
+
/** Accessible name of the time-axis brush track. */
|
|
2401
|
+
brush: string;
|
|
2402
|
+
brushHint: string;
|
|
2403
|
+
/** `{start}`, `{end}`, `{count}` — announced when a range is set. */
|
|
2404
|
+
brushRange: string;
|
|
2405
|
+
columnSegment: string;
|
|
2406
|
+
columnCases: string;
|
|
2407
|
+
columnMedian: string;
|
|
2408
|
+
columnP90: string;
|
|
2409
|
+
tableCaption: string;
|
|
2410
|
+
loading: string;
|
|
2411
|
+
empty: string;
|
|
2412
|
+
emptyBody: string;
|
|
2413
|
+
}
|
|
2414
|
+
/** The shipped English labels. */
|
|
2415
|
+
declare const PERFORMANCE_SPECTRUM_DEFAULT_LABELS: Readonly<PerformanceSpectrumLabels>;
|
|
2416
|
+
|
|
2417
|
+
/** One day in ms — the aggregated mode's default bucket. */
|
|
2418
|
+
declare const PERFORMANCE_SPECTRUM_DEFAULT_BIN_SIZE = 86400000;
|
|
2419
|
+
/** Default row height in CSS px when `height` is not given. */
|
|
2420
|
+
declare const PERFORMANCE_SPECTRUM_ROW_HEIGHT = 56;
|
|
2421
|
+
/** Default number of segment rows. */
|
|
2422
|
+
declare const PERFORMANCE_SPECTRUM_SEGMENT_LIMIT = 12;
|
|
2423
|
+
/** Which segments a spectrum shows, in row order. */
|
|
2424
|
+
type PerformanceSpectrumOrder = SegmentDefinition[] | "frequency" | {
|
|
2425
|
+
variantId: string;
|
|
2426
|
+
};
|
|
2427
|
+
/** The one intent the spectrum emits — a `/core` `FilterSpec`, straight into `filterLog`. */
|
|
2428
|
+
type PerformanceSpectrumFilterIntent = Extract<FilterSpec, {
|
|
2429
|
+
kind: "cases";
|
|
2430
|
+
}>;
|
|
2431
|
+
/** Props for {@link PerformanceSpectrum}. */
|
|
2432
|
+
interface PerformanceSpectrumProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
|
|
2433
|
+
log: EventLog;
|
|
2434
|
+
/** Row order: explicit segments, the busiest transitions, or one variant's path. @default "frequency" */
|
|
2435
|
+
order?: PerformanceSpectrumOrder;
|
|
2436
|
+
/** At most this many rows, whichever `order` is used. @default 12 */
|
|
2437
|
+
segmentLimit?: number;
|
|
2438
|
+
/** One line per occurrence, or one bar per time bucket. @default "lines" */
|
|
2439
|
+
mode?: "lines" | "aggregated";
|
|
2440
|
+
/** Bucket width in ms, aggregated mode only. @default 86_400_000 (1 day) */
|
|
2441
|
+
binSize?: number;
|
|
2442
|
+
/** Rows whose segment is (or touches) the selected transition/activity are marked. */
|
|
2443
|
+
selection?: ProcessSelection | null;
|
|
2444
|
+
/** When given, the time axis becomes a brush that emits `{ kind: "cases", ids }`. */
|
|
2445
|
+
onFilterIntent?: (intent: PerformanceSpectrumFilterIntent) => void;
|
|
2446
|
+
/** Click or `Enter` on an occurrence (lines) or on a bar's first case (aggregated). */
|
|
2447
|
+
onCaseSelect?: (caseId: string, occurrence: SpectrumLine) => void;
|
|
2448
|
+
/** Total plot height in CSS px, split evenly across rows (min 24 px a row). */
|
|
2449
|
+
height?: number;
|
|
2450
|
+
/** Render the accessible table twin instead of the chart. @default false */
|
|
2451
|
+
tableView?: boolean;
|
|
2452
|
+
/** Data not ready yet — renders the loading panel. */
|
|
2453
|
+
loading?: boolean;
|
|
2454
|
+
/** Override any user-visible string. */
|
|
2455
|
+
labels?: Partial<PerformanceSpectrumLabels>;
|
|
2456
|
+
}
|
|
2457
|
+
/**
|
|
2458
|
+
* The performance spectrum.
|
|
2459
|
+
*
|
|
2460
|
+
* @example
|
|
2461
|
+
* ```tsx
|
|
2462
|
+
* <PerformanceSpectrum
|
|
2463
|
+
* log={explorer.filteredLog}
|
|
2464
|
+
* order="frequency"
|
|
2465
|
+
* onFilterIntent={(intent) => setCaseFilter(intent)}
|
|
2466
|
+
* />
|
|
2467
|
+
* ```
|
|
2468
|
+
*/
|
|
2469
|
+
declare const PerformanceSpectrum: react.ForwardRefExoticComponent<PerformanceSpectrumProps & react.RefAttributes<HTMLDivElement>>;
|
|
2470
|
+
|
|
2471
|
+
/** The metric the overlay paints when none is given: case frequency on both marks. */
|
|
2472
|
+
declare const CONFORMANCE_OVERLAY_DEFAULT_METRIC: ProcessMetricSpec;
|
|
2473
|
+
/** Props for {@link ConformanceOverlay}. `onSelect` shadows the DOM handler, so it is omitted. */
|
|
2474
|
+
interface ConformanceOverlayProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSelect"> {
|
|
2475
|
+
/** The discovered graph to overlay. */
|
|
2476
|
+
graph: ProcessGraph;
|
|
2477
|
+
/** The replay result (`tokenReplay`) against the reference model. */
|
|
2478
|
+
conformance: ConformanceResult;
|
|
2479
|
+
/** Which readings the nodes and edges print. @default case frequency */
|
|
2480
|
+
metric?: ProcessMetricSpec;
|
|
2481
|
+
/** @default "TB" */
|
|
2482
|
+
direction?: FlowLayoutDirection;
|
|
2483
|
+
/** Controlled selection, passed straight to `ProcessMap`. */
|
|
2484
|
+
selection?: ProcessSelection | null;
|
|
2485
|
+
onSelect?: ProcessMapProps["onSelect"];
|
|
2486
|
+
onFilterIntent?: ProcessMapProps["onFilterIntent"];
|
|
2487
|
+
/** Render the accessible table twin instead of the canvas. @default false */
|
|
2488
|
+
tableView?: boolean;
|
|
2489
|
+
/** No graph or replay yet. Renders the map's loading panel and hides the legend. */
|
|
2490
|
+
loading?: boolean;
|
|
2491
|
+
/** Override the legend's words. */
|
|
2492
|
+
labels?: Partial<ConformanceStateLabels>;
|
|
2493
|
+
}
|
|
2494
|
+
/**
|
|
2495
|
+
* The conformance overlay.
|
|
2496
|
+
*
|
|
2497
|
+
* @example
|
|
2498
|
+
* ```tsx
|
|
2499
|
+
* const model = useMemo(() => liftHappyPath(happyPath), [happyPath]);
|
|
2500
|
+
* const conformance = useMemo(() => tokenReplay(log, model), [log, model]);
|
|
2501
|
+
* <ConformanceOverlay graph={graph} conformance={conformance} />
|
|
2502
|
+
* ```
|
|
2503
|
+
*/
|
|
2504
|
+
declare const ConformanceOverlay: react.ForwardRefExoticComponent<ConformanceOverlayProps & react.RefAttributes<HTMLDivElement>>;
|
|
2505
|
+
|
|
2506
|
+
/** Props for {@link ConformanceStateMark}. */
|
|
2507
|
+
interface ConformanceStateMarkProps extends HTMLAttributes<HTMLSpanElement> {
|
|
2508
|
+
state: ConformanceState;
|
|
2509
|
+
/** Override the state's word. */
|
|
2510
|
+
labels?: Partial<ConformanceStateLabels>;
|
|
2511
|
+
}
|
|
2512
|
+
/**
|
|
2513
|
+
* One state as glyph + coloured word — the text form a table cell prints. The glyph is
|
|
2514
|
+
* `aria-hidden`; the word is the accessible reading.
|
|
2515
|
+
*/
|
|
2516
|
+
declare const ConformanceStateMark: react.ForwardRefExoticComponent<ConformanceStateMarkProps & react.RefAttributes<HTMLSpanElement>>;
|
|
2517
|
+
/** Props for {@link ConformanceLegend}. */
|
|
2518
|
+
interface ConformanceLegendProps extends HTMLAttributes<HTMLDivElement> {
|
|
2519
|
+
/** Override any state word or the title. */
|
|
2520
|
+
labels?: Partial<ConformanceStateLabels>;
|
|
2521
|
+
}
|
|
2522
|
+
/** The three-state key: tone + glyph + dash + word per entry. */
|
|
2523
|
+
declare const ConformanceLegend: react.ForwardRefExoticComponent<ConformanceLegendProps & react.RefAttributes<HTMLDivElement>>;
|
|
2524
|
+
|
|
2525
|
+
/** What a row stands for: a deviation type, or the cases with none. */
|
|
2526
|
+
type ViolationRowKind = DeviationType | "conforming";
|
|
2527
|
+
/** One row of {@link ViolationList}. */
|
|
2528
|
+
interface ViolationRow {
|
|
2529
|
+
kind: ViolationRowKind;
|
|
2530
|
+
/** Deviations of this type across all cases (`0` for `"conforming"`). */
|
|
2531
|
+
deviations: number;
|
|
2532
|
+
/** Ids of the cases carrying at least one deviation of this type, in log order. */
|
|
2533
|
+
caseIds: string[];
|
|
2534
|
+
/** `caseIds.length / traces.length`; `0` for an empty log. */
|
|
2535
|
+
share: number;
|
|
2536
|
+
}
|
|
2537
|
+
/** The filter a row emits — a strict subset of `/core`'s `FilterSpec`. */
|
|
2538
|
+
type ViolationFilterIntent = Extract<FilterSpec, {
|
|
2539
|
+
kind: "cases";
|
|
2540
|
+
}>;
|
|
2541
|
+
/**
|
|
2542
|
+
* The rows {@link ViolationList} renders, in order: every type with deviations, by count
|
|
2543
|
+
* descending, then `"conforming"`.
|
|
2544
|
+
*/
|
|
2545
|
+
declare function violationRows(conformance: ConformanceResult): ViolationRow[];
|
|
2546
|
+
/** Every user-visible string. `{name}` placeholders are filled at render. */
|
|
2547
|
+
interface ViolationListLabels {
|
|
2548
|
+
undesired: string;
|
|
2549
|
+
skipped: string;
|
|
2550
|
+
wrongOrder: string;
|
|
2551
|
+
wrongStart: string;
|
|
2552
|
+
incomplete: string;
|
|
2553
|
+
conforming: string;
|
|
2554
|
+
columnType: string;
|
|
2555
|
+
columnShare: string;
|
|
2556
|
+
columnCases: string;
|
|
2557
|
+
/** `{conforming}`, `{total}`. */
|
|
2558
|
+
caption: string;
|
|
2559
|
+
/** Appended to the caption when rows can be chosen. */
|
|
2560
|
+
captionFilter: string;
|
|
2561
|
+
loading: string;
|
|
2562
|
+
empty: string;
|
|
2563
|
+
emptyBody: string;
|
|
2564
|
+
}
|
|
2565
|
+
/** The shipped English labels. */
|
|
2566
|
+
declare const VIOLATION_LIST_DEFAULT_LABELS: Readonly<ViolationListLabels>;
|
|
2567
|
+
/** Props for {@link ViolationList}. */
|
|
2568
|
+
interface ViolationListProps extends HTMLAttributes<HTMLDivElement> {
|
|
2569
|
+
/** The replay result (`tokenReplay`). */
|
|
2570
|
+
conformance: ConformanceResult;
|
|
2571
|
+
/** When given, each row emits `{ kind: "cases", ids }` for its cases. */
|
|
2572
|
+
onFilterIntent?: (intent: ViolationFilterIntent) => void;
|
|
2573
|
+
/** No replay yet. Renders the loading panel rather than an empty table. */
|
|
2574
|
+
loading?: boolean;
|
|
2575
|
+
/** Override any user-visible string. */
|
|
2576
|
+
labels?: Partial<ViolationListLabels>;
|
|
2577
|
+
}
|
|
2578
|
+
/**
|
|
2579
|
+
* The violation list.
|
|
2580
|
+
*
|
|
2581
|
+
* @example
|
|
2582
|
+
* ```tsx
|
|
2583
|
+
* <ViolationList
|
|
2584
|
+
* conformance={tokenReplay(log, liftHappyPath(path))}
|
|
2585
|
+
* onFilterIntent={(intent) => explorer.applyIntent(intent)}
|
|
2586
|
+
* />
|
|
2587
|
+
* ```
|
|
2588
|
+
*/
|
|
2589
|
+
declare const ViolationList: react.ForwardRefExoticComponent<ViolationListProps & react.RefAttributes<HTMLDivElement>>;
|
|
2590
|
+
|
|
2591
|
+
/** Every user-visible string of the editor. `{name}` placeholders are filled at render. */
|
|
2592
|
+
interface HappyPathEditorLabels {
|
|
2593
|
+
/** Accessible name of the canvas. `{path}` — the happy path's label. */
|
|
2594
|
+
canvas: string;
|
|
2595
|
+
/** Eyebrow above a step. `{n}` — the one-based position. */
|
|
2596
|
+
step: string;
|
|
2597
|
+
/** Accessible name of a step node. `{n}`, `{activity}`, `{flags}`. */
|
|
2598
|
+
stepName: string;
|
|
2599
|
+
/** Shown as a step's title while its activity is empty. */
|
|
2600
|
+
untitled: string;
|
|
2601
|
+
/** Accessible name of a step's activity field. `{n}`. */
|
|
2602
|
+
activity: string;
|
|
2603
|
+
/** Placeholder of the free-text activity field. */
|
|
2604
|
+
activityPlaceholder: string;
|
|
2605
|
+
optional: string;
|
|
2606
|
+
repeatable: string;
|
|
2607
|
+
/** Accessible name of a step's optional switch. `{activity}`. */
|
|
2608
|
+
optionalFor: string;
|
|
2609
|
+
/** Accessible name of a step's repeatable switch. `{activity}`. */
|
|
2610
|
+
repeatableFor: string;
|
|
2611
|
+
remove: string;
|
|
2612
|
+
/** Accessible name of a step's remove button. `{activity}`. */
|
|
2613
|
+
removeFor: string;
|
|
2614
|
+
/** Accessible name of an edge's insert button. `{before}`, `{after}`. */
|
|
2615
|
+
insertStep: string;
|
|
2616
|
+
/** Label of the tail placeholder that appends a step. */
|
|
2617
|
+
addStep: string;
|
|
2618
|
+
}
|
|
2619
|
+
/** The shipped English labels. */
|
|
2620
|
+
declare const HAPPY_PATH_EDITOR_DEFAULT_LABELS: Readonly<HappyPathEditorLabels>;
|
|
2621
|
+
/** What a step node reads from its editor. */
|
|
2622
|
+
interface HappyPathEditorContextValue {
|
|
2623
|
+
labels: HappyPathEditorLabels;
|
|
2624
|
+
availableActivities: readonly string[] | undefined;
|
|
2625
|
+
updateStep: (index: number, patch: Partial<HappyPathStep>) => void;
|
|
2626
|
+
removeStep: (index: number) => void;
|
|
2627
|
+
}
|
|
2628
|
+
/** Provided by `HappyPathEditor`; a step rendered on its own reads inert defaults. */
|
|
2629
|
+
declare const HappyPathEditorContext: react.Context<HappyPathEditorContextValue>;
|
|
2630
|
+
/** Read the editor's labels and actions. */
|
|
2631
|
+
declare function useHappyPathEditor(): HappyPathEditorContextValue;
|
|
2632
|
+
|
|
2633
|
+
/** Id of the node for the step at `index`. */
|
|
2634
|
+
declare function happyPathStepNodeId(index: number): string;
|
|
2635
|
+
/**
|
|
2636
|
+
* The activity a newly inserted step starts with: the first available activity the path
|
|
2637
|
+
* does not use yet, else the first available one, else empty (typed in afterwards).
|
|
2638
|
+
*/
|
|
2639
|
+
declare function nextHappyPathActivity(path: HappyPath, availableActivities: readonly string[] | undefined): string;
|
|
2640
|
+
/** `path` with a new step inserted at `index`. */
|
|
2641
|
+
declare function insertHappyPathStep(path: HappyPath, index: number, step: HappyPathStep): HappyPath;
|
|
2642
|
+
/** `path` without the step at `index`. The neighbours become consecutive. */
|
|
2643
|
+
declare function removeHappyPathStep(path: HappyPath, index: number): HappyPath;
|
|
2644
|
+
/** `path` with the step at `index` patched. `false` flags are dropped, not stored. */
|
|
2645
|
+
declare function updateHappyPathStep(path: HappyPath, index: number, patch: Partial<HappyPathStep>): HappyPath;
|
|
2646
|
+
/** Props for {@link HappyPathEditor}. `onChange` carries a path, so the DOM one is omitted. */
|
|
2647
|
+
interface HappyPathEditorProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
|
|
2648
|
+
value: HappyPath;
|
|
2649
|
+
/** Fires with the complete path after every edit. */
|
|
2650
|
+
onChange: (path: HappyPath) => void;
|
|
2651
|
+
/** Activities a step may pick from (e.g. the log's). Omit for free-text activities. */
|
|
2652
|
+
availableActivities?: string[];
|
|
2653
|
+
/** Override any user-visible string. */
|
|
2654
|
+
labels?: Partial<HappyPathEditorLabels>;
|
|
2655
|
+
}
|
|
2656
|
+
/**
|
|
2657
|
+
* The happy-path editor.
|
|
2658
|
+
*
|
|
2659
|
+
* @example
|
|
2660
|
+
* ```tsx
|
|
2661
|
+
* const [path, setPath] = useState<HappyPath>({ id: "p", label: "Order", steps: [] });
|
|
2662
|
+
* const conformance = useMemo(() => tokenReplay(log, liftHappyPath(path)), [log, path]);
|
|
2663
|
+
* <HappyPathEditor value={path} onChange={setPath} availableActivities={activities} />
|
|
2664
|
+
* ```
|
|
2665
|
+
*/
|
|
2666
|
+
declare const HappyPathEditor: react.ForwardRefExoticComponent<HappyPathEditorProps & react.RefAttributes<HTMLDivElement>>;
|
|
2667
|
+
|
|
2668
|
+
/** `data` carried by a {@link HappyPathStepFlowNode}. */
|
|
2669
|
+
interface HappyPathStepNodeData extends Record<string, unknown> {
|
|
2670
|
+
/** Zero-based position in the path. */
|
|
2671
|
+
index: number;
|
|
2672
|
+
step: HappyPathStep;
|
|
2673
|
+
}
|
|
2674
|
+
/** A happy-path step node. Register as `nodeTypes={{ "happy-path-step": … }}`. */
|
|
2675
|
+
type HappyPathStepFlowNode = Node<HappyPathStepNodeData, "happy-path-step">;
|
|
2676
|
+
/** One step of the happy-path editor. */
|
|
2677
|
+
declare function HappyPathStepNode(props: NodeProps<HappyPathStepFlowNode>): react.JSX.Element;
|
|
2678
|
+
|
|
2679
|
+
/** One side of the comparison. */
|
|
2680
|
+
interface ProcessCompareSide {
|
|
2681
|
+
/** How this side is named in headers, the KPI strip and the diff legend/labels. */
|
|
2682
|
+
label: string;
|
|
2683
|
+
/** A discovered graph. `undefined` while this side is still loading. */
|
|
2684
|
+
graph: ProcessGraph | undefined;
|
|
2685
|
+
/** The raw log, for `CompareKpiStrip`'s median-throughput reading. Optional. */
|
|
2686
|
+
log?: EventLog;
|
|
2687
|
+
}
|
|
2688
|
+
type ProcessCompareMode = "side-by-side" | "superimposed";
|
|
2689
|
+
interface ProcessCompareProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSelect"> {
|
|
2690
|
+
a: ProcessCompareSide;
|
|
2691
|
+
b: ProcessCompareSide;
|
|
2692
|
+
/** @default "side-by-side" */
|
|
2693
|
+
mode?: ProcessCompareMode;
|
|
2694
|
+
metric: ProcessMapProps["metric"];
|
|
2695
|
+
/** Shared abstraction, synced across both sides (or the one superimposed map). */
|
|
2696
|
+
abstraction: AbstractionOptions;
|
|
2697
|
+
onAbstractionChange(next: Partial<AbstractionOptions>): void;
|
|
2698
|
+
/** @default "TB" */
|
|
2699
|
+
direction?: FlowLayoutDirection;
|
|
2700
|
+
/** Neither side has a graph yet. Renders every map's own loading panel. @default false */
|
|
2701
|
+
loading?: boolean;
|
|
2702
|
+
/** Accessible name for the region. Defaults to the localized `process.compare.label`. */
|
|
2703
|
+
label?: string;
|
|
2704
|
+
}
|
|
2705
|
+
/**
|
|
2706
|
+
* Side-by-side or superimposed diff of two process maps.
|
|
2707
|
+
*
|
|
2708
|
+
* @example
|
|
2709
|
+
* ```tsx
|
|
2710
|
+
* <ProcessCompare
|
|
2711
|
+
* a={{ label: "Before", graph: beforeGraph }}
|
|
2712
|
+
* b={{ label: "After", graph: afterGraph }}
|
|
2713
|
+
* metric={{ node: "absolute_case", edge: "absolute" }}
|
|
2714
|
+
* abstraction={abstraction}
|
|
2715
|
+
* onAbstractionChange={setAbstraction}
|
|
2716
|
+
* />
|
|
2717
|
+
* ```
|
|
2718
|
+
*/
|
|
2719
|
+
declare const ProcessCompare: react.ForwardRefExoticComponent<ProcessCompareProps & react.RefAttributes<HTMLDivElement>>;
|
|
2720
|
+
|
|
2721
|
+
interface CompareSideProps extends HTMLAttributes<HTMLDivElement> {
|
|
2722
|
+
/** The host-supplied name for this side ("Before", "Q1", the log's own file name, …). */
|
|
2723
|
+
label: string;
|
|
2724
|
+
/** Forwarded to `ProcessMap` verbatim — everything this side's canvas needs. */
|
|
2725
|
+
map: Omit<ProcessMapProps, "className">;
|
|
2726
|
+
}
|
|
2727
|
+
/** One heading + one `ProcessMap`, stacked to fill its panel. */
|
|
2728
|
+
declare const CompareSide: react.ForwardRefExoticComponent<CompareSideProps & react.RefAttributes<HTMLDivElement>>;
|
|
2729
|
+
|
|
2730
|
+
/** Which side(s) of the diff an activity or transition survives in. */
|
|
2731
|
+
type DiffState = "common" | "aOnly" | "bOnly";
|
|
2732
|
+
/** One activity's or transition's diff — its identity, its state, and (when `"common"`) its delta. */
|
|
2733
|
+
interface DiffEntry<Stats> {
|
|
2734
|
+
id: string;
|
|
2735
|
+
state: DiffState;
|
|
2736
|
+
/** Present unless the element is `"bOnly"`. */
|
|
2737
|
+
a?: Stats;
|
|
2738
|
+
/** Present unless the element is `"aOnly"`. */
|
|
2739
|
+
b?: Stats;
|
|
2740
|
+
/** `b`'s reference value minus `a`'s. Only set for a `"common"` entry. */
|
|
2741
|
+
delta?: number;
|
|
2742
|
+
/** `b`'s reference value divided by `a`'s. Only set for a `"common"` entry with `a > 0`. */
|
|
2743
|
+
ratio?: number;
|
|
2744
|
+
}
|
|
2745
|
+
/** The full diff between two graphs. */
|
|
2746
|
+
interface ProcessGraphDiff {
|
|
2747
|
+
activities: DiffEntry<ActivityStats>[];
|
|
2748
|
+
transitions: DiffEntry<TransitionStats>[];
|
|
2749
|
+
totals: {
|
|
2750
|
+
a: ProcessGraph["totals"];
|
|
2751
|
+
b: ProcessGraph["totals"];
|
|
2752
|
+
};
|
|
2753
|
+
}
|
|
2754
|
+
|
|
2755
|
+
/** One side's raw input — a discovered graph, an event log, or (loading) neither. */
|
|
2756
|
+
interface CompareSideInput {
|
|
2757
|
+
graph?: ProcessGraph;
|
|
2758
|
+
log?: EventLog;
|
|
2759
|
+
}
|
|
2760
|
+
/** The two numbers {@link CompareKpiStrip} reads for one side. */
|
|
2761
|
+
interface CompareSideKpis {
|
|
2762
|
+
cases: number;
|
|
2763
|
+
/** Median case throughput, ms. Omitted when the side has no `log` to derive it from. */
|
|
2764
|
+
medianThroughput?: number;
|
|
2765
|
+
}
|
|
2766
|
+
/**
|
|
2767
|
+
* Cases and median throughput for one side, mirroring `useProcessExplorer`'s own `kpis`
|
|
2768
|
+
* derivation (`cases`/`medianThroughput` from a normalized log's per-case durations).
|
|
2769
|
+
* `medianThroughput` needs case-level duration samples that a bare `ProcessGraph` does not
|
|
2770
|
+
* carry (only per-activity/per-transition aggregates do) — so it is only derivable when the
|
|
2771
|
+
* caller also handed this side a `log`; a `graph`-only side reports cases alone.
|
|
2772
|
+
*/
|
|
2773
|
+
declare function resolveCompareKpis(side: CompareSideInput): CompareSideKpis;
|
|
2774
|
+
|
|
2775
|
+
interface CompareKpiStripSide {
|
|
2776
|
+
/** The host-supplied name for this side ("Before", "Q1", the log's own file name, …). */
|
|
2777
|
+
label: string;
|
|
2778
|
+
kpis: CompareSideKpis;
|
|
2779
|
+
}
|
|
2780
|
+
interface CompareKpiStripProps extends HTMLAttributes<HTMLDivElement> {
|
|
2781
|
+
a: CompareKpiStripSide;
|
|
2782
|
+
b: CompareKpiStripSide;
|
|
2783
|
+
loading?: boolean;
|
|
2784
|
+
}
|
|
2785
|
+
/** Compact KPI pairs for `ProcessCompare`: cases and median throughput, A vs B. */
|
|
2786
|
+
declare const CompareKpiStrip: react.ForwardRefExoticComponent<CompareKpiStripProps & react.RefAttributes<HTMLDivElement>>;
|
|
2787
|
+
|
|
2788
|
+
/**
|
|
2789
|
+
* diffToProcessGraph — turn a `ProcessGraphDiff` (`/core`'s `diffGraphs`, RM-064) into the
|
|
2790
|
+
* ONE `ProcessGraph` `ProcessCompare`'s superimposed mode hands to a single `ProcessMap`,
|
|
2791
|
+
* plus a synthetic `ActivityColorScale` that paints by diff state instead of by identity.
|
|
2792
|
+
*
|
|
2793
|
+
* `ProcessMap` (RM-051) is never forked or given a new prop for this: its existing
|
|
2794
|
+
* `colorScale` prop (RM-054) is the only per-activity colour hook it exposes, and
|
|
2795
|
+
* `ActivityColorScale` is a plain interface — nothing stops a second caller building one
|
|
2796
|
+
* keyed by diff state rather than by rank. Pure, no React; lives beside `process-compare.tsx`
|
|
2797
|
+
* rather than under `/core` because it is presentation shaping for ONE component (label
|
|
2798
|
+
* suffixes, colour tokens), not a reusable process-mining derivation.
|
|
2799
|
+
*/
|
|
2800
|
+
|
|
2801
|
+
/** Empty graph — the identity input for a side that has not discovered anything yet. */
|
|
2802
|
+
declare const EMPTY_PROCESS_GRAPH: ProcessGraph;
|
|
2803
|
+
/**
|
|
2804
|
+
* The three diff tokens the design asks for (RM-064's spec): `common` reads as success,
|
|
2805
|
+
* `aOnly` as the first chart series, `bOnly` as destructive. Semantic tokens only — no
|
|
2806
|
+
* literal colour is authored (`.claude/rules/conventions.md`'s styling rule).
|
|
2807
|
+
*/
|
|
2808
|
+
declare const DIFF_STATE_TOKEN: Record<DiffState, string>;
|
|
2809
|
+
/**
|
|
2810
|
+
* The ONE `ProcessGraph` a superimposed `ProcessMap` renders: every activity/transition
|
|
2811
|
+
* either side ever saw, painted with whichever side's stats are the "current" reading (`b`
|
|
2812
|
+
* when present, `a` otherwise). `startActivities`/`endActivities` are recomputed from the
|
|
2813
|
+
* represented activities themselves, so they can never disagree with what `activities`
|
|
2814
|
+
* above actually carries. `totals` prefers `b`'s (the "current" period) and falls back to
|
|
2815
|
+
* `a`'s only when `b` measured nothing at all (e.g. a `b` side still loading).
|
|
2816
|
+
*/
|
|
2817
|
+
declare function diffToProcessGraph(diff: ProcessGraphDiff): ProcessGraph;
|
|
2818
|
+
/** Diff state per activity id, straight off {@link ProcessGraphDiff.activities}. */
|
|
2819
|
+
declare function diffStateByActivity(diff: ProcessGraphDiff): ReadonlyMap<string, DiffState>;
|
|
2820
|
+
/**
|
|
2821
|
+
* A synthetic `ActivityColorScale` that paints every activity by its DIFF STATE rather
|
|
2822
|
+
* than its identity. `colorFor` is the only method `ProcessMap` itself calls (see
|
|
2823
|
+
* `map-model.ts`'s `buildProcessMapModel`); `codeFor`/`labelFor`/`legend` exist only to
|
|
2824
|
+
* satisfy the shared interface.
|
|
2825
|
+
*/
|
|
2826
|
+
declare function diffColorScale(diff: ProcessGraphDiff): ActivityColorScale;
|
|
2827
|
+
|
|
2828
|
+
/** One case travelling one edge. Times are relative to {@link ReplayTimeline.origin}. */
|
|
2829
|
+
interface ReplaySegment {
|
|
2830
|
+
caseId: string;
|
|
2831
|
+
/** `source + EDGE_KEY_SEPARATOR + target`. */
|
|
2832
|
+
edgeId: string;
|
|
2833
|
+
source: string;
|
|
2834
|
+
target: string;
|
|
2835
|
+
/** The source activity's completion. */
|
|
2836
|
+
enterAt: number;
|
|
2837
|
+
/** The target activity's start — never before {@link enterAt}. */
|
|
2838
|
+
exitAt: number;
|
|
2839
|
+
}
|
|
2840
|
+
/** One case's token on one edge at a playhead. */
|
|
2841
|
+
interface ReplayFrameToken {
|
|
2842
|
+
caseId: string;
|
|
2843
|
+
edgeId: string;
|
|
2844
|
+
/** 0 at the source end, 1 at the target end. */
|
|
2845
|
+
progress: number;
|
|
2846
|
+
}
|
|
2847
|
+
/** The replay at one playhead. */
|
|
2848
|
+
interface ReplayFrame {
|
|
2849
|
+
/** Playhead, relative to the timeline origin. */
|
|
2850
|
+
t: number;
|
|
2851
|
+
/** One token per in-flight case, in segment order. */
|
|
2852
|
+
tokens: ReplayFrameToken[];
|
|
2853
|
+
/** Edge id → distinct cases on that edge during the bucket starting at `t`. Zero edges are omitted. */
|
|
2854
|
+
congestion: Record<string, number>;
|
|
2855
|
+
}
|
|
2856
|
+
/** A replay-ready timeline. */
|
|
2857
|
+
interface ReplayTimeline {
|
|
2858
|
+
/** Epoch ms of `t = 0` in wall-clock mode; `0` in synchronized-start mode. */
|
|
2859
|
+
origin: number;
|
|
2860
|
+
/** Last relative instant any case reaches. `0` for an empty log. */
|
|
2861
|
+
duration: number;
|
|
2862
|
+
/** The bucket width actually used. */
|
|
2863
|
+
bucketMs: number;
|
|
2864
|
+
synchronizedStart: boolean;
|
|
2865
|
+
/** Every edge move of every case, ordered by `enterAt` then case order. */
|
|
2866
|
+
segments: ReplaySegment[];
|
|
2867
|
+
/** One frame per bucket, `frames[i].t === i * bucketMs`, covering `[0, duration]`. */
|
|
2868
|
+
frames: ReplayFrame[];
|
|
2869
|
+
/** Highest congestion any edge reaches in any bucket. `0` when nothing moves. */
|
|
2870
|
+
peakCongestion: number;
|
|
2871
|
+
}
|
|
2872
|
+
|
|
2873
|
+
/** Every user-visible string in `ProcessReplay` and its parts. `{…}` are placeholders. */
|
|
2874
|
+
interface ProcessReplayLabels {
|
|
2875
|
+
/** Accessible name of the replay region. */
|
|
2876
|
+
region: string;
|
|
2877
|
+
/** Accessible name of the map canvas. */
|
|
2878
|
+
map: string;
|
|
2879
|
+
play: string;
|
|
2880
|
+
pause: string;
|
|
2881
|
+
/** The time slider. */
|
|
2882
|
+
time: string;
|
|
2883
|
+
/** The speed select. */
|
|
2884
|
+
speed: string;
|
|
2885
|
+
/** `{speed}` — one speed option. */
|
|
2886
|
+
speedOption: string;
|
|
2887
|
+
/** `{time}`, `{count}` — the readout and the paused announcement. */
|
|
2888
|
+
readout: string;
|
|
2889
|
+
/** Announced while the replay runs (the time is not announced frame by frame). */
|
|
2890
|
+
playing: string;
|
|
2891
|
+
/** `{duration}` — a playhead in synchronized-start mode. */
|
|
2892
|
+
relativeTime: string;
|
|
2893
|
+
congestionTitle: string;
|
|
2894
|
+
/** `{source}`, `{target}`. */
|
|
2895
|
+
congestionTransition: string;
|
|
2896
|
+
/** `{peak}`, `{time}` — one ranked transition. */
|
|
2897
|
+
congestionPeak: string;
|
|
2898
|
+
/** `{source}`, `{target}`, `{peak}`, `{time}` — the one-line summary of the busiest transition. */
|
|
2899
|
+
congestionSummary: string;
|
|
2900
|
+
congestionEmpty: string;
|
|
2901
|
+
loading: string;
|
|
2902
|
+
empty: string;
|
|
2903
|
+
emptyBody: string;
|
|
2904
|
+
}
|
|
2905
|
+
/** The shipped English labels. */
|
|
2906
|
+
declare const PROCESS_REPLAY_DEFAULT_LABELS: Readonly<ProcessReplayLabels>;
|
|
2907
|
+
/**
|
|
2908
|
+
* Formats a playhead: a medium date and short time in wall-clock mode, `+duration` since each
|
|
2909
|
+
* case's start in synchronized-start mode.
|
|
2910
|
+
*/
|
|
2911
|
+
declare function useReplayTimeFormatter(timeline: Pick<ReplayTimeline, "origin" | "synchronizedStart">, relativeTemplate?: string): (t: number) => string;
|
|
2912
|
+
|
|
2913
|
+
/** Wall-clock length of a full replay at 1×, in ms. */
|
|
2914
|
+
declare const REPLAY_PLAYBACK_MS = 30000;
|
|
2915
|
+
/** The metric the map paints when none is given: case frequency on both marks. */
|
|
2916
|
+
declare const PROCESS_REPLAY_DEFAULT_METRIC: ProcessMetricSpec;
|
|
2917
|
+
/** Props for {@link ProcessReplay}. `onSelect` is not offered: the map is read-only. */
|
|
2918
|
+
interface ProcessReplayProps extends HTMLAttributes<HTMLDivElement> {
|
|
2919
|
+
/** The discovered graph to replay over. */
|
|
2920
|
+
graph: ProcessGraph;
|
|
2921
|
+
/** The log the graph came from — tokens need per-case timing, not just the aggregate. */
|
|
2922
|
+
log: EventLog;
|
|
2923
|
+
/** Align every case's start to `t = 0` instead of the wall clock. @default false */
|
|
2924
|
+
synchronizedStart?: boolean;
|
|
2925
|
+
/** Bucket width in ms for congestion. @default the log span / 300 */
|
|
2926
|
+
bucketMs?: number;
|
|
2927
|
+
/** Which readings the nodes and edges print. @default case frequency */
|
|
2928
|
+
metric?: ProcessMetricSpec;
|
|
2929
|
+
/** @default "TB" */
|
|
2930
|
+
direction?: FlowLayoutDirection;
|
|
2931
|
+
/** Controlled playing state. Held while reduced motion is on until the reader presses play. */
|
|
2932
|
+
playing?: boolean;
|
|
2933
|
+
/** Initial playing state when uncontrolled. Ignored under reduced motion. @default false */
|
|
2934
|
+
defaultPlaying?: boolean;
|
|
2935
|
+
onPlayingChange?: (playing: boolean) => void;
|
|
2936
|
+
/** Controlled playhead, ms relative to the timeline origin. */
|
|
2937
|
+
time?: number;
|
|
2938
|
+
/** @default 0 */
|
|
2939
|
+
defaultTime?: number;
|
|
2940
|
+
onTimeChange?: (time: number) => void;
|
|
2941
|
+
/** Controlled playback multiplier. */
|
|
2942
|
+
speed?: number;
|
|
2943
|
+
/** @default 1 */
|
|
2944
|
+
defaultSpeed?: number;
|
|
2945
|
+
onSpeedChange?: (speed: number) => void;
|
|
2946
|
+
/** How many transitions the congestion list ranks. @default 5 */
|
|
2947
|
+
congestionLimit?: number;
|
|
2948
|
+
/** No log yet. Renders the loading panel. */
|
|
2949
|
+
loading?: boolean;
|
|
2950
|
+
/** Override any user-visible string. */
|
|
2951
|
+
labels?: Partial<ProcessReplayLabels>;
|
|
2952
|
+
}
|
|
2953
|
+
/**
|
|
2954
|
+
* The process replay.
|
|
2955
|
+
*
|
|
2956
|
+
* @example
|
|
2957
|
+
* ```tsx
|
|
2958
|
+
* const graph = useMemo(() => discoverGraph(log), [log]);
|
|
2959
|
+
* <ProcessReplay graph={graph} log={log} synchronizedStart />
|
|
2960
|
+
* ```
|
|
2961
|
+
*/
|
|
2962
|
+
declare const ProcessReplay: react.ForwardRefExoticComponent<ProcessReplayProps & react.RefAttributes<HTMLDivElement>>;
|
|
2963
|
+
|
|
2964
|
+
/** The speed multipliers the select offers. */
|
|
2965
|
+
declare const REPLAY_SPEEDS: readonly [0.5, 1, 2, 4];
|
|
2966
|
+
/** Props for {@link ReplayControls}. */
|
|
2967
|
+
interface ReplayControlsProps extends HTMLAttributes<HTMLDivElement> {
|
|
2968
|
+
playing: boolean;
|
|
2969
|
+
onPlayingChange: (playing: boolean) => void;
|
|
2970
|
+
/** Playhead, ms relative to the timeline origin. */
|
|
2971
|
+
time: number;
|
|
2972
|
+
onTimeChange: (time: number) => void;
|
|
2973
|
+
/** Timeline length in ms — the slider's maximum. */
|
|
2974
|
+
duration: number;
|
|
2975
|
+
/** Slider step in ms (one bucket). */
|
|
2976
|
+
step: number;
|
|
2977
|
+
speed: number;
|
|
2978
|
+
onSpeedChange: (speed: number) => void;
|
|
2979
|
+
/** Cases in flight at {@link time}. */
|
|
2980
|
+
inFlight: number;
|
|
2981
|
+
/** Formats a playhead for the readout and the slider's value text. */
|
|
2982
|
+
formatTime: (time: number) => string;
|
|
2983
|
+
/** Disable every control (an empty timeline). */
|
|
2984
|
+
disabled?: boolean;
|
|
2985
|
+
labels?: Partial<ProcessReplayLabels>;
|
|
2986
|
+
}
|
|
2987
|
+
/** Play/pause, time slider, speed select and a readout. */
|
|
2988
|
+
declare const ReplayControls: react.ForwardRefExoticComponent<ReplayControlsProps & react.RefAttributes<HTMLDivElement>>;
|
|
2989
|
+
|
|
2990
|
+
/** Props for {@link CongestionHeat}. */
|
|
2991
|
+
interface CongestionHeatProps extends HTMLAttributes<HTMLElement> {
|
|
2992
|
+
/** The replay timeline (`replayTimeline`). */
|
|
2993
|
+
timeline: ReplayTimeline;
|
|
2994
|
+
/** How many transitions to list. @default 5 */
|
|
2995
|
+
limit?: number;
|
|
2996
|
+
labels?: Partial<ProcessReplayLabels>;
|
|
2997
|
+
}
|
|
2998
|
+
/** The most congested transitions of a replay, ranked. */
|
|
2999
|
+
declare const CongestionHeat: react.ForwardRefExoticComponent<CongestionHeatProps & react.RefAttributes<HTMLElement>>;
|
|
3000
|
+
|
|
3001
|
+
/** Edge id → the tokens on that edge right now. An edge with no entry carries none. */
|
|
3002
|
+
type ProcessReplayTokens = ReadonlyMap<string, readonly FlowEdgeToken[]>;
|
|
3003
|
+
/** Provided by `ProcessReplay`. `null` (the default) means no replay is running. */
|
|
3004
|
+
declare const ProcessReplayTokensContext: react.Context<ProcessReplayTokens | null>;
|
|
3005
|
+
/** The tokens on one edge, or `undefined` outside a replay. */
|
|
3006
|
+
declare function useProcessReplayEdgeTokens(edgeId: string): readonly FlowEdgeToken[] | undefined;
|
|
3007
|
+
|
|
3008
|
+
export { ACTIVITY_COLOR_SLOTS, ACTIVITY_OTHER_TOKEN, type AbstractedObjectCentricGraph, AbstractionControls, type AbstractionControlsProps, type ActivityColor, type ActivityColorLegendEntry, type ActivityColorScale, type ActivityFrequencyMode, type AutoAbstractionOptions, type AutoAbstractionResult, type BuildObjectCentricMapModelOptions, type BuildProcessMapModelOptions, CASE_TABLE_COLUMN_LABEL_KEYS, CONFORMANCE_OVERLAY_DEFAULT_METRIC, CONFORMANCE_STATES, CONFORMANCE_STATE_DEFAULT_LABELS, CONFORMANCE_STATE_ENCODING, type CaseRow, CaseTable, type CaseTableProps, CaseTimeline, type CaseTimelineGap, type CaseTimelineInstance, type CaseTimelineModelOptions, type CaseTimelineProps, CompareKpiStrip, type CompareKpiStripProps, type CompareKpiStripSide, CompareSide, type CompareSideInput, type CompareSideKpis, type CompareSideProps, type ComputeDotsOptions, type ConformanceDash, ConformanceLegend, type ConformanceLegendProps, ConformanceOverlay, type ConformanceOverlayProps, type ConformanceState, type ConformanceStateEncoding, type ConformanceStateLabels, ConformanceStateMark, type ConformanceStateMarkProps, type ConformanceStates, type ConformanceTone, CongestionHeat, type CongestionHeatProps, type CreateCaseTableColumnsOptions, DEFAULT_LAYOUT_DEBOUNCE_MS, DIFF_STATE_TOKEN, DOTTED_CHART_DEFAULT_LABELS, DOTTED_CHART_DOT_RADIUS, DottedChart, type DottedChartCategory, type DottedChartColor, type DottedChartDatum, type DottedChartDot, type DottedChartFilterIntent, type DottedChartLabels, type DottedChartModel, type DottedChartProps, type DottedChartRow, type DottedChartSort, type DottedChartX, EMPTY_PROCESS_GRAPH, EMPTY_PROCESS_MAP_HOVER, type FilterIntent, GHOST_OPACITY, HAPPY_PATH_EDITOR_DEFAULT_LABELS, HappyPathEditor, HappyPathEditorContext, type HappyPathEditorContextValue, type HappyPathEditorLabels, type HappyPathEditorProps, type HappyPathStepFlowNode, HappyPathStepNode, type HappyPathStepNodeData, type MetricLayer, MetricLayerSwitch, type MetricLayerSwitchMetric, type MetricLayerSwitchProps, OBJECT_CENTRIC_MAP_DEFAULT_LABELS, OBJECT_TYPE_ABSTRACTION_DEFAULT_LABELS, type ObjectCentricActivityStats, type ObjectCentricGraph, type ObjectCentricMapLabels, type ObjectTypeAbstraction, type ObjectTypeAbstractionLabels, type ObjectTypeActivityCounts, PERFORMANCE_SPECTRUM_DEFAULT_BIN_SIZE, PERFORMANCE_SPECTRUM_DEFAULT_LABELS, PERFORMANCE_SPECTRUM_ROW_HEIGHT, PERFORMANCE_SPECTRUM_SEGMENT_LIMIT, PROCESS_FILTER_INTENT_KINDS, PROCESS_FILTER_INTENT_LABELS, PROCESS_FILTER_INTENT_MESSAGE_KEYS, PROCESS_MAP_EDGE_SCALE_GROUP, PROCESS_MAP_LEGIBLE_ZOOM, PROCESS_MAP_NODE_MOTION_CLASS, PROCESS_REPLAY_DEFAULT_LABELS, PROCESS_REPLAY_DEFAULT_METRIC, PROCESS_SELECTION_STATE_MESSAGE_KEYS, PerformanceSpectrum, type PerformanceSpectrumFilterIntent, type PerformanceSpectrumLabels, type PerformanceSpectrumOrder, type PerformanceSpectrumProps, ProcessActivityNode, type ProcessActivityNodeData, type ProcessActivityRow, ProcessCompare, type ProcessCompareMode, type ProcessCompareProps, type ProcessCompareSide, type ProcessEdgeDenominators, type ProcessExplorerMetric, type ProcessExplorerMetricSpec, type ProcessExplorerOptions, ProcessFilterBar, type ProcessFilterBarProps, type ProcessFilterIntent, ProcessKpiStrip, type ProcessKpiStripKpis, type ProcessKpiStripProps, type ProcessKpiStripTrendKey, type ProcessLayoutSnapshot, ProcessMap, type ProcessMapEdge, ProcessMapEdgeKeyContext, type ProcessMapEdgeKeyHandler, type ProcessMapExcludedCounts, ProcessMapHoverContext, type ProcessMapHoverState, type ProcessMapModel, type ProcessMapNode, type ProcessMapProps, type ProcessMetric, type ProcessMetricSpec, type ProcessObjectTypeCount, type ProcessObjectTypeMark, ProcessReplay, type ProcessReplayLabels, type ProcessReplayProps, type ProcessReplayTokens, ProcessReplayTokensContext, type ProcessSelection, type ProcessSelectionKind, type ProcessSelectionNeighbourhood, type ProcessSelectionState, type ProcessSelectionStates, ProcessTransitionEdge, type ProcessTransitionEdgeData, type ProcessTransitionRow, REPLAY_PLAYBACK_MS, REPLAY_SPEEDS, ReplayControls, type ReplayControlsProps, type SpectrumBin, type SpectrumLine, type SpectrumRow, type TransitionFrequencyMode, type UseProcessExplorerResult, type UseProcessLayoutOptions, type UseProcessLayoutResult, VARIANT_EXPLORER_COLUMNS, VARIANT_EXPLORER_DEFAULT_LABELS, VARIANT_EXPLORER_ROW_HEIGHT, VIOLATION_LIST_DEFAULT_LABELS, VariantExplorer, type VariantExplorerColumn, type VariantExplorerLabels, type VariantExplorerProps, type VariantSelectMode, type ViolationFilterIntent, ViolationList, type ViolationListLabels, type ViolationListProps, type ViolationRow, type ViolationRowKind, activityAccentStyle, activityAriaLabel, activityColorScale, activityConformance, activityMetricValue, activityRole, aggregateSegmentBins, applyLayoutSnapshot, buildCaseTimelineInstances, buildObjectCentricMapModel, buildProcessMapModel, buildSpectrumRows, casesFromLog, casesInBrush, casesInRange, computeAutoAbstraction, computeDots, createCaseTableColumns, diffColorScale, diffStateByActivity, diffToProcessGraph, edgeMetricLabel, formatDurationMs, formatMetricValue, happyPathStepNodeId, insertHappyPathStep, isPerformanceMetric, nextHappyPathActivity, nodeMetricLabel, objectCentricEdgeId, processEdgeDenominators, processEdgeId, processGraphStructureKey, rankCategoryColors, removeHappyPathStep, resolveActivityFrequencyMode, resolveCompareKpis, resolveConformanceStates, resolveSelectionState, resolveTransitionFrequencyMode, selectVariantsByCoverage, selectionNeighbourhood, selectionStateLabel, spectrumDomain, spectrumTicks, transitionAriaLabel, transitionConformance, transitionMetricValue, transitionShape, updateHappyPathStep, useHappyPathEditor, useProcessExplorer, useProcessLayout, useProcessMapEdgeKeys, useProcessMapHover, useProcessReplayEdgeTokens, useReplayTimeFormatter, violationRows, withActivityConformance, withTransitionConformance };
|