@formicoidea/labre-framework-uml 0.42.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.
Files changed (114) hide show
  1. package/LICENSE +384 -0
  2. package/dist/actions.d.ts +430 -0
  3. package/dist/actions.js +724 -0
  4. package/dist/background.d.ts +153 -0
  5. package/dist/background.js +557 -0
  6. package/dist/board-hit.d.ts +137 -0
  7. package/dist/board-hit.js +191 -0
  8. package/dist/commands-manifest.d.ts +19 -0
  9. package/dist/commands-manifest.js +571 -0
  10. package/dist/commands.d.ts +4 -0
  11. package/dist/commands.js +983 -0
  12. package/dist/component.d.ts +521 -0
  13. package/dist/component.js +708 -0
  14. package/dist/consts.d.ts +365 -0
  15. package/dist/consts.js +463 -0
  16. package/dist/descriptor.d.ts +12 -0
  17. package/dist/descriptor.js +10 -0
  18. package/dist/drawio-decode.d.ts +32 -0
  19. package/dist/drawio-decode.js +96 -0
  20. package/dist/drawio-import.d.ts +133 -0
  21. package/dist/drawio-import.js +885 -0
  22. package/dist/edge-morph.d.ts +154 -0
  23. package/dist/edge-morph.js +153 -0
  24. package/dist/edge-styles.d.ts +78 -0
  25. package/dist/edge-styles.js +210 -0
  26. package/dist/effects.d.ts +9 -0
  27. package/dist/effects.js +6 -0
  28. package/dist/element-renderer.d.ts +64 -0
  29. package/dist/element-renderer.js +114 -0
  30. package/dist/element-view.d.ts +234 -0
  31. package/dist/element-view.js +430 -0
  32. package/dist/export.d.ts +61 -0
  33. package/dist/export.js +41 -0
  34. package/dist/filename.d.ts +17 -0
  35. package/dist/filename.js +26 -0
  36. package/dist/frame-tag.d.ts +70 -0
  37. package/dist/frame-tag.js +78 -0
  38. package/dist/grammar.d.ts +695 -0
  39. package/dist/grammar.js +1436 -0
  40. package/dist/import.d.ts +306 -0
  41. package/dist/import.js +1270 -0
  42. package/dist/index.d.ts +47 -0
  43. package/dist/index.js +67 -0
  44. package/dist/interchange.d.ts +125 -0
  45. package/dist/interchange.js +372 -0
  46. package/dist/keywords.d.ts +204 -0
  47. package/dist/keywords.js +361 -0
  48. package/dist/kinds.d.ts +73 -0
  49. package/dist/kinds.js +91 -0
  50. package/dist/legend.d.ts +30 -0
  51. package/dist/legend.js +255 -0
  52. package/dist/model.d.ts +862 -0
  53. package/dist/model.js +1316 -0
  54. package/dist/morph.d.ts +178 -0
  55. package/dist/morph.js +496 -0
  56. package/dist/node/act-glyphs.d.ts +30 -0
  57. package/dist/node/act-glyphs.js +142 -0
  58. package/dist/node/compartment-watcher.d.ts +107 -0
  59. package/dist/node/compartment-watcher.js +163 -0
  60. package/dist/node/fit.d.ts +85 -0
  61. package/dist/node/fit.js +129 -0
  62. package/dist/node/node-renderer.d.ts +49 -0
  63. package/dist/node/node-renderer.js +611 -0
  64. package/dist/node/node-view.d.ts +51 -0
  65. package/dist/node/node-view.js +89 -0
  66. package/dist/node/paint.d.ts +84 -0
  67. package/dist/node/paint.js +143 -0
  68. package/dist/node/sd-glyphs.d.ts +36 -0
  69. package/dist/node/sd-glyphs.js +79 -0
  70. package/dist/node/stm-glyphs.d.ts +22 -0
  71. package/dist/node/stm-glyphs.js +111 -0
  72. package/dist/node/tier-metrics.d.ts +38 -0
  73. package/dist/node/tier-metrics.js +45 -0
  74. package/dist/operators.d.ts +45 -0
  75. package/dist/operators.js +75 -0
  76. package/dist/plantuml-import.d.ts +113 -0
  77. package/dist/plantuml-import.js +1723 -0
  78. package/dist/plantuml.d.ts +94 -0
  79. package/dist/plantuml.js +985 -0
  80. package/dist/presets.d.ts +149 -0
  81. package/dist/presets.js +302 -0
  82. package/dist/profiles.d.ts +2 -0
  83. package/dist/profiles.js +358 -0
  84. package/dist/reading.d.ts +160 -0
  85. package/dist/reading.js +648 -0
  86. package/dist/roles.d.ts +257 -0
  87. package/dist/roles.js +997 -0
  88. package/dist/rules.d.ts +267 -0
  89. package/dist/rules.js +3090 -0
  90. package/dist/templates.d.ts +2 -0
  91. package/dist/templates.js +197 -0
  92. package/dist/toolbar/config.d.ts +228 -0
  93. package/dist/toolbar/config.js +833 -0
  94. package/dist/toolbar/icons.d.ts +440 -0
  95. package/dist/toolbar/icons.js +711 -0
  96. package/dist/toolbar/senior-tool.d.ts +11 -0
  97. package/dist/toolbar/senior-tool.js +21 -0
  98. package/dist/toolbar/uml-menu.d.ts +17 -0
  99. package/dist/toolbar/uml-menu.js +20 -0
  100. package/dist/toolbar/uml-senior-button.d.ts +18 -0
  101. package/dist/toolbar/uml-senior-button.js +22 -0
  102. package/dist/translations.d.ts +27 -0
  103. package/dist/translations.js +117 -0
  104. package/dist/view.d.ts +33 -0
  105. package/dist/view.js +236 -0
  106. package/dist/xmi-import.d.ts +174 -0
  107. package/dist/xmi-import.js +2268 -0
  108. package/dist/xmi.d.ts +61 -0
  109. package/dist/xmi.js +1860 -0
  110. package/dist/xml-reader.d.ts +157 -0
  111. package/dist/xml-reader.js +430 -0
  112. package/dist/xml.d.ts +72 -0
  113. package/dist/xml.js +96 -0
  114. package/package.json +38 -0
