@formicoidea/labre-framework-bpmn 0.43.1 → 0.46.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/dist/actions.d.ts +11 -1
- package/dist/actions.js +41 -11
- package/dist/consts.d.ts +72 -27
- package/dist/consts.js +106 -42
- package/dist/element-renderer.d.ts +1 -1
- package/dist/export.d.ts +12 -0
- package/dist/export.js +3 -1
- package/dist/import.d.ts +0 -11
- package/dist/import.js +98 -30
- package/dist/interchange.d.ts +7 -12
- package/dist/interchange.js +61 -22
- package/dist/morph.d.ts +37 -1
- package/dist/morph.js +124 -2
- package/dist/node/node-renderer.d.ts +1 -1
- package/dist/node/node-view.d.ts +24 -3
- package/dist/node/node-view.js +31 -4
- package/dist/presets.d.ts +32 -1
- package/dist/presets.js +44 -3
- package/dist/reading.js +41 -3
- package/dist/roles.d.ts +2 -1
- package/dist/roles.js +23 -0
- package/dist/rules.d.ts +4 -1
- package/dist/rules.js +24 -8
- package/dist/templates/index.d.ts +20 -0
- package/dist/templates/index.js +74 -14
- package/dist/toolbar/config.d.ts +2 -2
- package/dist/toolbar/node-config.d.ts +21 -0
- package/dist/toolbar/node-config.js +88 -0
- package/dist/toolbar/senior-tool.d.ts +1 -1
- package/dist/view.js +38 -16
- package/package.json +2 -2
package/dist/actions.d.ts
CHANGED
|
@@ -2,7 +2,17 @@ import { type InterchangeReport, type SerializedElementProps } from '@formicoide
|
|
|
2
2
|
import { type BpmnLane, type BpmnNodeKind, BpmnPoolElementModel } from '@formicoidea/labre-core/model';
|
|
3
3
|
import type { BlockStdScope } from '@formicoidea/labre-core/std';
|
|
4
4
|
import { type BpmnExportBoard } from './export.js';
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Create a flow-object node (native shape) centred on the viewport.
|
|
7
|
+
*
|
|
8
|
+
* An inscribed kind (activities, annotation, group) carries its name as the
|
|
9
|
+
* shape's own inner text. An external kind (events, gateways, data shapes)
|
|
10
|
+
* is born WITHOUT inner text and gets a gravitating label instead: a free
|
|
11
|
+
* `bpmn:label` text centred under the symbol, grouped with it through the
|
|
12
|
+
* native group command — exactly Wardley's `createWardleyNode` (R38). The
|
|
13
|
+
* group is what makes the pair move as one; the role is what tells the name
|
|
14
|
+
* from a note typed beside the process.
|
|
15
|
+
*/
|
|
6
16
|
export declare function createBpmnNode(std: BlockStdScope, kind: BpmnNodeKind): void;
|
|
7
17
|
/** Create a pool (background container) centred on the viewport. */
|
|
8
18
|
export declare function createBpmnPool(std: BlockStdScope): void;
|
package/dist/actions.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { DefaultTool, EdgelessCRUDIdentifier, generateElementId, materializeInterchangeImport, reportInterchangeImport, runInterchangeImportFile, } from '@formicoidea/labre-core/blocks/surface';
|
|
2
2
|
import { ConnectorTool } from '@formicoidea/labre-core/gfx/connector';
|
|
3
|
+
import { createGroupCommand } from '@formicoidea/labre-core/gfx/group';
|
|
3
4
|
import { BpmnPoolElementModel, ConnectorMode, } from '@formicoidea/labre-core/model';
|
|
4
5
|
import { NotificationProvider, translateKey, } from '@formicoidea/labre-core/shared/services';
|
|
5
6
|
import { downloadBlob } from '@formicoidea/labre-core/shared/utils';
|
|
6
7
|
import { Bound } from '@formicoidea/labre-core/global/gfx';
|
|
7
8
|
import { GfxControllerIdentifier } from '@formicoidea/labre-core/std/gfx';
|
|
8
|
-
import { BPMN_EDGE_STYLE, LANE_NAME_FALLBACK, LANE_NAME_KEY, NODE_LABEL, nodeLabelKey, NODE_SIZE, POOL_NAME_FALLBACK, POOL_NAME_KEY, } from './consts.js';
|
|
9
|
+
import { BPMN_EDGE_STYLE, bpmnLabelMode, LANE_NAME_FALLBACK, LANE_NAME_KEY, NODE_LABEL, nodeLabelKey, NODE_SIZE, POOL_NAME_FALLBACK, POOL_NAME_KEY, } from './consts.js';
|
|
9
10
|
import { BPMN_FORMAT_ID, exportBpmnXmlWithWarnings, } from './export.js';
|
|
10
11
|
import { BPMN_SVG_IMPORT, BPMN_XML_EXPORT, BPMN_XML_FORMAT, BPMN_XML_IMPORT, bpmnBoardFrom, bpmnSafeFilename, } from './interchange.js';
|
|
11
|
-
import { bpmnNodeProps, bpmnPoolProps } from './presets.js';
|
|
12
|
+
import { bpmnLabelBoxFor, bpmnLabelProps, bpmnNodeProps, bpmnPoolProps, } from './presets.js';
|
|
12
13
|
import { BPMN_ROLE } from './roles.js';
|
|
13
14
|
/**
|
|
14
15
|
* Standalone creation/activation actions for the BPMN toolbox — lifted out of
|
|
@@ -22,7 +23,28 @@ function finish(gfx, id) {
|
|
|
22
23
|
gfx.selection.set({ elements: [id], editing: false });
|
|
23
24
|
// Keep the palette open (native sub-menu behaviour).
|
|
24
25
|
}
|
|
25
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Group elements; returns the group id, or the first id if grouping failed —
|
|
28
|
+
* the same fallback as Wardley's helper, so a failed group still leaves the
|
|
29
|
+
* symbol selected rather than nothing.
|
|
30
|
+
*/
|
|
31
|
+
function group(gfx, ids) {
|
|
32
|
+
const [, result] = gfx.std.command.exec(createGroupCommand, {
|
|
33
|
+
elements: ids,
|
|
34
|
+
});
|
|
35
|
+
return result.groupId || ids[0];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Create a flow-object node (native shape) centred on the viewport.
|
|
39
|
+
*
|
|
40
|
+
* An inscribed kind (activities, annotation, group) carries its name as the
|
|
41
|
+
* shape's own inner text. An external kind (events, gateways, data shapes)
|
|
42
|
+
* is born WITHOUT inner text and gets a gravitating label instead: a free
|
|
43
|
+
* `bpmn:label` text centred under the symbol, grouped with it through the
|
|
44
|
+
* native group command — exactly Wardley's `createWardleyNode` (R38). The
|
|
45
|
+
* group is what makes the pair move as one; the role is what tells the name
|
|
46
|
+
* from a note typed beside the process.
|
|
47
|
+
*/
|
|
26
48
|
export function createBpmnNode(std, kind) {
|
|
27
49
|
const gfx = gfxOf(std);
|
|
28
50
|
const surface = gfx.surface;
|
|
@@ -30,6 +52,14 @@ export function createBpmnNode(std, kind) {
|
|
|
30
52
|
return;
|
|
31
53
|
const { w, h } = NODE_SIZE[kind];
|
|
32
54
|
const { centerX: cx, centerY: cy } = gfx.viewport;
|
|
55
|
+
// Translated HERE and once: the caption is document content the moment it
|
|
56
|
+
// lands, so the host's catalogue is asked at placement and never again
|
|
57
|
+
// (`nodeLabelKey`, and #183 on why a French board should not start in
|
|
58
|
+
// English).
|
|
59
|
+
const seed = NODE_LABEL[kind]
|
|
60
|
+
? translateKey(std, nodeLabelKey(kind), NODE_LABEL[kind])
|
|
61
|
+
: undefined;
|
|
62
|
+
const external = bpmnLabelMode(kind) === 'external';
|
|
33
63
|
// What a node IS lives in one place (`./presets.ts`), because the importer
|
|
34
64
|
// creates the same artefacts out of a `.bpmn` file and the two must not
|
|
35
65
|
// drift: a task read from a file and a task drawn here are one element type
|
|
@@ -37,15 +67,15 @@ export function createBpmnNode(std, kind) {
|
|
|
37
67
|
// nothing else.
|
|
38
68
|
const id = surface.addElement(bpmnNodeProps(kind, {
|
|
39
69
|
xywh: new Bound(cx - w / 2, cy - h / 2, w, h).serialize(),
|
|
40
|
-
|
|
41
|
-
// it lands, so the host's catalogue is asked at placement and never
|
|
42
|
-
// again (`nodeLabelKey`, and #183 on why a French board should not
|
|
43
|
-
// start in English).
|
|
44
|
-
text: NODE_LABEL[kind]
|
|
45
|
-
? translateKey(std, nodeLabelKey(kind), NODE_LABEL[kind])
|
|
46
|
-
: undefined,
|
|
70
|
+
text: external ? undefined : seed,
|
|
47
71
|
}));
|
|
48
|
-
|
|
72
|
+
if (!external || seed === undefined) {
|
|
73
|
+
finish(gfx, id);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const { x, y } = bpmnLabelBoxFor(kind, cx, cy);
|
|
77
|
+
const labelId = surface.addElement(bpmnLabelProps(seed, x, y));
|
|
78
|
+
finish(gfx, group(gfx, [id, labelId]));
|
|
49
79
|
}
|
|
50
80
|
/** Create a pool (background container) centred on the viewport. */
|
|
51
81
|
export function createBpmnPool(std) {
|
package/dist/consts.d.ts
CHANGED
|
@@ -35,8 +35,9 @@ export declare const CALL_ACTIVITY_WIDTH = 4;
|
|
|
35
35
|
/** Task corner radius (absolute px — a lightly rounded rectangle). */
|
|
36
36
|
export declare const TASK_RADIUS = 10;
|
|
37
37
|
/**
|
|
38
|
-
* The group's corner radius — twice a task's, because
|
|
39
|
-
*
|
|
38
|
+
* The group's corner radius — twice a task's, because a group is born the
|
|
39
|
+
* biggest artefact on the board and a 10-unit corner on a 300-unit box reads
|
|
40
|
+
* as a square one.
|
|
40
41
|
*/
|
|
41
42
|
export declare const GROUP_RADIUS = 20;
|
|
42
43
|
/**
|
|
@@ -58,7 +59,8 @@ export declare const INNER_FONT_SIZE = 18;
|
|
|
58
59
|
*
|
|
59
60
|
* A file draws its artefacts at whatever scale its author's tool uses, and
|
|
60
61
|
* bpmn.io's normative sizes are about six tenths of this pack's: a 36-unit
|
|
61
|
-
* event against a 56-unit one, a 100×
|
|
62
|
+
* event against a 56-unit one, a 100×80 task against the 120×72 activities are
|
|
63
|
+
* fitted against (`ACTIVITY_FIT_REF`). The label of an
|
|
62
64
|
* imported artefact is therefore asked for at a size proportional to the box
|
|
63
65
|
* the FILE gave, and 10 is where that shrinking stops — under it a label is no
|
|
64
66
|
* longer read, it is guessed at.
|
|
@@ -75,19 +77,20 @@ export declare const LABEL_MIN_FONT_SIZE = 10;
|
|
|
75
77
|
* How much of a box a fitted label gives up to its margin, per side.
|
|
76
78
|
*
|
|
77
79
|
* A shape's native inset is a FIXED 20 units horizontally
|
|
78
|
-
* (`SHAPE_TEXT_PADDING`), which is a sixth of
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
80
|
+
* (`SHAPE_TEXT_PADDING`), which is a sixth of the 120-unit activity width
|
|
81
|
+
* labels are fitted against (`ACTIVITY_FIT_REF`) and therefore invisible on a
|
|
82
|
+
* drawn board — and more than the whole width of a 36-unit event, which leaves
|
|
83
|
+
* NEGATIVE room for the text and is why an imported label breaks in the middle
|
|
84
|
+
* of a word. Expressed as a ratio, the margin follows the artefact down: it is
|
|
85
|
+
* exactly the native inset at 120 units and it never grows past it (the cap in
|
|
86
|
+
* `bpmnLabelFit`), so a drawn node — 180 wide since activities grew — is
|
|
87
|
+
* untouched and a small one keeps a usable line.
|
|
85
88
|
*/
|
|
86
89
|
export declare const LABEL_INSET_RATIO: number;
|
|
87
90
|
/**
|
|
88
91
|
* Default node sizes (model units) per kind.
|
|
89
92
|
*
|
|
90
|
-
* Three sizes carry the whole scale: the 56-unit event, the
|
|
93
|
+
* Three sizes carry the whole scale: the 56-unit event, the 180×108 task and the
|
|
91
94
|
* 72-unit gateway. Everything the descriptive profile adds takes one of them —
|
|
92
95
|
* a message start is a start event, a user task is a task — except the three
|
|
93
96
|
* data/artifact shapes, which have no sibling to inherit from:
|
|
@@ -96,32 +99,74 @@ export declare const LABEL_INSET_RATIO: number;
|
|
|
96
99
|
* 56-unit event without looking like a shrunken task;
|
|
97
100
|
* - `dataStore` is the event's own diameter, which is what a cylinder needs to
|
|
98
101
|
* read as one rather than as a squashed ellipse;
|
|
99
|
-
* - `textAnnotation` is
|
|
100
|
-
* not a verb phrase.
|
|
102
|
+
* - `textAnnotation` is a wide, short strip (140×48) — it holds a sentence,
|
|
103
|
+
* not a verb phrase. It was sized against the 120×72 task and kept when the
|
|
104
|
+
* activities grew.
|
|
101
105
|
*
|
|
102
106
|
* These three are ~1.2–1.4× bpmn.io's normative pixel sizes, which is the ratio
|
|
103
|
-
* this pack's event
|
|
107
|
+
* this pack's event sits at against the same reference (the activities sat
|
|
108
|
+
* there too until they grew 1.5×, see below).
|
|
104
109
|
*
|
|
105
110
|
* `group` is on no scale at all: it is a LASSO, so it has to be born big enough
|
|
106
|
-
* to have something in it
|
|
107
|
-
*
|
|
111
|
+
* to have something in it — bigger than any other artefact on both axes. It
|
|
112
|
+
* was sized for two 120×72 tasks and the arrow between them; since the
|
|
113
|
+
* activities grew it holds one task with room around it, and the author
|
|
114
|
+
* stretches it from there.
|
|
108
115
|
*/
|
|
109
116
|
export declare const NODE_SIZE: Record<BpmnNodeKind, {
|
|
110
117
|
w: number;
|
|
111
118
|
h: number;
|
|
112
119
|
}>;
|
|
113
120
|
/**
|
|
114
|
-
*
|
|
121
|
+
* The box an ACTIVITY's inscribed label is fitted against on import
|
|
122
|
+
* (`bpmnLabelFit`, `presets.ts`) — the 120×72 the drawn task shipped at, kept
|
|
123
|
+
* as the fit reference when the drawn task grew to 180×108.
|
|
115
124
|
*
|
|
116
|
-
* The
|
|
117
|
-
*
|
|
118
|
-
*
|
|
125
|
+
* The fit scales the 18-unit type by how much smaller a file's box is than
|
|
126
|
+
* "the box this typography is comfortable in". That box did not change when
|
|
127
|
+
* the palette's did: 18 units were comfortable at 120×72 (that is why the pack
|
|
128
|
+
* shipped there), so a bpmn.io task of 100×80 still reads at 15 units rather
|
|
129
|
+
* than falling to the 10-unit floor it would hit against 180×108.
|
|
130
|
+
*/
|
|
131
|
+
export declare const ACTIVITY_FIT_REF: {
|
|
132
|
+
w: number;
|
|
133
|
+
h: number;
|
|
134
|
+
};
|
|
135
|
+
/** The five activity kinds — the ones drawn at the 180×108 box. */
|
|
136
|
+
export declare const isBpmnActivityKind: (kind: BpmnNodeKind) => boolean;
|
|
137
|
+
/**
|
|
138
|
+
* The kinds whose name GRAVITATES: a free text element centred under the
|
|
139
|
+
* symbol, grouped with it — never the shape's own inner text (R38).
|
|
140
|
+
*
|
|
141
|
+
* Events, gateways and the two data shapes are small, punctual symbols: two
|
|
142
|
+
* five-letter words at 18 units do not fit a 56-unit ring or a 72-unit diamond
|
|
143
|
+
* without enlarging it, and the glyph is already inside. BPMN itself draws
|
|
144
|
+
* their name below the symbol, which is what `bpmnLabelBoxFor` places.
|
|
145
|
+
*
|
|
146
|
+
* The activities, the annotation and the group stay INSCRIBED: the label fits
|
|
147
|
+
* (`label-mode.unit.spec.ts` proves it against the rule's arithmetic), and for
|
|
148
|
+
* the annotation the text IS the artefact.
|
|
149
|
+
*
|
|
150
|
+
* A stored node keeps whatever it was born with: an event drawn before this
|
|
151
|
+
* list existed carries inner text and keeps painting it. Nothing is migrated.
|
|
152
|
+
*/
|
|
153
|
+
export declare const BPMN_EXTERNAL_LABEL_KINDS: readonly ["startEvent", "startEventMessage", "startEventTimer", "endEvent", "endEventMessage", "endEventTerminate", "gatewayExclusive", "gatewayParallel", "dataObject", "dataStore"];
|
|
154
|
+
/** Whether a kind's name is the shape's inner text or a grouped text beside it. */
|
|
155
|
+
export declare const bpmnLabelMode: (kind: BpmnNodeKind) => "inscribed" | "external";
|
|
156
|
+
/** Gravitating-label metrics: a 120-wide, one-line box under the symbol. */
|
|
157
|
+
export declare const LABEL_FONT_SIZE = 18;
|
|
158
|
+
export declare const BPMN_LABEL_W = 120;
|
|
159
|
+
export declare const BPMN_LABEL_H: number;
|
|
160
|
+
/** Gap between the symbol's bottom edge and the label's top. */
|
|
161
|
+
export declare const BPMN_LABEL_GAP = 6;
|
|
162
|
+
/**
|
|
163
|
+
* Default text per kind — the shape's inner text for an inscribed kind, the
|
|
164
|
+
* grouped label's text for an external one ({@link bpmnLabelMode}).
|
|
119
165
|
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* honest failure rather than a label painted over the glyph.
|
|
166
|
+
* Every kind carries one, because a symbol whose label is born empty is a text
|
|
167
|
+
* element nobody can find to click (PO, 24/09/2026 — the Wardley precedent
|
|
168
|
+
* seeds "Component" for the same reason). The external kinds are seeded with
|
|
169
|
+
* the spec's own name for the artefact, the wording their role already carries.
|
|
125
170
|
*
|
|
126
171
|
* The caption is asked of the host's catalogue under {@link nodeLabelKey} when
|
|
127
172
|
* the artefact is placed, with the entry below as the English default.
|
|
@@ -133,8 +178,8 @@ export declare const NODE_LABEL: Record<BpmnNodeKind, string>;
|
|
|
133
178
|
* Resolved AT PLACEMENT (`createBpmnNode`) and never afterwards: what a gesture
|
|
134
179
|
* writes into the document is content the author owns from that moment on, and
|
|
135
180
|
* a renderer that re-translated it on every paint would silently overwrite a
|
|
136
|
-
* name somebody typed.
|
|
137
|
-
*
|
|
181
|
+
* name somebody typed. Every kind has a seed now; for an external kind it is
|
|
182
|
+
* written into the grouped `bpmn:label` rather than the shape (R38).
|
|
138
183
|
*/
|
|
139
184
|
export declare const nodeLabelKey: (kind: BpmnNodeKind) => string;
|
|
140
185
|
/**
|
package/dist/consts.js
CHANGED
|
@@ -35,8 +35,9 @@ export const CALL_ACTIVITY_WIDTH = END_WIDTH;
|
|
|
35
35
|
/** Task corner radius (absolute px — a lightly rounded rectangle). */
|
|
36
36
|
export const TASK_RADIUS = 10;
|
|
37
37
|
/**
|
|
38
|
-
* The group's corner radius — twice a task's, because
|
|
39
|
-
*
|
|
38
|
+
* The group's corner radius — twice a task's, because a group is born the
|
|
39
|
+
* biggest artefact on the board and a 10-unit corner on a 300-unit box reads
|
|
40
|
+
* as a square one.
|
|
40
41
|
*/
|
|
41
42
|
export const GROUP_RADIUS = 20;
|
|
42
43
|
/**
|
|
@@ -58,7 +59,8 @@ export const INNER_FONT_SIZE = 18;
|
|
|
58
59
|
*
|
|
59
60
|
* A file draws its artefacts at whatever scale its author's tool uses, and
|
|
60
61
|
* bpmn.io's normative sizes are about six tenths of this pack's: a 36-unit
|
|
61
|
-
* event against a 56-unit one, a 100×
|
|
62
|
+
* event against a 56-unit one, a 100×80 task against the 120×72 activities are
|
|
63
|
+
* fitted against (`ACTIVITY_FIT_REF`). The label of an
|
|
62
64
|
* imported artefact is therefore asked for at a size proportional to the box
|
|
63
65
|
* the FILE gave, and 10 is where that shrinking stops — under it a label is no
|
|
64
66
|
* longer read, it is guessed at.
|
|
@@ -75,19 +77,20 @@ export const LABEL_MIN_FONT_SIZE = 10;
|
|
|
75
77
|
* How much of a box a fitted label gives up to its margin, per side.
|
|
76
78
|
*
|
|
77
79
|
* A shape's native inset is a FIXED 20 units horizontally
|
|
78
|
-
* (`SHAPE_TEXT_PADDING`), which is a sixth of
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
80
|
+
* (`SHAPE_TEXT_PADDING`), which is a sixth of the 120-unit activity width
|
|
81
|
+
* labels are fitted against (`ACTIVITY_FIT_REF`) and therefore invisible on a
|
|
82
|
+
* drawn board — and more than the whole width of a 36-unit event, which leaves
|
|
83
|
+
* NEGATIVE room for the text and is why an imported label breaks in the middle
|
|
84
|
+
* of a word. Expressed as a ratio, the margin follows the artefact down: it is
|
|
85
|
+
* exactly the native inset at 120 units and it never grows past it (the cap in
|
|
86
|
+
* `bpmnLabelFit`), so a drawn node — 180 wide since activities grew — is
|
|
87
|
+
* untouched and a small one keeps a usable line.
|
|
85
88
|
*/
|
|
86
89
|
export const LABEL_INSET_RATIO = 1 / 6;
|
|
87
90
|
/**
|
|
88
91
|
* Default node sizes (model units) per kind.
|
|
89
92
|
*
|
|
90
|
-
* Three sizes carry the whole scale: the 56-unit event, the
|
|
93
|
+
* Three sizes carry the whole scale: the 56-unit event, the 180×108 task and the
|
|
91
94
|
* 72-unit gateway. Everything the descriptive profile adds takes one of them —
|
|
92
95
|
* a message start is a start event, a user task is a task — except the three
|
|
93
96
|
* data/artifact shapes, which have no sibling to inherit from:
|
|
@@ -96,15 +99,19 @@ export const LABEL_INSET_RATIO = 1 / 6;
|
|
|
96
99
|
* 56-unit event without looking like a shrunken task;
|
|
97
100
|
* - `dataStore` is the event's own diameter, which is what a cylinder needs to
|
|
98
101
|
* read as one rather than as a squashed ellipse;
|
|
99
|
-
* - `textAnnotation` is
|
|
100
|
-
* not a verb phrase.
|
|
102
|
+
* - `textAnnotation` is a wide, short strip (140×48) — it holds a sentence,
|
|
103
|
+
* not a verb phrase. It was sized against the 120×72 task and kept when the
|
|
104
|
+
* activities grew.
|
|
101
105
|
*
|
|
102
106
|
* These three are ~1.2–1.4× bpmn.io's normative pixel sizes, which is the ratio
|
|
103
|
-
* this pack's event
|
|
107
|
+
* this pack's event sits at against the same reference (the activities sat
|
|
108
|
+
* there too until they grew 1.5×, see below).
|
|
104
109
|
*
|
|
105
110
|
* `group` is on no scale at all: it is a LASSO, so it has to be born big enough
|
|
106
|
-
* to have something in it
|
|
107
|
-
*
|
|
111
|
+
* to have something in it — bigger than any other artefact on both axes. It
|
|
112
|
+
* was sized for two 120×72 tasks and the arrow between them; since the
|
|
113
|
+
* activities grew it holds one task with room around it, and the author
|
|
114
|
+
* stretches it from there.
|
|
108
115
|
*/
|
|
109
116
|
export const NODE_SIZE = {
|
|
110
117
|
startEvent: { w: 56, h: 56 },
|
|
@@ -113,11 +120,14 @@ export const NODE_SIZE = {
|
|
|
113
120
|
endEvent: { w: 56, h: 56 },
|
|
114
121
|
endEventMessage: { w: 56, h: 56 },
|
|
115
122
|
endEventTerminate: { w: 56, h: 56 },
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
123
|
+
// Activities: 1.5× the 120×72 they shipped at (user feedback, 24/09/2026):
|
|
124
|
+
// the inscribed label at 18 units needs the room, and the type does not
|
|
125
|
+
// grow with the box (R38, `docs/add-a-framework/02-framework-rules.md`).
|
|
126
|
+
task: { w: 180, h: 108 },
|
|
127
|
+
taskUser: { w: 180, h: 108 },
|
|
128
|
+
taskService: { w: 180, h: 108 },
|
|
129
|
+
subProcess: { w: 180, h: 108 },
|
|
130
|
+
callActivity: { w: 180, h: 108 },
|
|
121
131
|
gatewayExclusive: { w: 72, h: 72 },
|
|
122
132
|
gatewayParallel: { w: 72, h: 72 },
|
|
123
133
|
dataObject: { w: 48, h: 64 },
|
|
@@ -126,37 +136,91 @@ export const NODE_SIZE = {
|
|
|
126
136
|
group: { w: 300, h: 200 },
|
|
127
137
|
};
|
|
128
138
|
/**
|
|
129
|
-
*
|
|
139
|
+
* The box an ACTIVITY's inscribed label is fitted against on import
|
|
140
|
+
* (`bpmnLabelFit`, `presets.ts`) — the 120×72 the drawn task shipped at, kept
|
|
141
|
+
* as the fit reference when the drawn task grew to 180×108.
|
|
130
142
|
*
|
|
131
|
-
* The
|
|
132
|
-
*
|
|
133
|
-
*
|
|
143
|
+
* The fit scales the 18-unit type by how much smaller a file's box is than
|
|
144
|
+
* "the box this typography is comfortable in". That box did not change when
|
|
145
|
+
* the palette's did: 18 units were comfortable at 120×72 (that is why the pack
|
|
146
|
+
* shipped there), so a bpmn.io task of 100×80 still reads at 15 units rather
|
|
147
|
+
* than falling to the 10-unit floor it would hit against 180×108.
|
|
148
|
+
*/
|
|
149
|
+
export const ACTIVITY_FIT_REF = { w: 120, h: 72 };
|
|
150
|
+
const ACTIVITY_KINDS = new Set([
|
|
151
|
+
'task',
|
|
152
|
+
'taskUser',
|
|
153
|
+
'taskService',
|
|
154
|
+
'subProcess',
|
|
155
|
+
'callActivity',
|
|
156
|
+
]);
|
|
157
|
+
/** The five activity kinds — the ones drawn at the 180×108 box. */
|
|
158
|
+
export const isBpmnActivityKind = (kind) => ACTIVITY_KINDS.has(kind);
|
|
159
|
+
/**
|
|
160
|
+
* The kinds whose name GRAVITATES: a free text element centred under the
|
|
161
|
+
* symbol, grouped with it — never the shape's own inner text (R38).
|
|
162
|
+
*
|
|
163
|
+
* Events, gateways and the two data shapes are small, punctual symbols: two
|
|
164
|
+
* five-letter words at 18 units do not fit a 56-unit ring or a 72-unit diamond
|
|
165
|
+
* without enlarging it, and the glyph is already inside. BPMN itself draws
|
|
166
|
+
* their name below the symbol, which is what `bpmnLabelBoxFor` places.
|
|
167
|
+
*
|
|
168
|
+
* The activities, the annotation and the group stay INSCRIBED: the label fits
|
|
169
|
+
* (`label-mode.unit.spec.ts` proves it against the rule's arithmetic), and for
|
|
170
|
+
* the annotation the text IS the artefact.
|
|
171
|
+
*
|
|
172
|
+
* A stored node keeps whatever it was born with: an event drawn before this
|
|
173
|
+
* list existed carries inner text and keeps painting it. Nothing is migrated.
|
|
174
|
+
*/
|
|
175
|
+
export const BPMN_EXTERNAL_LABEL_KINDS = [
|
|
176
|
+
'startEvent',
|
|
177
|
+
'startEventMessage',
|
|
178
|
+
'startEventTimer',
|
|
179
|
+
'endEvent',
|
|
180
|
+
'endEventMessage',
|
|
181
|
+
'endEventTerminate',
|
|
182
|
+
'gatewayExclusive',
|
|
183
|
+
'gatewayParallel',
|
|
184
|
+
'dataObject',
|
|
185
|
+
'dataStore',
|
|
186
|
+
];
|
|
187
|
+
const EXTERNAL_LABEL_KINDS = new Set(BPMN_EXTERNAL_LABEL_KINDS);
|
|
188
|
+
/** Whether a kind's name is the shape's inner text or a grouped text beside it. */
|
|
189
|
+
export const bpmnLabelMode = (kind) => EXTERNAL_LABEL_KINDS.has(kind) ? 'external' : 'inscribed';
|
|
190
|
+
/** Gravitating-label metrics: a 120-wide, one-line box under the symbol. */
|
|
191
|
+
export const LABEL_FONT_SIZE = INNER_FONT_SIZE;
|
|
192
|
+
export const BPMN_LABEL_W = 120;
|
|
193
|
+
export const BPMN_LABEL_H = LABEL_FONT_SIZE + 8;
|
|
194
|
+
/** Gap between the symbol's bottom edge and the label's top. */
|
|
195
|
+
export const BPMN_LABEL_GAP = 6;
|
|
196
|
+
/**
|
|
197
|
+
* Default text per kind — the shape's inner text for an inscribed kind, the
|
|
198
|
+
* grouped label's text for an external one ({@link bpmnLabelMode}).
|
|
134
199
|
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* honest failure rather than a label painted over the glyph.
|
|
200
|
+
* Every kind carries one, because a symbol whose label is born empty is a text
|
|
201
|
+
* element nobody can find to click (PO, 24/09/2026 — the Wardley precedent
|
|
202
|
+
* seeds "Component" for the same reason). The external kinds are seeded with
|
|
203
|
+
* the spec's own name for the artefact, the wording their role already carries.
|
|
140
204
|
*
|
|
141
205
|
* The caption is asked of the host's catalogue under {@link nodeLabelKey} when
|
|
142
206
|
* the artefact is placed, with the entry below as the English default.
|
|
143
207
|
*/
|
|
144
208
|
export const NODE_LABEL = {
|
|
145
|
-
startEvent: '',
|
|
146
|
-
startEventMessage: '',
|
|
147
|
-
startEventTimer: '',
|
|
148
|
-
endEvent: '',
|
|
149
|
-
endEventMessage: '',
|
|
150
|
-
endEventTerminate: '',
|
|
209
|
+
startEvent: 'Start event',
|
|
210
|
+
startEventMessage: 'Message start event',
|
|
211
|
+
startEventTimer: 'Timer start event',
|
|
212
|
+
endEvent: 'End event',
|
|
213
|
+
endEventMessage: 'Message end event',
|
|
214
|
+
endEventTerminate: 'Terminate end event',
|
|
151
215
|
task: 'Task',
|
|
152
216
|
taskUser: 'User task',
|
|
153
217
|
taskService: 'Service task',
|
|
154
218
|
subProcess: 'Sub-process',
|
|
155
219
|
callActivity: 'Call activity',
|
|
156
|
-
gatewayExclusive: '',
|
|
157
|
-
gatewayParallel: '',
|
|
158
|
-
dataObject: '',
|
|
159
|
-
dataStore: '',
|
|
220
|
+
gatewayExclusive: 'Exclusive gateway',
|
|
221
|
+
gatewayParallel: 'Parallel gateway',
|
|
222
|
+
dataObject: 'Data object',
|
|
223
|
+
dataStore: 'Data store',
|
|
160
224
|
// The one artefact that IS its text.
|
|
161
225
|
textAnnotation: 'Annotation',
|
|
162
226
|
// The group's label is a CategoryValue in the spec. A plain editable string
|
|
@@ -170,8 +234,8 @@ export const NODE_LABEL = {
|
|
|
170
234
|
* Resolved AT PLACEMENT (`createBpmnNode`) and never afterwards: what a gesture
|
|
171
235
|
* writes into the document is content the author owns from that moment on, and
|
|
172
236
|
* a renderer that re-translated it on every paint would silently overwrite a
|
|
173
|
-
* name somebody typed.
|
|
174
|
-
*
|
|
237
|
+
* name somebody typed. Every kind has a seed now; for an external kind it is
|
|
238
|
+
* written into the grouped `bpmn:label` rather than the shape (R38).
|
|
175
239
|
*/
|
|
176
240
|
export const nodeLabelKey = (kind) => `com.labre.bpmn.seed.${kind}`;
|
|
177
241
|
/**
|
|
@@ -13,6 +13,6 @@ import type { BpmnPoolElementModel } from '@formicoidea/labre-core/model';
|
|
|
13
13
|
* drives it directly with a canvas stub.
|
|
14
14
|
*/
|
|
15
15
|
export declare const bpmnPool: ElementRenderer<BpmnPoolElementModel>;
|
|
16
|
-
export declare const BpmnPoolRendererExtension: import("@formicoidea/labre-core/store").ExtensionType & {
|
|
16
|
+
export declare const BpmnPoolRendererExtension: import("@formicoidea/labre-core/_pkgs/store").ExtensionType & {
|
|
17
17
|
identifier: import("@formicoidea/labre-core/_pkgs/global/di").ServiceIdentifier<ElementRenderer<BpmnPoolElementModel>>;
|
|
18
18
|
};
|
package/dist/export.d.ts
CHANGED
|
@@ -217,6 +217,18 @@ export interface BpmnExportBoard {
|
|
|
217
217
|
pools: readonly BpmnPoolElementModel[];
|
|
218
218
|
nodes: readonly BpmnNodeElementModel[];
|
|
219
219
|
connectors: readonly ConnectorElementModel[];
|
|
220
|
+
/**
|
|
221
|
+
* A node's gravitating name, keyed by the node's surface id: the text of the
|
|
222
|
+
* `bpmn:label` that shares its native group (R38, `bpmnLabelMode`).
|
|
223
|
+
*
|
|
224
|
+
* Resolved by whoever picked the board (`bpmnBoardFrom`), because group
|
|
225
|
+
* membership is a fact about the surface and this writer sees none of it.
|
|
226
|
+
* GROUP membership is the binding and never geometry: a label dragged away
|
|
227
|
+
* from its event is still its name, and a text that happens to sit under an
|
|
228
|
+
* event is not. A node with no entry falls back to its own `text` — every
|
|
229
|
+
* inscribed kind, and an event drawn before its name gravitated.
|
|
230
|
+
*/
|
|
231
|
+
labels?: ReadonlyMap<string, string>;
|
|
220
232
|
/**
|
|
221
233
|
* How many things drawn INSIDE a pool the picking left behind because they
|
|
222
234
|
* carry no BPMN role — a free shape, a text, an artefact drawn before roles
|
package/dist/export.js
CHANGED
|
@@ -1128,7 +1128,9 @@ export function exportBpmnXmlWithWarnings(board, options = {}) {
|
|
|
1128
1128
|
: hasCollaboration && mapping.slot === 'artifact'
|
|
1129
1129
|
? COLLABORATION
|
|
1130
1130
|
: orphanProcessIndex();
|
|
1131
|
-
|
|
1131
|
+
// The grouped label first, then the shape's own text: a legacy event kept
|
|
1132
|
+
// its inner text and must still export the same name.
|
|
1133
|
+
const name = labelOf(board.labels?.get(model.id)) || labelOf(model.text);
|
|
1132
1134
|
const node = {
|
|
1133
1135
|
model,
|
|
1134
1136
|
mapping,
|
package/dist/import.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type InterchangeImportContext, type InterchangeImportResult } from '@formicoidea/labre-core/blocks/surface';
|
|
2
2
|
import type { BpmnNodeKind } from '@formicoidea/labre-core/model';
|
|
3
|
-
import { BPMN_SCOPE } from './export.js';
|
|
4
3
|
/**
|
|
5
4
|
* The remarks whose wording is FIXED, as `[key, English]` pairs — one entry
|
|
6
5
|
* per SHAPE of sentence, never one per exact string: a remark that names
|
|
@@ -91,16 +90,6 @@ export declare const BPMN_IMPORT_ERRORS: {
|
|
|
91
90
|
* instead of this line assuming it.
|
|
92
91
|
*/
|
|
93
92
|
export declare const BPMN_KIND_OF_XML: ReadonlyMap<string, BpmnNodeKind>;
|
|
94
|
-
/**
|
|
95
|
-
* `.bpmn`'s scope vocabulary — where a carried fragment came off (D2, as
|
|
96
|
-
* amended in #157), and where the writer puts it back.
|
|
97
|
-
*
|
|
98
|
-
* Declared in `export.ts` and re-exported here, for the reason
|
|
99
|
-
* {@link BPMN_FORMAT_ID} is: the reader files a fragment under a scope and the
|
|
100
|
-
* writer looks it up under one, and a table written twice is a table that
|
|
101
|
-
* drifts. See its doc comment there for what a scope means.
|
|
102
|
-
*/
|
|
103
|
-
export { BPMN_SCOPE };
|
|
104
93
|
/** The four reasons a fragment is kept and not written back (D5). Closed. */
|
|
105
94
|
export declare const BPMN_QUARANTINE_REASON: {
|
|
106
95
|
readonly colour: string;
|