@formicoidea/labre-framework-bpmn 0.32.0 → 0.34.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/actions.d.ts +202 -6
  2. package/dist/actions.js +427 -43
  3. package/dist/background.d.ts +2 -0
  4. package/dist/background.js +158 -0
  5. package/dist/commands-manifest.d.ts +18 -0
  6. package/dist/commands-manifest.js +226 -0
  7. package/dist/commands.js +496 -5
  8. package/dist/consts.d.ts +195 -4
  9. package/dist/consts.js +230 -4
  10. package/dist/element-renderer.d.ts +10 -4
  11. package/dist/element-renderer.js +14 -55
  12. package/dist/element-view.d.ts +119 -8
  13. package/dist/element-view.js +274 -30
  14. package/dist/export.d.ts +277 -0
  15. package/dist/export.js +1802 -0
  16. package/dist/facts.d.ts +48 -0
  17. package/dist/facts.js +127 -0
  18. package/dist/import.d.ts +69 -0
  19. package/dist/import.js +1476 -0
  20. package/dist/index.d.ts +12 -0
  21. package/dist/index.js +47 -0
  22. package/dist/interchange.d.ts +109 -0
  23. package/dist/interchange.js +191 -0
  24. package/dist/morph.d.ts +61 -0
  25. package/dist/morph.js +118 -0
  26. package/dist/node/node-renderer.d.ts +0 -9
  27. package/dist/node/node-renderer.js +294 -17
  28. package/dist/pool-hit.d.ts +98 -0
  29. package/dist/pool-hit.js +130 -0
  30. package/dist/presets.d.ts +168 -0
  31. package/dist/presets.js +327 -0
  32. package/dist/profiles.d.ts +2 -0
  33. package/dist/profiles.js +189 -0
  34. package/dist/roles.d.ts +96 -0
  35. package/dist/roles.js +410 -0
  36. package/dist/rules.d.ts +199 -0
  37. package/dist/rules.js +1539 -0
  38. package/dist/templates/index.js +116 -9
  39. package/dist/toolbar/bpmn-senior-button.js +8 -2
  40. package/dist/toolbar/config.d.ts +28 -2
  41. package/dist/toolbar/config.js +93 -4
  42. package/dist/toolbar/icons.d.ts +67 -0
  43. package/dist/toolbar/icons.js +141 -0
  44. package/dist/toolbar/senior-tool.js +1 -0
  45. package/dist/translations.d.ts +3 -1
  46. package/dist/translations.js +38 -3
  47. package/dist/view.d.ts +6 -2
  48. package/dist/view.js +68 -5
  49. package/package.json +6 -2