@@ -0,0 +1,862 @@
1
+ import { type UmlDiagramKind, type UmlFragmentOperand, type UmlFragmentOperator, type UmlNodeKind } from '@formicoidea/labre-core/model';
2
+ import { type UmlBox, type UmlComponent, type UmlComponentElement, type UmlComponentGroup } from './component.js';
3
+ import { type UmlAssociationEnd, type UmlOperation, type UmlProperty } from './grammar.js';
4
+ /**
5
+ * The neutral intermediate representation one UML diagram exports through.
6
+ *
7
+ * ## Why there is an IR at all
8
+ *
9
+ * Two writers — PlantUML and XMI — and one canvas. Without a model in between,
10
+ * each writer would have to know that a class's name lives in a grouped text
11
+ * element with the role `uml:name`, that its attributes are a second one, that a
12
+ * connector's ends may land on the group rather than on the shape, and that a
13
+ * package contains what its box contains. Two copies of that reading is two
14
+ * copies that drift, and the drift shows up as two files that disagree about the
15
+ * same drawing.
16
+ *
17
+ * So the canvas is read ONCE, here, and the writers take records. It is also
18
+ * what makes them testable with literals: a golden XMI test needs a model, not a
19
+ * surface.
20
+ *
21
+ * ## Pure
22
+ *
23
+ * Elements in, records out. No `std`, no DOM, no clock, no randomness — the
24
+ * discipline `docs/adr/0012` P3 sets for every interchange function, and the
25
+ * reason {@link umlModelFrom} takes plain structural records
26
+ * ({@link UmlSourceElement}) rather than element models: the same function runs
27
+ * against a live surface and against six object literals in a spec.
28
+ */
29
+ /**
30
+ * The shape of an element as this module reads it.
31
+ *
32
+ * Structural, and deliberately so: every field is one a real
33
+ * `GfxPrimitiveElementModel` carries, and every field is optional, so a test can
34
+ * hand over `{ id, type, kind, xywh }` and get the same answer a surface does.
35
+ * `text` and `name` are `unknown` because on a live element they are a `Y.Text`
36
+ * and in a spec they are a string, and nothing here has any business knowing
37
+ * which — both go through `umlTierText`, which stringifies whatever it is given.
38
+ * That is also what keeps this file free of a Yjs import.
39
+ */
40
+ export interface UmlSourceElement extends UmlComponentElement {
41
+ /** `'umlDiagram'`, `'umlNode'`, `'umlSubject'`, `'connector'`, `'text'`, … */
42
+ type?: string;
43
+ /** `UmlNodeKind` on a node, `UmlDiagramKind` on a frame. */
44
+ kind?: string;
45
+ name?: unknown;
46
+ heading?: unknown;
47
+ /** Which way a `umlPartition`'s band runs (§15.6.4). */
48
+ orientation?: string;
49
+ xywh?: string;
50
+ deserializedXYWH?: readonly number[];
51
+ elementBound?: {
52
+ x: number;
53
+ y: number;
54
+ w: number;
55
+ h: number;
56
+ };
57
+ /** A group's members. */
58
+ childIds?: readonly string[];
59
+ /**
60
+ * A connector's ends.
61
+ *
62
+ * `position` is the RELATIVE point the end is anchored at on the element it
63
+ * touches — `[0.5, 0.5]` for a centre anchor, `[0, 0.35]` for a message
64
+ * attached a third of the way down a lifeline's left edge. Read for one thing
65
+ * only, and it is the thing a sequence diagram is made of: §17.4.4 says the
66
+ * HEIGHT an arrow is drawn at is WHEN it happens, and that height is stored
67
+ * here rather than derived — a connector's own bound is computed by the router
68
+ * and reads `[0,0,0,0]` on a freshly loaded document.
69
+ */
70
+ source?: {
71
+ id?: string;
72
+ position?: readonly number[];
73
+ } | null;
74
+ target?: {
75
+ id?: string;
76
+ position?: readonly number[];
77
+ } | null;
78
+ /** A `umlFragment`'s interaction operator (§17.6.4). */
79
+ operator?: string;
80
+ /** A `umlFragment`'s operand bands, top to bottom (§17.6.4). */
81
+ operands?: readonly UmlFragmentOperand[];
82
+ /**
83
+ * The two PER-END labels of a connector (ADR 0020), beside `text`.
84
+ *
85
+ * `unknown` for the reason {@link UmlSourceElement.name} is: a live connector
86
+ * holds a `Y.Text` and a spec hands over a string, and both go through
87
+ * `umlTierText`.
88
+ */
89
+ sourceLabel?: unknown;
90
+ targetLabel?: unknown;
91
+ }
92
+ /** A slot of an InstanceSpecification — `attribute = value` (§11.6.4). */
93
+ export interface UmlSlot {
94
+ name: string;
95
+ /** Absent when the author named a feature and gave it no value. */
96
+ value?: string;
97
+ }
98
+ /** What every drawn artefact states, whatever kind it is. */
99
+ export interface UmlNodeBase {
100
+ /** The surface element's id — what a relation's ends resolve to. */
101
+ id: string;
102
+ name: string;
103
+ /** Annex C labels read off the name compartment, in order. */
104
+ keywords: string[];
105
+ /** `{abstract}` was written on it (§9.2.4). */
106
+ isAbstract: boolean;
107
+ /** Where it is drawn — what package and subject nesting is decided by. */
108
+ bounds?: UmlBox;
109
+ }
110
+ /** A Class, an Interface, an Enumeration or an InstanceSpecification. */
111
+ export interface UmlClassifier extends UmlNodeBase {
112
+ kind: Extract<UmlNodeKind, 'class' | 'interface' | 'enumeration' | 'object'>;
113
+ /** The attribute compartment, parsed. Empty for an object. */
114
+ attributes: UmlProperty[];
115
+ /** The operation compartment, parsed. Empty for an object. */
116
+ operations: UmlOperation[];
117
+ /** The value compartment of an object. Empty for the other three. */
118
+ slots: UmlSlot[];
119
+ /**
120
+ * The compartments as the author TYPED them — trimmed, blanks and elision
121
+ * markers dropped, and otherwise untouched.
122
+ *
123
+ * Carried beside the parsed forms because one of the two writers wants each.
124
+ * XMI needs the structure: it has a slot for a visibility, a type and a
125
+ * multiplicity and nothing to do with a line. PlantUML's member syntax IS
126
+ * §9.5.4's own notation, so re-spelling a parsed property for it could only
127
+ * lose what the parser did not model — a constraint, an unusual modifier, a
128
+ * qualified redefinition. Both readings of the same compartment, stated once
129
+ * here rather than re-derived in two files.
130
+ */
131
+ lines: {
132
+ attributes: string[];
133
+ operations: string[];
134
+ };
135
+ /**
136
+ * The Classifier an object is an instance OF — the `Class` of
137
+ * `object : Class` (§11.6.4). Objects only, and absent when the author wrote
138
+ * a bare instance name.
139
+ */
140
+ instanceOf?: string;
141
+ }
142
+ /** A Package (§12.2), an Actor or a UseCase (§18.1) — a named box. */
143
+ export type UmlPackageNode = UmlNodeBase;
144
+ export type UmlActorNode = UmlNodeBase;
145
+ export type UmlUseCaseNode = UmlNodeBase;
146
+ /**
147
+ * A Port (§11.3) — the small square on an EncapsulatedClassifier's boundary.
148
+ *
149
+ * `ownerId` is the surface id of the component (or the node) the square is drawn
150
+ * ON, and it is GEOMETRY rather than a stored link: §11.3.4 says the symbol "may
151
+ * be placed either overlapping the boundary of the rectangle symbol denoting
152
+ * that EncapsulatedClassifier or it may be shown inside the rectangle symbol",
153
+ * and a canvas has no other statement to read. See {@link umlHostOf} for the
154
+ * reading and for its tolerance.
155
+ *
156
+ * Absent when the author has drawn a port beside every box, which is a port
157
+ * belonging to nothing — the file writes it nowhere rather than guessing an
158
+ * owner, and the drawing keeps it.
159
+ */
160
+ export interface UmlPort extends UmlNodeBase {
161
+ ownerId?: string;
162
+ }
163
+ /**
164
+ * A Component (§11.6) — the classifier rectangle with the two-tab icon.
165
+ *
166
+ * `provided` and `required` are the NAMES read off the lollipops and sockets
167
+ * drawn against it, not references: §10.4.4 draws a provided Interface as a
168
+ * circle "labeled with the name of the Interface, attached by a solid line to
169
+ * the BehavioredClassifier that realizes this Interface", and on this canvas the
170
+ * glyph carries its own `uml:label` and nothing else. The names are what both
171
+ * writers need — XMI mints a `uml:Interface` per name, PlantUML declares one —
172
+ * and what neither can get from an id, because the glyph IS the interface as far
173
+ * as the drawing is concerned.
174
+ *
175
+ * `ports` are the squares on its border, resolved the same geometric way.
176
+ */
177
+ export interface UmlComponentNode extends UmlNodeBase {
178
+ ports: UmlPort[];
179
+ /** Interface names read off the lollipops touching this component. */
180
+ provided: string[];
181
+ /** Interface names read off the sockets touching this component. */
182
+ required: string[];
183
+ }
184
+ /** An Artifact (§19.3) — the `«artifact»` rectangle with the document icon. */
185
+ export type UmlArtifactNode = UmlNodeBase;
186
+ /**
187
+ * A Node, a Device or an ExecutionEnvironment (§19.4) — the perspective cube.
188
+ *
189
+ * ONE record with a `kind` discriminant rather than three lists, because §19.4.2
190
+ * makes Device and ExecutionEnvironment specializations of Node and §19.4.4
191
+ * draws all three as the same cube: the keyword is the difference, and both
192
+ * writers need exactly that — an `xmi:type` and a PlantUML stereotype.
193
+ */
194
+ export interface UmlDeploymentNode extends UmlNodeBase {
195
+ kind: Extract<UmlNodeKind, 'node' | 'device' | 'execution-environment'>;
196
+ }
197
+ /** The subject of a use case diagram — the rectangle the cases sit in. */
198
+ export type UmlSubjectBox = UmlNodeBase;
199
+ /** A Comment (Annex A) — prose, kept whole. */
200
+ export interface UmlNote extends UmlNodeBase {
201
+ /** The note's text, verbatim: a note is prose, not a name compartment. */
202
+ body: string;
203
+ }
204
+ /**
205
+ * The relationships phase 1 draws — the local half of each `uml:…` edge role.
206
+ *
207
+ * A closed union rather than an open string, because every writer maps it
208
+ * TOTALLY: a `Record<UmlRelationKind, …>` in `plantuml.ts` and an exhaustive
209
+ * `switch` in `xmi.ts` both fail the build the day a tenth relationship is drawn
210
+ * with nothing to write it as. That failure is cheap here and expensive in a
211
+ * file somebody exported.
212
+ */
213
+ export type UmlRelationKind = 'association' | 'aggregation' | 'composition' | 'generalization' | 'realization' | 'dependency' | 'anchor' | 'include' | 'extend' | 'deploy' | 'manifest' | 'communication-path' | 'control-flow' | 'object-flow' | 'transition' | 'message-sync' | 'message-async' | 'message-reply' | 'message-create' | 'message-delete';
214
+ /** One connector, once both of its ends are known artefacts of this diagram. */
215
+ export interface UmlRelation {
216
+ kind: UmlRelationKind;
217
+ /**
218
+ * The SUBJECT of the sentence the edge's direction states (the role table in
219
+ * `roles.ts`): the specific classifier of a generalization, the WHOLE of an
220
+ * aggregation, the base UseCase of an include, the extending UseCase of an
221
+ * extend.
222
+ */
223
+ sourceId: string;
224
+ targetId: string;
225
+ /** The connector's own centre text, when it carries one. */
226
+ label?: string;
227
+ /**
228
+ * What is written beside the SOURCE end of the line — §11.5.4's adornments.
229
+ *
230
+ * Present whenever the connector carries an end label at all, whatever the
231
+ * relationship is. On the four kinds §11.5.4 governs
232
+ * ({@link ADORNED_RELATION_KINDS}) it is PARSED — a multiplicity, a role name,
233
+ * a visibility glyph; on every other kind only
234
+ * {@link UmlAssociationEnd.raw} is filled, because a multiplicity beside a
235
+ * generalization is not a multiplicity of anything and writing one into a file
236
+ * would state a fact the metamodel has nowhere to hold. Carrying the raw text
237
+ * regardless is what keeps the round trip lossless: the author's words come
238
+ * back on the board even where no writer can spell them.
239
+ */
240
+ sourceEnd?: UmlAssociationEnd;
241
+ /** What is written beside the TARGET end — see {@link sourceEnd}. */
242
+ targetEnd?: UmlAssociationEnd;
243
+ }
244
+ /**
245
+ * The relationships whose end labels §11.5.4 gives a MEANING to.
246
+ *
247
+ * An Association and its two aggregation flavours, plus the CommunicationPath
248
+ * §19.4.3 defines as "an Association between two DeploymentTargets" — which is
249
+ * why it is in the set: it is an Association, so its ends are Properties and
250
+ * take a multiplicity like any other.
251
+ */
252
+ export declare const ADORNED_RELATION_KINDS: ReadonlySet<UmlRelationKind>;
253
+ /** The ten glyphs an `act` sheet draws — §15.3.4, §15.4.4, §16.3.4, §16.10.4. */
254
+ export type UmlActivityNodeKind = Extract<UmlNodeKind, 'action' | 'initial' | 'activity-final' | 'flow-final' | 'decision' | 'fork' | 'object-node' | 'send-signal' | 'accept-event' | 'time-event'>;
255
+ /**
256
+ * One node of an Activity — the glyph, its words, and the lane it is drawn in.
257
+ *
258
+ * ONE record with a `kind` discriminant rather than ten lists, for the reason
259
+ * {@link UmlDeploymentNode} gives: §15.7 makes all ten ActivityNodes and both
260
+ * writers need exactly the discriminant — an `xmi:type` and a PlantUML
261
+ * stereotype. A list per glyph would be ten fields the writers would have to
262
+ * concatenate back into one traversal order.
263
+ */
264
+ export interface UmlActivityNode extends UmlNodeBase {
265
+ kind: UmlActivityNodeKind;
266
+ /**
267
+ * The surface id of the `umlPartition` whose box holds this node's centre —
268
+ * §15.6.4's swimlane, read at EXPORT time from geometry and never stored.
269
+ *
270
+ * The same reading {@link UmlPort.ownerId} gets, and for the same reason: a
271
+ * partition is a band drawn across the sheet, membership is which band a glyph
272
+ * sits in, and a canvas holds no second statement about it. Absent for a node
273
+ * drawn between the lanes, or on a sheet with no lanes at all — which is most
274
+ * of them.
275
+ */
276
+ partitionId?: string;
277
+ }
278
+ /** One ActivityEdge — the arrow, and the three things §15.2.4 writes on it. */
279
+ export interface UmlActivityEdge {
280
+ /** §15.7.9 / §15.7.11 — which of the two kinds of token travels. */
281
+ kind: Extract<UmlRelationKind, 'control-flow' | 'object-flow'>;
282
+ sourceId: string;
283
+ targetId: string;
284
+ /** The edge's own name, "notated near the arrow". */
285
+ name?: string;
286
+ /** The `[…]` guard, without its brackets — §15.2.4's own notation. */
287
+ guard?: string;
288
+ /** `{weight = …}`'s value, as written — see {@link UmlActivityEdgeLabel}. */
289
+ weight?: string;
290
+ }
291
+ /** An ActivityPartition (§15.6) — the swimlane, and what is drawn in it. */
292
+ export interface UmlPartition extends UmlNodeBase {
293
+ /** Which way the band runs. A column unless the author turned it. */
294
+ orientation: 'vertical' | 'horizontal';
295
+ /**
296
+ * The activity nodes whose centres it holds, in document order.
297
+ *
298
+ * Listed on the partition AS WELL AS named by each node's
299
+ * {@link UmlActivityNode.partitionId}, and the duplication is the one
300
+ * {@link UmlModel.ports} already explains: the XMI writer walks the lane (an
301
+ * `ActivityPartition` carries `node` idrefs, so it needs the list) while a
302
+ * reader asking which lane one action is in must not have to scan every lane
303
+ * to find out. Both readings are built from one pass, so they cannot disagree.
304
+ */
305
+ nodeIds: string[];
306
+ }
307
+ /**
308
+ * One Activity — the whole of what an `act` sheet says.
309
+ *
310
+ * A frame is ONE Activity: §15.2.4 draws the border and the name in the upper
311
+ * left corner, Annex A replaces that border with the diagram frame, and that is
312
+ * exactly the frame this model was read off. So the id and the name are the
313
+ * sheet's own, and a second activity on one canvas is a second frame — the same
314
+ * reading ADR 0017 makes about every other UML sheet.
315
+ */
316
+ export interface UmlActivity {
317
+ /** The diagram frame's surface id — the Activity IS the sheet. */
318
+ id: string;
319
+ name: string;
320
+ nodes: UmlActivityNode[];
321
+ edges: UmlActivityEdge[];
322
+ partitions: UmlPartition[];
323
+ }
324
+ /** The nine glyphs §14.2.4 routes transitions through. */
325
+ export type UmlPseudostateKind = Extract<UmlNodeKind, 'initial' | 'choice' | 'junction' | 'shallow-history' | 'deep-history' | 'entry-point' | 'exit-point' | 'terminate' | 'fork'>;
326
+ /** A Region (§14.2.4) — the composite state, drawn as a box round its parts. */
327
+ export interface UmlRegion extends UmlNodeBase {
328
+ /**
329
+ * The region this one is drawn inside — §14.2.4's nested composite state.
330
+ *
331
+ * Geometry, most-nested first, exactly as a package inside a package is read
332
+ * (`xmi.ts`'s `containerOf`). Absent for a region at the top level of the
333
+ * sheet, which is where most of them are.
334
+ */
335
+ parentId?: string;
336
+ }
337
+ /** A State (§14.2.4.4) — the rounded box and its internal activities. */
338
+ export interface UmlState extends UmlNodeBase {
339
+ /** `entry / …` lines, in order, as the expressions alone. */
340
+ entry: string[];
341
+ /** `do / …` lines — the metamodel's `doActivity`. */
342
+ doActivity: string[];
343
+ /** `exit / …` lines. */
344
+ exit: string[];
345
+ /**
346
+ * Every line of the compartment that is NONE of the three — an internal
347
+ * transition (§14.2.4.4's second compartment), a constraint, a note to self.
348
+ *
349
+ * Carried rather than dropped for the reason {@link UmlClassifier.lines}
350
+ * exists: the author typed it, so something has to be able to write it back,
351
+ * and a writer that silently lost a compartment would be the worst kind of
352
+ * lossy export. Neither writer has a metamodel slot for it today; PlantUML
353
+ * prints it as a state line.
354
+ */
355
+ lines: string[];
356
+ /** The composite state whose box holds its centre — {@link UmlRegion}. */
357
+ regionId?: string;
358
+ }
359
+ /** A FinalState (§14.2.4.5) — the bullseye a machine stops at. */
360
+ export interface UmlFinalState extends UmlNodeBase {
361
+ regionId?: string;
362
+ }
363
+ /** A Pseudostate (§14.2.4.6) — a vertex that routes rather than one that is. */
364
+ export interface UmlPseudostate extends UmlNodeBase {
365
+ kind: UmlPseudostateKind;
366
+ regionId?: string;
367
+ }
368
+ /** One Transition (§14.2.4.8) — its two ends and its label, parsed. */
369
+ export interface UmlTransition {
370
+ sourceId: string;
371
+ targetId: string;
372
+ /** `<trigger> [',' <trigger>]*`, verbatim and in order. */
373
+ triggers: string[];
374
+ /** The `[…]` guard, without its brackets. */
375
+ guard?: string;
376
+ /** The `/ <behavior-expression>` effect, as written. */
377
+ effect?: string;
378
+ }
379
+ /**
380
+ * One StateMachine — the whole of what an `stm` sheet says.
381
+ *
382
+ * {@link UmlActivity}'s twin, and it carries its vertices in FOUR lists rather
383
+ * than one discriminated list because the metamodel does: a State owns
384
+ * behaviours and regions, a FinalState owns neither and forbids both
385
+ * (§14.5.11.4), and a Pseudostate is a `kind` attribute on one metaclass. Three
386
+ * different `xmi:type`s with three different shapes is three lists; ten
387
+ * identically shaped ActivityNodes is one.
388
+ */
389
+ export interface UmlStateMachine {
390
+ /** The diagram frame's surface id — the StateMachine IS the sheet. */
391
+ id: string;
392
+ name: string;
393
+ /** The composite states, outermost and nested alike. */
394
+ regions: UmlRegion[];
395
+ states: UmlState[];
396
+ finalStates: UmlFinalState[];
397
+ pseudostates: UmlPseudostate[];
398
+ transitions: UmlTransition[];
399
+ }
400
+ /**
401
+ * §17.4.3's `messageSort`, as the five arrows an `sd` sheet is drawn with.
402
+ *
403
+ * A projection of {@link UmlRelationKind} rather than a union of its own, for
404
+ * the reason {@link UmlActivityEdge.kind} is one: a message IS a connector on
405
+ * the canvas, read off the same role table in the same pass, and two spellings
406
+ * of the same five words would be two things to keep in step.
407
+ */
408
+ export type UmlMessageKind = Extract<UmlRelationKind, 'message-sync' | 'message-async' | 'message-reply' | 'message-create' | 'message-delete'>;
409
+ /**
410
+ * A Lifeline (§17.3) — the participant column: a named head over a dashed
411
+ * spine.
412
+ *
413
+ * `name` and `type` are the two halves of §17.3.4's `<name> : <Type>`, split by
414
+ * `parseLifelineIdent` — the same grammar `keywords.ts` seeds a fresh head
415
+ * with. `type` is absent when the author wrote a bare participant name, which
416
+ * is most of them.
417
+ */
418
+ export interface UmlLifeline extends UmlNodeBase {
419
+ /** The Classifier this participant is an instance of (§17.3.4). */
420
+ type?: string;
421
+ }
422
+ /**
423
+ * One Message (§17.4) — its two ends, its label, and WHEN it happens.
424
+ *
425
+ * ## Why `y` is on the record and the list is sorted by it
426
+ *
427
+ * Because on a sequence diagram the vertical axis IS time (§17.4.4: "every line
428
+ * fragment is either horizontal or downwards"), and every writer needs the
429
+ * order rather than the height: XMI serializes a pair of
430
+ * `MessageOccurrenceSpecification`s per message and an Interaction's `fragment`
431
+ * list is READ IN ORDER, PlantUML's whole syntax is one message per line top to
432
+ * bottom. So the canvas's one statement about sequence — the height an arrow was
433
+ * drawn at — is turned into an order here, once, and the writers take a list.
434
+ *
435
+ * `sourceId` and `targetId` are the ids the connector actually resolves to,
436
+ * which is a LIFELINE or an EXECUTION ({@link UmlExecution}): §17.4.4 draws an
437
+ * arrow onto the bar as readily as onto the spine, and a reading that snapped
438
+ * every end to a lifeline would lose which activation the author aimed at.
439
+ * A writer that needs the covering lifeline resolves it through
440
+ * {@link UmlExecution.lifelineId}.
441
+ */
442
+ export interface UmlMessage {
443
+ /** The connector's own surface id — what a report names it by. */
444
+ id: string;
445
+ kind: UmlMessageKind;
446
+ sourceId: string;
447
+ targetId: string;
448
+ /** The connector's centre text: §17.4.4's message label, as written. */
449
+ label?: string;
450
+ /** The height it is drawn at — see the docblock. */
451
+ y: number;
452
+ }
453
+ /**
454
+ * One InteractionOperand (§17.6.4) — a horizontal band of a combined fragment,
455
+ * separated from the next by a dashed line.
456
+ *
457
+ * `guard` is §17.6.4's `[…]` InteractionConstraint WITHOUT its brackets, the
458
+ * same way {@link UmlActivityEdge.guard} and {@link UmlTransition.guard} carry
459
+ * theirs: the brackets are the notation's delimiter, and a writer that had to
460
+ * strip them would be parsing its own model. The canvas keeps them — they are
461
+ * what the author typed and what the renderer paints — and
462
+ * {@link umlGuardText} takes exactly one pair off on the way in here.
463
+ *
464
+ * `y0` and `y1` are the band's own top and bottom in canvas units, because that
465
+ * is what decides which messages are inside WHICH operand — an `alt`'s two
466
+ * branches are told apart by nothing else.
467
+ */
468
+ export interface UmlInteractionOperand {
469
+ guard?: string;
470
+ y0: number;
471
+ y1: number;
472
+ }
473
+ /**
474
+ * A CombinedFragment (§17.6) — the rectangle with an operator in its corner —
475
+ * and, under the `ref` operator, §17.7's InteractionUse.
476
+ *
477
+ * ONE record for both, because the canvas draws one element for both
478
+ * (`UmlFragmentElementModel`): §17.7.4's InteractionUse is the same rectangle
479
+ * with the same pentagon, and every tool offers it from the same menu. The
480
+ * writers branch on `operator === 'ref'`, which is one line each.
481
+ *
482
+ * `name` is the fragment's own word — the first operand's guard on an `alt`,
483
+ * the referenced interaction's name on a `ref`.
484
+ *
485
+ * `coveredLifelineIds` is GEOMETRY, like every other membership in this file:
486
+ * a fragment covers the lifelines whose spine runs through it, because that is
487
+ * what §17.6.4 draws and a canvas holds no second statement about it.
488
+ */
489
+ export interface UmlCombinedFragment extends UmlNodeBase {
490
+ operator: UmlFragmentOperator;
491
+ operands: UmlInteractionOperand[];
492
+ coveredLifelineIds: string[];
493
+ }
494
+ /**
495
+ * An ExecutionSpecification (§17.2.4) — the thin bar saying the participant is
496
+ * busy between two occurrences.
497
+ *
498
+ * `lifelineId` is the spine the bar sits ON, resolved by measuring
499
+ * ({@link umlLifelineAt}): a bar is a plain node and the canvas holds no
500
+ * parent link, exactly as a port's owner and a lollipop's component are read by
501
+ * measuring. Absent for a bar drawn off every spine — which is on the drawing
502
+ * and in no file.
503
+ */
504
+ export interface UmlExecution extends UmlNodeBase {
505
+ lifelineId?: string;
506
+ /** The occurrence it starts at. */
507
+ y0: number;
508
+ /** The occurrence it finishes at. */
509
+ y1: number;
510
+ }
511
+ /** A DestructionOccurrenceSpecification (§17.2.4) — the X a lifeline ends at. */
512
+ export interface UmlDestruction extends UmlNodeBase {
513
+ lifelineId?: string;
514
+ y: number;
515
+ }
516
+ /**
517
+ * One Interaction — the whole of what an `sd` sheet says.
518
+ *
519
+ * {@link UmlActivity}'s and {@link UmlStateMachine}'s twin, down to the reading
520
+ * that the FRAME IS THE INTERACTION: §17.2.4 draws the interaction as a
521
+ * rectangle with `sd <name>` in its corner, which is Annex A's frame, which is
522
+ * the frame this model was read off.
523
+ */
524
+ export interface UmlInteraction {
525
+ /** The diagram frame's surface id — the Interaction IS the sheet. */
526
+ id: string;
527
+ name: string;
528
+ lifelines: UmlLifeline[];
529
+ /** ORDERED by `y`: top to bottom is earlier to later (§17.4.4). */
530
+ messages: UmlMessage[];
531
+ fragments: UmlCombinedFragment[];
532
+ executions: UmlExecution[];
533
+ destructions: UmlDestruction[];
534
+ }
535
+ /** One diagram, as everything the writers need and nothing else. */
536
+ export interface UmlModel {
537
+ diagram: {
538
+ id: string;
539
+ kind: UmlDiagramKind;
540
+ name: string;
541
+ /** `<kind> <name>` — Annex A's frame heading. */
542
+ heading: string;
543
+ bounds?: UmlBox;
544
+ };
545
+ classifiers: UmlClassifier[];
546
+ packages: UmlPackageNode[];
547
+ actors: UmlActorNode[];
548
+ useCases: UmlUseCaseNode[];
549
+ subjects: UmlSubjectBox[];
550
+ notes: UmlNote[];
551
+ /** §11.6 — the component boxes, each carrying its ports and its interfaces. */
552
+ components: UmlComponentNode[];
553
+ /**
554
+ * §11.3 — every port on the sheet, whether or not it found a host.
555
+ *
556
+ * Listed here AS WELL AS under its component, and the duplication is on
557
+ * purpose: the XMI writer walks the components (a `uml:Port` is an
558
+ * `ownedAttribute`, so it has nowhere else to go) while a reader asking "how
559
+ * many ports are on this sheet" — a check, a count, a later rule — must not
560
+ * have to know that a hostless one is invisible from every component. The two
561
+ * readings hold the SAME record, so they cannot disagree.
562
+ */
563
+ ports: UmlPort[];
564
+ /** §19.3 — the artefacts. */
565
+ artifacts: UmlArtifactNode[];
566
+ /** §19.4 — the nodes, devices and execution environments. */
567
+ nodes: UmlDeploymentNode[];
568
+ /**
569
+ * §15.2 — the Activity this sheet draws, or nothing.
570
+ *
571
+ * A LIST holding zero or one entry rather than an optional field, and the
572
+ * shape is what makes both writers a loop instead of a branch: every other
573
+ * artefact on this model is a list, `for (const activity of model.activities)`
574
+ * reads identically to `for (const component of model.components)`, and a
575
+ * sheet that draws no flow contributes nothing without either writer testing
576
+ * for it. Populated when the sheet holds an activity NODE or an activity EDGE
577
+ * — a lone arrow is still something the author drew.
578
+ */
579
+ activities: UmlActivity[];
580
+ /** §14.2 — the StateMachine this sheet draws, or nothing. The same shape. */
581
+ stateMachines: UmlStateMachine[];
582
+ /** §17.2 — the Interaction this sheet draws, or nothing. The same shape. */
583
+ interactions: UmlInteraction[];
584
+ relations: UmlRelation[];
585
+ /**
586
+ * What the READING could not make sense of, one line each, in the user's
587
+ * words (`InterchangeExportResult.warnings`).
588
+ *
589
+ * Never an error and never noise: the two cases below are both a connector
590
+ * the author DREW that no file can carry, which is the one thing a user who
591
+ * clicked Export is entitled to be told about. A shape with no role, a
592
+ * neutral connector between two neutral shapes, a type name that names
593
+ * nothing on this sheet — none of those is warned about, because none of them
594
+ * is a statement the author made and lost (`docs/adr/0010`).
595
+ */
596
+ warnings: string[];
597
+ }
598
+ /**
599
+ * An element's box, from whichever of the three spellings it carries.
600
+ *
601
+ * `deserializedXYWH` first because that is what a live element answers with;
602
+ * `elementBound` because that is what the shared canvas fixtures build; the
603
+ * serialized `xywh` last, for a record that carries only what the store holds.
604
+ */
605
+ export declare function umlBoundsOf(element: UmlSourceElement): UmlBox | undefined;
606
+ /** Inclusive containment of a box's CENTRE in another box. */
607
+ export declare function umlCentreInside(inner: UmlBox, outer: UmlBox): boolean;
608
+ /**
609
+ * How near a glyph has to be drawn to count as attached to a box, in model
610
+ * units.
611
+ *
612
+ * The one number this file invents, and the reason it is small: §10.4.4 and
613
+ * §11.3.4 both describe a symbol TOUCHING a rectangle — a lollipop "attached by
614
+ * a solid line" to the classifier that realizes it, a port "overlapping the
615
+ * boundary" of the box it is on. Touching is a gap of zero, and a hand drawing
616
+ * on a canvas misses by a few units, so the tolerance is a couple of grid steps
617
+ * and not a neighbourhood: an interface glyph parked halfway across the sheet is
618
+ * not this component's, and a reading that guessed would put an interface in the
619
+ * file that nobody drew.
620
+ *
621
+ * Read by {@link umlHostOf} and by {@link umlBoxGap}'s callers alike, so the
622
+ * port's owner and the interface's component are decided by the same distance.
623
+ */
624
+ export declare const UML_ATTACH_TOLERANCE = 24;
625
+ /**
626
+ * The GAP between two boxes — zero when they touch or overlap, otherwise the
627
+ * shortest distance from edge to edge.
628
+ *
629
+ * Edges, never centres: a lollipop is thirty units across and a component two
630
+ * hundred, so "nearest centre" would hand a glyph to whichever box happens to be
631
+ * squattest rather than to the one it is drawn against. The same argument
632
+ * `gapSquared` makes in the validation engine, one package over.
633
+ */
634
+ export declare function umlBoxGap(a: UmlBox, b: UmlBox): number;
635
+ /**
636
+ * The DRAWING area of a diagram frame — the frame minus its heading band.
637
+ *
638
+ * The same carve-out `c4/export.ts` makes with `backgroundPlot`, arrived at from
639
+ * the MODEL's own constant so this module owes the framework declaration
640
+ * nothing: the top margin is where the frame writes its own heading
641
+ * (`UmlDiagramElementModel`), and an element laid over the heading is on the
642
+ * sheet's chrome rather than on its drawing area.
643
+ */
644
+ export declare function umlSheetOf(frame: UmlBox): UmlBox;
645
+ /** The little {@link umlHostOf} needs to know about a candidate host. */
646
+ export interface UmlHostCandidate {
647
+ id: string;
648
+ bounds?: UmlBox;
649
+ }
650
+ /**
651
+ * Which box a glyph is drawn AGAINST — the one reading that gives a port its
652
+ * owner and a lollipop its component.
653
+ *
654
+ * The nearest host within {@link UML_ATTACH_TOLERANCE}, and `undefined` when
655
+ * nothing is that near: a port drawn in the middle of the sheet belongs to
656
+ * nothing, and inventing an owner for it would put a `uml:Port` on a component
657
+ * the author never drew it on.
658
+ *
659
+ * ## The tie-breaks, and why there are two of them
660
+ *
661
+ * A component nested inside another (§11.6.4's white-box view) puts a port on
662
+ * the boundary of BOTH, at a gap of zero from each. The smaller box wins,
663
+ * because the most-nested container is the one the author was aiming at — the
664
+ * same reading `containerOf` makes in the two writers. And an exact tie on both
665
+ * gap and area is broken by the smaller id, never by the order the surface
666
+ * happened to be walked in: this decides what a FILE says, and a Y.Map rebuilt
667
+ * on every load does not promise an order.
668
+ */
669
+ export declare function umlHostOf<T extends UmlHostCandidate>(glyph: UmlBox | undefined, hosts: readonly T[], tolerance?: number): T | undefined;
670
+ /**
671
+ * The x of a lifeline's SPINE — the dashed line everything on a sequence sheet
672
+ * is measured against.
673
+ *
674
+ * The centre of the element's own box, which is the column and not the head:
675
+ * `UmlNodeElementModel` makes a lifeline a narrow tall column so that the
676
+ * connector layer's native anchors land on the spine, and paints the 160-wide
677
+ * head over the top of it. So the spine is the column's own centre line, and
678
+ * this function exists so that the four readers below cannot each decide that
679
+ * differently.
680
+ */
681
+ export declare function umlSpineX(lifeline: UmlBox): number;
682
+ /**
683
+ * How far off a spine a bar or a cross may be drawn and still be ON it.
684
+ *
685
+ * Half the HEAD's width, and it is the notation's own number rather than a
686
+ * guess: §17.2.4 draws an ExecutionSpecification as a bar centred on the spine
687
+ * and a destruction as a cross centred on it, so the honest tolerance is "nearer
688
+ * to this spine than to any other", and lifelines laid out at the 200-unit
689
+ * spacing of an invented sequence layout are 200 apart. 80 is inside that by a
690
+ * comfortable margin, so a bar dropped a little off centre finds its own
691
+ * lifeline and a bar dropped between two finds neither.
692
+ */
693
+ export declare const UML_SPINE_TOLERANCE: number;
694
+ /**
695
+ * Which lifeline a bar or a cross is drawn ON — {@link umlHostOf}'s twin for
696
+ * §17.2.4's two glyphs.
697
+ *
698
+ * A different reading from `umlHostOf` and deliberately so: a port is attached
699
+ * to a box by TOUCHING it, and a bar is attached to a spine by SITTING ON it —
700
+ * one is an edge-to-edge gap, the other a distance from one vertical line. The
701
+ * nearest spine within {@link UML_SPINE_TOLERANCE} wins; an exact tie is broken
702
+ * by the smaller id, never by the order the surface happened to be walked in,
703
+ * for the reason `umlHostOf` gives: this decides what a FILE says.
704
+ *
705
+ * `undefined` when nothing is that near — a bar drawn between two spines belongs
706
+ * to neither, and inventing an owner for it would put an execution on a
707
+ * participant the author never drew it on.
708
+ */
709
+ export declare function umlLifelineAt<T extends UmlHostCandidate>(glyph: UmlBox | undefined, lifelines: readonly T[]): T | undefined;
710
+ /**
711
+ * The operand bands of a combined fragment, as boxes — §17.6.4's horizontal
712
+ * slices, separated by dashed lines.
713
+ *
714
+ * The operator BAND is carved off the top first (`UML_FRAGMENT_BAND`), exactly
715
+ * as `umlSheetOf` carves the frame's heading off: the pentagon is the
716
+ * fragment's own chrome, and a guard written over it is on the furniture rather
717
+ * than in an operand.
718
+ *
719
+ * `size` is a relative WEIGHT (`UmlFragmentOperand`), so the bands are the body
720
+ * divided in proportion — a fragment dragged taller keeps its operands' shares.
721
+ * A fragment that declares no operands is ONE operand, which is what every
722
+ * `opt`, every `loop` and every `ref` is, and its guard is the fragment's own
723
+ * `name`.
724
+ */
725
+ /**
726
+ * A guard as the IR spells it — §17.6.4's condition with ONE surrounding pair
727
+ * of brackets taken off.
728
+ *
729
+ * The canvas text is exactly what the author types, and §17.6.4.4 prints the
730
+ * condition **in brackets**: `[x > 0]`, `[else]`. So the brackets are stored,
731
+ * the renderer paints them verbatim, and the delimiter is stripped HERE, once,
732
+ * for both writers — PlantUML writes its own `[…]` back round the condition and
733
+ * XMI writes a bare `LiteralString`, and neither should have to parse the
734
+ * model it is given.
735
+ *
736
+ * Tolerant in both directions, because a guard is free text an author types:
737
+ * `x > 0` typed without brackets is the same condition and exports identically,
738
+ * and `[[x > 0]]` gives up exactly one pair. Only a pair that actually
739
+ * SURROUNDS the condition is taken — `[a] or [b]` opens and closes twice, and
740
+ * dropping its outer characters would turn a sentence inside out.
741
+ */
742
+ export declare function umlGuardText(written: string | undefined): string;
743
+ export declare function umlOperandBands(box: UmlBox, operands: readonly UmlFragmentOperand[] | undefined, name: string): UmlInteractionOperand[];
744
+ export interface UmlModelOptions {
745
+ /**
746
+ * Which words belong to which shape — `component.ts`'s
747
+ * {@link umlComponentSiblings}, injectable.
748
+ *
749
+ * Injectable rather than only imported so a caller can resolve a component
750
+ * some other way (a test with a hand-built resolution, a host that already
751
+ * holds the answer) without this module growing a second reading of a group.
752
+ * The default IS `umlComponentSiblings`, so nothing has two behaviours.
753
+ */
754
+ siblingsOf?: (group: UmlComponentGroup, elements: readonly UmlComponentElement[]) => UmlComponent;
755
+ }
756
+ /**
757
+ * One diagram, read off a flat element list.
758
+ *
759
+ * ## What belongs to it
760
+ *
761
+ * Geometry, exactly as every other framework in this library attributes: an
762
+ * element is on this sheet when its CENTRE is inside the frame's drawing area.
763
+ * Selecting a frame therefore selects what is drawn on it, and a second frame
764
+ * beside it is a second diagram — the reading `c4/export.ts` argues for at
765
+ * length, and the reason UML ships four diagram kinds on one canvas (ADR 0017).
766
+ *
767
+ * ## How an end finds its artefact
768
+ *
769
+ * A UML node is drawn as a GROUP — a shape plus its written tiers — and every
770
+ * part of that group is connectable. An arrow dragged onto a class records the
771
+ * id of the group, of the name tier or of the attribute tier about as often as
772
+ * the shape's, and all four look identical to the person drawing it. So each
773
+ * part answers for its shape, and only where the group holds exactly ONE UML
774
+ * node: a lasso somebody drew round two classes points at neither in
775
+ * particular, and guessing there would put a relationship in the file that
776
+ * nobody drew.
777
+ *
778
+ * ## Two things geometry decides, and nothing else does
779
+ *
780
+ * Phase 2 added the only readings in this file that measure one element against
781
+ * ANOTHER element: which component a PORT sits on (§11.3.4) and which component
782
+ * a lollipop or a socket is drawn against (§10.4.4, §11.6.4). Both are the
783
+ * notation's own statement — the specification describes a small symbol placed
784
+ * on or touching a rectangle, and a whiteboard holds no second link to read — so
785
+ * the reading is {@link umlHostOf} and the tolerance is
786
+ * {@link UML_ATTACH_TOLERANCE}. A glyph that touches nothing is kept on the
787
+ * drawing and written into no file, which is the same call the rest of this
788
+ * module makes about anything it cannot attribute.
789
+ *
790
+ * ## What is warned about
791
+ *
792
+ * Two things, and both are a line the author DREW that the file cannot carry: a
793
+ * typed relationship with an end this diagram cannot resolve, and a connector
794
+ * between two UML nodes carrying no role at all. The second is not an error —
795
+ * `docs/adr/0010` is explicit that the role IS the statement, so a bare
796
+ * connector relates nothing — but a user who drew a line between two classes
797
+ * and gets a file without it is owed the sentence.
798
+ *
799
+ * Neither is said about a connector that is not this sheet's. A line belongs to
800
+ * this diagram when at least one of its ends resolves to an artefact of it, or —
801
+ * for a line attached to nothing — when its own centre is inside the sheet.
802
+ * Anything else is another frame's drawing, and warning about it would mean
803
+ * every export of a two-frame board complaining about lines that are perfectly
804
+ * drawn next door.
805
+ */
806
+ export declare function umlModelFrom(diagram: UmlSourceElement, elements: readonly UmlSourceElement[], options?: UmlModelOptions): UmlModel;
807
+ /**
808
+ * One thing that happens on a sequence sheet, at the height it happens at.
809
+ *
810
+ * A discriminated union over the five, and a TREE rather than a list: a combined
811
+ * fragment carries the entries drawn inside each of its operands, which is what
812
+ * §17.6.4 makes it — an `InteractionOperand` OWNS the fragments in its band, and
813
+ * PlantUML's `alt … else … end` is the same nesting spelled with keywords.
814
+ */
815
+ export type UmlTimelineEntry = {
816
+ at: 'message';
817
+ y: number;
818
+ message: UmlMessage;
819
+ } | {
820
+ at: 'execution-start';
821
+ y: number;
822
+ execution: UmlExecution;
823
+ } | {
824
+ at: 'execution-finish';
825
+ y: number;
826
+ execution: UmlExecution;
827
+ } | {
828
+ at: 'destruction';
829
+ y: number;
830
+ destruction: UmlDestruction;
831
+ } | {
832
+ at: 'fragment';
833
+ y: number;
834
+ fragment: UmlCombinedFragment;
835
+ operands: UmlTimelineOperand[];
836
+ };
837
+ /** One operand's band and what is drawn in it. */
838
+ export interface UmlTimelineOperand {
839
+ operand: UmlInteractionOperand;
840
+ entries: UmlTimelineEntry[];
841
+ }
842
+ /**
843
+ * One Interaction as the ordered, nested account of what happens on it — the
844
+ * reading BOTH writers take, so that a `.puml` and an XMI file can never
845
+ * disagree about the order of a conversation.
846
+ *
847
+ * ## What decides that something is INSIDE a fragment
848
+ *
849
+ * Two things, and both are what §17.6.4 draws: the moment falls inside the
850
+ * fragment's box VERTICALLY, and the fragment COVERS the lifeline it happens on
851
+ * ({@link UmlCombinedFragment.coveredLifelineIds}). The second is what stops an
852
+ * `alt` drawn over two of five participants from swallowing a message exchanged
853
+ * between the other three at the same height — which a y-only test would, and
854
+ * which would put an arrow in a branch nobody drew it in.
855
+ *
856
+ * The innermost matching fragment wins, measured by AREA, exactly as `umlHostOf`
857
+ * and `containerOf` decide every other containment in this framework.
858
+ *
859
+ * Pure and total: every message, bar and cross of the interaction comes back
860
+ * exactly once, whether it landed in a fragment or at the top level.
861
+ */
862
+ export declare function umlInteractionTimeline(interaction: UmlInteraction): UmlTimelineEntry[];