@@ -0,0 +1,48 @@
1
+ import type { BpmnLane, BpmnPoolElementModel } from '@formicoidea/labre-core/model';
2
+ import type { Bound } from '@formicoidea/labre-core/global/gfx';
3
+ /**
4
+ * The pool whose plot contains the bound's centre, or `null`.
5
+ *
6
+ * ## Which attribution rule this is, and why it is not the audit's whole one
7
+ *
8
+ * The audit attributes in two halves (`attribute()` in `audit.ts`, and
9
+ * `attributeBackground()` in `validation.ts`): the frame that CONTAINS the
10
+ * element, failing that the NEAREST by edge-to-edge gap. This is the containment
11
+ * half only, with the audit's own first-match-in-document-order tie-break —
12
+ * which is the sanctioned reduction, and it is the right one here for two
13
+ * reasons.
14
+ *
15
+ * - The nearest-fallback never returns `null` while a single pool exists on the
16
+ * board. That is correct for an audit, which has to say something about every
17
+ * role-carrying element it reports; it is wrong for a fact query, whose whole
18
+ * value is telling "in this pool" apart from "beside it". A task dropped on
19
+ * bare canvas is not in a pool, and saying so is the answer.
20
+ * - Containment is tested on the CENTRE against the plot, not on the full
21
+ * element box against the element box, so this function and {@link bpmnLaneOf}
22
+ * are the same test at two scales. A laned pool therefore cannot answer "yes,
23
+ * this pool" and "no lane" for a lane set that covers the plot — the two are
24
+ * congruent by construction rather than by agreement.
25
+ *
26
+ * Ties — a centre inside two overlapping pools — go to the first pool in the
27
+ * order given, which for a surface is document order. The audit's `attribute()`
28
+ * returns on its first containing frame the same way.
29
+ */
30
+ export declare function bpmnPoolOf(pools: readonly BpmnPoolElementModel[], bound: Bound): BpmnPoolElementModel | null;
31
+ /**
32
+ * The lane of `pool` the bound's centre falls in — `null` when the pool carries
33
+ * no lane, when the centre is outside its plot, or when the partition is
34
+ * malformed enough that `backgroundInstanceZones` dropped the band it would have
35
+ * been in.
36
+ *
37
+ * The lanes come from the declaration, never from `pool.lanes` read directly:
38
+ * `backgroundInstanceZones` is what normalises the weights into rectangles,
39
+ * drops the rows a user's typo made unusable and redistributes their space, and
40
+ * a second reading of the raw prop would place a task in a band the pool does
41
+ * not paint. The `BpmnLane` handed back is the model's own row, matched by id,
42
+ * so a caller gets the thing it can rename or resize.
43
+ *
44
+ * First match in declaration order, so a centre landing exactly ON a divider
45
+ * belongs to the band ABOVE it. Arbitrary in isolation and deliberate together:
46
+ * it is the tie `zoneAt` breaks, and the two must break it the same way.
47
+ */
48
+ export declare function bpmnLaneOf(pool: BpmnPoolElementModel, bound: Bound): BpmnLane | null;
package/dist/facts.js ADDED
@@ -0,0 +1,127 @@
1
+ import { backgroundInstanceZones, backgroundPlot, } from '@formicoidea/labre-core/blocks/surface';
2
+ import { BPMN_POOL_BACKGROUND } from './background.js';
3
+ /**
4
+ * Where a BPMN artefact SITS — the facts, answerable without a `BlockStdScope`.
5
+ *
6
+ * The audit already computes exactly this (`collectAuditFacts`), and computes it
7
+ * better: it attributes across every framework at once and reports the answer as
8
+ * a serializable fact. What it will not do is answer a question — it runs only
9
+ * for frames matched by a REGISTERED validation rule, and BPMN registers none
10
+ * until the rules session lands. A host, a template check or a rule being
11
+ * written today therefore has nowhere to ask "which lane is this task in", and
12
+ * has been doing the arithmetic by hand at every call site.
13
+ *
14
+ * These two functions are that arithmetic, once. Pure by construction — models
15
+ * and a `Bound` in, model data out; no DI, no std, no signal — so a rule can
16
+ * call them, a test can call them with a stub, and the answer cannot depend on
17
+ * which extensions happen to be registered.
18
+ *
19
+ * ## One convention, copied rather than reinvented
20
+ *
21
+ * Both read the element's CENTRE against ratios of the pool's PLOT, and take the
22
+ * FIRST matching zone in declaration order — the convention `plotRatios` and
23
+ * `zoneAt` already use inside the audit. Copied deliberately and stated here so
24
+ * it stays copied: the day these two disagree with the audit, one component gets
25
+ * two answers about which lane it is in, and no user can be told which is right.
26
+ * The centre also has the property the geometry needs — a task wider than a lane
27
+ * still belongs to exactly one of them.
28
+ */
29
+ /**
30
+ * `lane` — the namespace the pool's instance zones report under.
31
+ *
32
+ * Read off the declaration rather than spelled again: `backgroundInstanceZones`
33
+ * builds `lane:<id>` from this very field, and a second copy of the string is a
34
+ * second thing to keep in step.
35
+ */
36
+ const LANE_PREFIX = BPMN_POOL_BACKGROUND.instanceZones?.idPrefix ?? 'lane';
37
+ /**
38
+ * A bound's centre, as ratios of `pool`'s plot. `null` for a degenerate plot —
39
+ * a pool dragged narrower than its own name band has no flow area to be inside.
40
+ *
41
+ * Ratios of the PLOT and not of the element box, for the reason the audit gives:
42
+ * the margin between the two is where the name band lives, and a task laid over
43
+ * the band is not in the flow area at all.
44
+ */
45
+ function plotRatios(pool, bound) {
46
+ const frame = pool.elementBound;
47
+ const plot = backgroundPlot(BPMN_POOL_BACKGROUND, frame.w, frame.h);
48
+ if (!(plot.width > 0) || !(plot.height > 0))
49
+ return null;
50
+ return [
51
+ (bound.x + bound.w / 2 - frame.x - plot.x0) / plot.width,
52
+ (bound.y + bound.h / 2 - frame.y - plot.y0) / plot.height,
53
+ ];
54
+ }
55
+ /** Inclusive containment of a plot-ratio point, exactly as `zoneAt` tests it. */
56
+ function within(at, rect) {
57
+ return (at[0] >= rect.x &&
58
+ at[0] <= rect.x + rect.w &&
59
+ at[1] >= rect.y &&
60
+ at[1] <= rect.y + rect.h);
61
+ }
62
+ /** The whole plot, as the ratios every zone rectangle is expressed in. */
63
+ const WHOLE_PLOT = { x: 0, y: 0, w: 1, h: 1 };
64
+ /**
65
+ * The pool whose plot contains the bound's centre, or `null`.
66
+ *
67
+ * ## Which attribution rule this is, and why it is not the audit's whole one
68
+ *
69
+ * The audit attributes in two halves (`attribute()` in `audit.ts`, and
70
+ * `attributeBackground()` in `validation.ts`): the frame that CONTAINS the
71
+ * element, failing that the NEAREST by edge-to-edge gap. This is the containment
72
+ * half only, with the audit's own first-match-in-document-order tie-break —
73
+ * which is the sanctioned reduction, and it is the right one here for two
74
+ * reasons.
75
+ *
76
+ * - The nearest-fallback never returns `null` while a single pool exists on the
77
+ * board. That is correct for an audit, which has to say something about every
78
+ * role-carrying element it reports; it is wrong for a fact query, whose whole
79
+ * value is telling "in this pool" apart from "beside it". A task dropped on
80
+ * bare canvas is not in a pool, and saying so is the answer.
81
+ * - Containment is tested on the CENTRE against the plot, not on the full
82
+ * element box against the element box, so this function and {@link bpmnLaneOf}
83
+ * are the same test at two scales. A laned pool therefore cannot answer "yes,
84
+ * this pool" and "no lane" for a lane set that covers the plot — the two are
85
+ * congruent by construction rather than by agreement.
86
+ *
87
+ * Ties — a centre inside two overlapping pools — go to the first pool in the
88
+ * order given, which for a surface is document order. The audit's `attribute()`
89
+ * returns on its first containing frame the same way.
90
+ */
91
+ export function bpmnPoolOf(pools, bound) {
92
+ for (const pool of pools) {
93
+ const at = plotRatios(pool, bound);
94
+ if (at !== null && within(at, WHOLE_PLOT))
95
+ return pool;
96
+ }
97
+ return null;
98
+ }
99
+ /**
100
+ * The lane of `pool` the bound's centre falls in — `null` when the pool carries
101
+ * no lane, when the centre is outside its plot, or when the partition is
102
+ * malformed enough that `backgroundInstanceZones` dropped the band it would have
103
+ * been in.
104
+ *
105
+ * The lanes come from the declaration, never from `pool.lanes` read directly:
106
+ * `backgroundInstanceZones` is what normalises the weights into rectangles,
107
+ * drops the rows a user's typo made unusable and redistributes their space, and
108
+ * a second reading of the raw prop would place a task in a band the pool does
109
+ * not paint. The `BpmnLane` handed back is the model's own row, matched by id,
110
+ * so a caller gets the thing it can rename or resize.
111
+ *
112
+ * First match in declaration order, so a centre landing exactly ON a divider
113
+ * belongs to the band ABOVE it. Arbitrary in isolation and deliberate together:
114
+ * it is the tie `zoneAt` breaks, and the two must break it the same way.
115
+ */
116
+ export function bpmnLaneOf(pool, bound) {
117
+ const at = plotRatios(pool, bound);
118
+ if (at === null)
119
+ return null;
120
+ const zones = backgroundInstanceZones(BPMN_POOL_BACKGROUND, pool);
121
+ for (const zone of zones) {
122
+ if (!within(at, zone.rect))
123
+ continue;
124
+ return (pool.lanes?.find(lane => zone.id === `${LANE_PREFIX}:${lane.id}`) ?? null);
125
+ }
126
+ return null;
127
+ }
@@ -0,0 +1,69 @@
1
+ import type { InterchangeImportContext, InterchangeImportResult } from '@formicoidea/labre-core/blocks/surface';
2
+ import type { BpmnNodeKind } from '@formicoidea/labre-core/model';
3
+ import { BPMN_SCOPE } from './export.js';
4
+ /**
5
+ * The remarks whose wording is FIXED, as `[key, English]` pairs.
6
+ *
7
+ * A reader is a pure function of text (`docs/adr/0012`, P3) and has no `std`,
8
+ * so it cannot ask the host's catalogue for anything: it declares the key on
9
+ * the note and `reportInterchangeImport` resolves it when it draws the report
10
+ * (`InterchangeNote.messageKey`). The English string stays here and stays the
11
+ * fallback, so the console table and a playground with no catalogue read
12
+ * exactly what they read before.
13
+ *
14
+ * These three and no others, and the line is not arbitrary: every remaining
15
+ * remark NAMES something out of the file — `<boundaryEvent>`, an id, a count of
16
+ * lanes — and the seam has neither interpolation nor pluralisation. A key for
17
+ * one of those would be a sentence with holes in it that a translator cannot
18
+ * see the shape of, which is the same refusal the interchange count labels
19
+ * already make (`interchange-import.ts`).
20
+ *
21
+ * They are contributed to the manifest by `./translations.ts`, with the
22
+ * framework, because they ship in the BPMN bundle rather than in core.
23
+ */
24
+ export declare const BPMN_IMPORT_REMARKS: {
25
+ readonly inventedPool: readonly ["com.labre.bpmn.import.remark.invented-pool", "This file names no participant, so its process was drawn in a pool of Labre's own. The pool is not the file's: exporting writes the process back without one."];
26
+ readonly laneGap: readonly ["com.labre.bpmn.import.remark.lane-gap", "The lanes of this pool are drawn with a gap or an overlap between them. Labre lays its bands end to end, so their heights were kept in proportion and the space between them was closed."];
27
+ readonly mustUnderstand: readonly ["com.labre.bpmn.import.remark.must-understand", "The file declares an extension that it says MUST be understood to read the model correctly. Labre does not understand it: the import went ahead, and this reading of the process may be wrong."];
28
+ };
29
+ /**
30
+ * `startEvent` + `messageEventDefinition` → `startEventMessage`, and the
31
+ * sixteen other answers.
32
+ *
33
+ * DERIVED from {@link BPMN_XML_OF_KIND} rather than typed out a second time,
34
+ * which is the only arrangement in which the two directions cannot drift: a
35
+ * kind added to the pack gains its reading the moment it gains its writing, and
36
+ * an element name corrected in the table is corrected in both. The inverse of
37
+ * that table is not a function in general — `startEvent` alone is four kinds —
38
+ * so the key is the PAIR (element name, event definition), which is exactly
39
+ * what the table tells them apart by.
40
+ *
41
+ * That the pair is injective — seventeen kinds, seventeen distinct keys — is a
42
+ * property of the table rather than of this code, so the spec asserts it
43
+ * instead of this line assuming it.
44
+ */
45
+ export declare const BPMN_KIND_OF_XML: ReadonlyMap<string, BpmnNodeKind>;
46
+ /**
47
+ * `.bpmn`'s scope vocabulary — where a carried fragment came off (D2, as
48
+ * amended in #157), and where the writer puts it back.
49
+ *
50
+ * Declared in `export.ts` and re-exported here, for the reason
51
+ * {@link BPMN_FORMAT_ID} is: the reader files a fragment under a scope and the
52
+ * writer looks it up under one, and a table written twice is a table that
53
+ * drifts. See its doc comment there for what a scope means.
54
+ */
55
+ export { BPMN_SCOPE };
56
+ /** The four reasons a fragment is kept and not written back (D5). Closed. */
57
+ export declare const BPMN_QUARANTINE_REASON: {
58
+ readonly colour: string;
59
+ readonly expanded: string;
60
+ readonly nestedLanes: string;
61
+ readonly imported: string;
62
+ };
63
+ /**
64
+ * Read a BPMN 2.0 interchange document as element props plus a report.
65
+ *
66
+ * See the module comment for the contract, and `docs/adr/0012` D1–D6 for why it
67
+ * is this contract and not a shorter one.
68
+ */
69
+ export declare function importBpmnXml(source: string, context?: InterchangeImportContext): InterchangeImportResult;