@formicoidea/labre-framework-bpmn 0.32.0 → 0.33.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 (47) hide show
  1. package/dist/actions.d.ts +202 -6
  2. package/dist/actions.js +421 -43
  3. package/dist/background.d.ts +2 -0
  4. package/dist/background.js +158 -0
  5. package/dist/commands.js +496 -5
  6. package/dist/consts.d.ts +157 -3
  7. package/dist/consts.js +192 -3
  8. package/dist/element-renderer.d.ts +10 -4
  9. package/dist/element-renderer.js +14 -55
  10. package/dist/element-view.d.ts +100 -8
  11. package/dist/element-view.js +249 -30
  12. package/dist/export.d.ts +277 -0
  13. package/dist/export.js +1802 -0
  14. package/dist/facts.d.ts +48 -0
  15. package/dist/facts.js +127 -0
  16. package/dist/import.d.ts +44 -0
  17. package/dist/import.js +1440 -0
  18. package/dist/index.d.ts +12 -0
  19. package/dist/index.js +44 -0
  20. package/dist/interchange.d.ts +109 -0
  21. package/dist/interchange.js +191 -0
  22. package/dist/morph.d.ts +61 -0
  23. package/dist/morph.js +118 -0
  24. package/dist/node/node-renderer.d.ts +0 -9
  25. package/dist/node/node-renderer.js +294 -17
  26. package/dist/pool-hit.d.ts +98 -0
  27. package/dist/pool-hit.js +130 -0
  28. package/dist/presets.d.ts +114 -0
  29. package/dist/presets.js +232 -0
  30. package/dist/profiles.d.ts +2 -0
  31. package/dist/profiles.js +189 -0
  32. package/dist/roles.d.ts +96 -0
  33. package/dist/roles.js +410 -0
  34. package/dist/rules.d.ts +199 -0
  35. package/dist/rules.js +1539 -0
  36. package/dist/templates/index.js +116 -9
  37. package/dist/toolbar/bpmn-senior-button.js +8 -2
  38. package/dist/toolbar/config.d.ts +27 -2
  39. package/dist/toolbar/config.js +86 -2
  40. package/dist/toolbar/icons.d.ts +67 -0
  41. package/dist/toolbar/icons.js +141 -0
  42. package/dist/toolbar/senior-tool.js +1 -0
  43. package/dist/translations.d.ts +3 -1
  44. package/dist/translations.js +8 -3
  45. package/dist/view.d.ts +6 -2
  46. package/dist/view.js +68 -5
  47. package/package.json +2 -2
package/dist/consts.d.ts CHANGED
@@ -17,25 +17,179 @@ export declare const NODE_FILL = "#ffffff";
17
17
  export declare const START_WIDTH = 2;
18
18
  export declare const END_WIDTH = 4;
19
19
  export declare const NODE_STROKE_WIDTH = 2;
20
+ /**
21
+ * The call activity's border, which the spec draws THICK — it is the one way to
22
+ * tell it from the sub-process, since both carry the same `+` marker. Same
23
+ * weight as the end-event ring, and for the same reason: this is the heaviest
24
+ * line the notation uses, and it is spent on "this one stands for a whole
25
+ * process defined somewhere else".
26
+ */
27
+ export declare const CALL_ACTIVITY_WIDTH = 4;
20
28
  /** Task corner radius (absolute px — a lightly rounded rectangle). */
21
29
  export declare const TASK_RADIUS = 10;
30
+ /**
31
+ * The group's corner radius — twice a task's, because it is drawn at three
32
+ * times the size and a 10-unit corner on a 300-unit box reads as a square one.
33
+ */
34
+ export declare const GROUP_RADIUS = 20;
35
+ /**
36
+ * The group's dashed border.
37
+ *
38
+ * Grey and not the flow objects' near-black: a group is furniture drawn AROUND
39
+ * the work, and it is the one artefact on the canvas guaranteed to overlap
40
+ * several others. At the neutral stroke it out-shouts everything it encloses,
41
+ * which is the exact opposite of what a lasso is for. Every tool that draws
42
+ * BPMN makes the same call; the spec prescribes the dash and says nothing about
43
+ * the colour.
44
+ */
45
+ export declare const GROUP_STROKE = "#8e8d91";
22
46
  /** Inner-text font for the task label. */
23
47
  export declare const INNER_FONT_SIZE = 18;
24
- /** Default node sizes (model units) per kind. */
48
+ /**
49
+ * Default node sizes (model units) per kind.
50
+ *
51
+ * Three sizes carry the whole scale: the 56-unit event, the 120×72 task and the
52
+ * 72-unit gateway. Everything the descriptive profile adds takes one of them —
53
+ * a message start is a start event, a user task is a task — except the three
54
+ * data/artifact shapes, which have no sibling to inherit from:
55
+ *
56
+ * - `dataObject` is a PORTRAIT page (3:4), 64 tall so it stands beside a
57
+ * 56-unit event without looking like a shrunken task;
58
+ * - `dataStore` is the event's own diameter, which is what a cylinder needs to
59
+ * read as one rather than as a squashed ellipse;
60
+ * - `textAnnotation` is wider than a task and shorter — it holds a sentence,
61
+ * not a verb phrase.
62
+ *
63
+ * These three are ~1.2–1.4× bpmn.io's normative pixel sizes, which is the ratio
64
+ * this pack's event and task already sit at against the same reference.
65
+ *
66
+ * `group` is on no scale at all: it is a LASSO, so it has to be born big enough
67
+ * to have something in it. 300×200 holds two tasks and the arrow between them,
68
+ * which is the smallest thing anybody draws a group around.
69
+ */
25
70
  export declare const NODE_SIZE: Record<BpmnNodeKind, {
26
71
  w: number;
27
72
  h: number;
28
73
  }>;
29
- /** Default inner text per kind (only the task carries a label). */
74
+ /**
75
+ * Default inner text per kind.
76
+ *
77
+ * The activities carry one, because a rectangle with nothing written in it says
78
+ * nothing at all. Events and gateways do not: their meaning is the glyph, and
79
+ * BPMN puts whatever name they have OUTSIDE the symbol.
80
+ *
81
+ * `dataObject` and `dataStore` are empty for the same reason plus one of our
82
+ * own: the spec puts their name under the shape, the native inner text can only
83
+ * go inside it, and inside is where the folded page and the cylinder already
84
+ * are. The user can still type — the text simply overflows, which is the
85
+ * honest failure rather than a label painted over the glyph.
86
+ */
30
87
  export declare const NODE_LABEL: Record<BpmnNodeKind, string>;
31
- /** Pool (background container) defaults. */
88
+ /**
89
+ * Pool (background container) defaults — read by the `BPMN_POOL_BACKGROUND`
90
+ * declaration (`background.ts`), which is the only thing that draws a pool.
91
+ */
32
92
  export declare const POOL_BAND_WIDTH = 28;
33
93
  export declare const POOL_FRAME_COLOR = "#262626";
94
+ /**
95
+ * The card. The same white every framework background paints — it is what
96
+ * `DEFAULT_BACKGROUND_SURFACE` gives a declaration that names no fill, and what
97
+ * the Wardley map, the Core Domain Chart and the Context Map board all declare.
98
+ */
99
+ export declare const POOL_CARD_FILL = "#ffffff";
34
100
  export declare const POOL_BAND_FILL = "#f4f4f5";
35
101
  export declare const POOL_FRAME_WIDTH = 1.5;
102
+ export declare const POOL_CORNER_RADIUS = 6;
36
103
  export declare const POOL_NAME_FONT_SIZE = 15;
37
104
  export declare const POOL_NAME_COLOR = "#262626";
38
105
  export declare const POOL_FONT_FAMILY = "Inter, sans-serif";
106
+ /**
107
+ * Lane (couloir) name size — two units under the participant's own.
108
+ *
109
+ * The pool names WHO does the work and the lane names which part of them does
110
+ * it: a subdivision reads as a subdivision when its label is quieter than the
111
+ * one it sits under. Two units is the smallest difference that survives being
112
+ * zoomed out, which is the size the distinction has to hold at.
113
+ */
114
+ export declare const POOL_LANE_NAME_FONT_SIZE = 13;
115
+ /**
116
+ * Width of a lane's own title band, in model units — the strip immediately
117
+ * inside the participant band, with the lane name turned on its side.
118
+ *
119
+ * Four units narrower than {@link POOL_BAND_WIDTH}, and for the same reason the
120
+ * font is two points smaller: the two strips sit side by side, so the
121
+ * subordinate one has to say so. Identical widths read as a single 56-unit
122
+ * gutter rather than as a participant containing lanes, which is exactly the
123
+ * relationship the picture has to carry.
124
+ *
125
+ * NO fill, divider only — what bpmn.io, Camunda and Visio all draw. A second
126
+ * grey strip beside the pool's own would double the furniture and leave the
127
+ * flow area looking inset by two margins.
128
+ */
129
+ export declare const POOL_LANE_BAND_WIDTH = 24;
130
+ /**
131
+ * How close to an internal lane boundary a pointer has to be, in MODEL units,
132
+ * for the gesture to be a separator drag rather than a click on the pool.
133
+ *
134
+ * Symmetric, so the zone is 12 units wide. Model units and not view pixels on
135
+ * purpose: the grab zone then scales with the drawing, exactly like the lane it
136
+ * belongs to, and a pool zoomed out to a thumbnail does not become a strip of
137
+ * overlapping hit zones with no lane left between them.
138
+ */
139
+ export declare const POOL_LANE_GRAB = 6;
140
+ /**
141
+ * The smallest a lane may be dragged to, in model units of a pool at its
142
+ * REFERENCE height ({@link POOL_REF_HEIGHT}).
143
+ *
144
+ * A floor and not a minimum height: sizes are weights, so this is converted to
145
+ * a weight against the pool's current total before it is applied. 24 units is
146
+ * about one line of a lane name plus its inset — below that the band cannot
147
+ * show what it is, and a lane nothing can be put in and nothing can be read off
148
+ * is one the user did not mean to make.
149
+ */
150
+ export declare const POOL_LANE_MIN_HEIGHT = 24;
151
+ /**
152
+ * The size a fresh pool is created at. Unlike a map, a pool is NOT grown to
153
+ * cover the ones already on the board: pools sit side by side, one per
154
+ * participant, and a second lane that matched the first one's height would
155
+ * claim room the process has not asked for.
156
+ *
157
+ * `actions.ts` and the templates still write these two numbers themselves; the
158
+ * declaration names them so there is somewhere for them to converge.
159
+ */
160
+ export declare const POOL_REF_WIDTH = 560;
161
+ export declare const POOL_REF_HEIGHT = 200;
39
162
  /** Sequence-flow connector preset. */
40
163
  export declare const SEQUENCE_STROKE = "#262626";
41
164
  export declare const SEQUENCE_WIDTH = 2;
165
+ /**
166
+ * Message-flow connector preset — the dashed line that crosses between pools.
167
+ *
168
+ * Same ink and same weight as the sequence flow: what tells the two apart is
169
+ * the DASH and the endpoints (an open circle where the message leaves, an open
170
+ * arrowhead where it lands), which is exactly the distinction BPMN draws.
171
+ */
172
+ export declare const MESSAGE_STROKE = "#262626";
173
+ export declare const MESSAGE_WIDTH = 2;
174
+ /**
175
+ * Association connector preset — the line that ties a note or a data object to
176
+ * the work it is about.
177
+ *
178
+ * ## Dashed, not dotted (simplification, and why it is survivable)
179
+ *
180
+ * BPMN draws a message flow DASHED and an association DOTTED. This editor's
181
+ * `StrokeStyle` has three members — `Solid`, `Dash`, `None` — and the dash
182
+ * pattern is a fixed `[12, 12]` no framework can tighten, so there is no dotted
183
+ * stroke to ask for. Drawing it thinner instead is not available either: a
184
+ * connector's `strokeWidth` is a closed enum (`2 | 4 | … | 12`) the props store
185
+ * validates, and 2 is already the floor.
186
+ *
187
+ * So the association ships with the message flow's own line, and carries the
188
+ * distinction entirely on its ENDPOINTS: a message flow always shows a circle
189
+ * where it leaves and an arrowhead where it lands, an association shows neither
190
+ * at either end. That is a difference the eye reads at a glance and, unlike the
191
+ * dot pattern, it is one the notation itself means — an association has no
192
+ * direction to point in. A rule reads the `role`, which is exact either way.
193
+ */
194
+ export declare const ASSOCIATION_STROKE = "#262626";
195
+ export declare const ASSOCIATION_WIDTH = 2;
package/dist/consts.js CHANGED
@@ -16,32 +16,221 @@ export const NODE_FILL = '#ffffff';
16
16
  export const START_WIDTH = 2;
17
17
  export const END_WIDTH = 4;
18
18
  export const NODE_STROKE_WIDTH = 2;
19
+ /**
20
+ * The call activity's border, which the spec draws THICK — it is the one way to
21
+ * tell it from the sub-process, since both carry the same `+` marker. Same
22
+ * weight as the end-event ring, and for the same reason: this is the heaviest
23
+ * line the notation uses, and it is spent on "this one stands for a whole
24
+ * process defined somewhere else".
25
+ */
26
+ export const CALL_ACTIVITY_WIDTH = END_WIDTH;
19
27
  /** Task corner radius (absolute px — a lightly rounded rectangle). */
20
28
  export const TASK_RADIUS = 10;
29
+ /**
30
+ * The group's corner radius — twice a task's, because it is drawn at three
31
+ * times the size and a 10-unit corner on a 300-unit box reads as a square one.
32
+ */
33
+ export const GROUP_RADIUS = 20;
34
+ /**
35
+ * The group's dashed border.
36
+ *
37
+ * Grey and not the flow objects' near-black: a group is furniture drawn AROUND
38
+ * the work, and it is the one artefact on the canvas guaranteed to overlap
39
+ * several others. At the neutral stroke it out-shouts everything it encloses,
40
+ * which is the exact opposite of what a lasso is for. Every tool that draws
41
+ * BPMN makes the same call; the spec prescribes the dash and says nothing about
42
+ * the colour.
43
+ */
44
+ export const GROUP_STROKE = '#8e8d91';
21
45
  /** Inner-text font for the task label. */
22
46
  export const INNER_FONT_SIZE = 18;
23
- /** Default node sizes (model units) per kind. */
47
+ /**
48
+ * Default node sizes (model units) per kind.
49
+ *
50
+ * Three sizes carry the whole scale: the 56-unit event, the 120×72 task and the
51
+ * 72-unit gateway. Everything the descriptive profile adds takes one of them —
52
+ * a message start is a start event, a user task is a task — except the three
53
+ * data/artifact shapes, which have no sibling to inherit from:
54
+ *
55
+ * - `dataObject` is a PORTRAIT page (3:4), 64 tall so it stands beside a
56
+ * 56-unit event without looking like a shrunken task;
57
+ * - `dataStore` is the event's own diameter, which is what a cylinder needs to
58
+ * read as one rather than as a squashed ellipse;
59
+ * - `textAnnotation` is wider than a task and shorter — it holds a sentence,
60
+ * not a verb phrase.
61
+ *
62
+ * These three are ~1.2–1.4× bpmn.io's normative pixel sizes, which is the ratio
63
+ * this pack's event and task already sit at against the same reference.
64
+ *
65
+ * `group` is on no scale at all: it is a LASSO, so it has to be born big enough
66
+ * to have something in it. 300×200 holds two tasks and the arrow between them,
67
+ * which is the smallest thing anybody draws a group around.
68
+ */
24
69
  export const NODE_SIZE = {
25
70
  startEvent: { w: 56, h: 56 },
71
+ startEventMessage: { w: 56, h: 56 },
72
+ startEventTimer: { w: 56, h: 56 },
26
73
  endEvent: { w: 56, h: 56 },
74
+ endEventMessage: { w: 56, h: 56 },
75
+ endEventTerminate: { w: 56, h: 56 },
27
76
  task: { w: 120, h: 72 },
77
+ taskUser: { w: 120, h: 72 },
78
+ taskService: { w: 120, h: 72 },
79
+ subProcess: { w: 120, h: 72 },
80
+ callActivity: { w: 120, h: 72 },
28
81
  gatewayExclusive: { w: 72, h: 72 },
82
+ gatewayParallel: { w: 72, h: 72 },
83
+ dataObject: { w: 48, h: 64 },
84
+ dataStore: { w: 56, h: 56 },
85
+ textAnnotation: { w: 140, h: 48 },
86
+ group: { w: 300, h: 200 },
29
87
  };
30
- /** Default inner text per kind (only the task carries a label). */
88
+ /**
89
+ * Default inner text per kind.
90
+ *
91
+ * The activities carry one, because a rectangle with nothing written in it says
92
+ * nothing at all. Events and gateways do not: their meaning is the glyph, and
93
+ * BPMN puts whatever name they have OUTSIDE the symbol.
94
+ *
95
+ * `dataObject` and `dataStore` are empty for the same reason plus one of our
96
+ * own: the spec puts their name under the shape, the native inner text can only
97
+ * go inside it, and inside is where the folded page and the cylinder already
98
+ * are. The user can still type — the text simply overflows, which is the
99
+ * honest failure rather than a label painted over the glyph.
100
+ */
31
101
  export const NODE_LABEL = {
32
102
  startEvent: '',
103
+ startEventMessage: '',
104
+ startEventTimer: '',
33
105
  endEvent: '',
106
+ endEventMessage: '',
107
+ endEventTerminate: '',
34
108
  task: 'Task',
109
+ taskUser: 'User task',
110
+ taskService: 'Service task',
111
+ subProcess: 'Sub-process',
112
+ callActivity: 'Call activity',
35
113
  gatewayExclusive: '',
114
+ gatewayParallel: '',
115
+ dataObject: '',
116
+ dataStore: '',
117
+ // The one artefact that IS its text.
118
+ textAnnotation: 'Annotation',
119
+ // The group's label is a CategoryValue in the spec. A plain editable string
120
+ // is the v1 of that: it names the lasso, and it is drawn top-left rather than
121
+ // centred so it does not float over whatever the group encloses.
122
+ group: 'Group',
36
123
  };
37
- /** Pool (background container) defaults. */
124
+ /**
125
+ * Pool (background container) defaults — read by the `BPMN_POOL_BACKGROUND`
126
+ * declaration (`background.ts`), which is the only thing that draws a pool.
127
+ */
38
128
  export const POOL_BAND_WIDTH = 28;
39
129
  export const POOL_FRAME_COLOR = '#262626';
130
+ /**
131
+ * The card. The same white every framework background paints — it is what
132
+ * `DEFAULT_BACKGROUND_SURFACE` gives a declaration that names no fill, and what
133
+ * the Wardley map, the Core Domain Chart and the Context Map board all declare.
134
+ */
135
+ export const POOL_CARD_FILL = '#ffffff';
40
136
  export const POOL_BAND_FILL = '#f4f4f5';
41
137
  export const POOL_FRAME_WIDTH = 1.5;
138
+ export const POOL_CORNER_RADIUS = 6;
42
139
  export const POOL_NAME_FONT_SIZE = 15;
43
140
  export const POOL_NAME_COLOR = '#262626';
44
141
  export const POOL_FONT_FAMILY = 'Inter, sans-serif';
142
+ /**
143
+ * Lane (couloir) name size — two units under the participant's own.
144
+ *
145
+ * The pool names WHO does the work and the lane names which part of them does
146
+ * it: a subdivision reads as a subdivision when its label is quieter than the
147
+ * one it sits under. Two units is the smallest difference that survives being
148
+ * zoomed out, which is the size the distinction has to hold at.
149
+ */
150
+ export const POOL_LANE_NAME_FONT_SIZE = 13;
151
+ /**
152
+ * Width of a lane's own title band, in model units — the strip immediately
153
+ * inside the participant band, with the lane name turned on its side.
154
+ *
155
+ * Four units narrower than {@link POOL_BAND_WIDTH}, and for the same reason the
156
+ * font is two points smaller: the two strips sit side by side, so the
157
+ * subordinate one has to say so. Identical widths read as a single 56-unit
158
+ * gutter rather than as a participant containing lanes, which is exactly the
159
+ * relationship the picture has to carry.
160
+ *
161
+ * NO fill, divider only — what bpmn.io, Camunda and Visio all draw. A second
162
+ * grey strip beside the pool's own would double the furniture and leave the
163
+ * flow area looking inset by two margins.
164
+ */
165
+ export const POOL_LANE_BAND_WIDTH = 24;
166
+ /**
167
+ * How close to an internal lane boundary a pointer has to be, in MODEL units,
168
+ * for the gesture to be a separator drag rather than a click on the pool.
169
+ *
170
+ * Symmetric, so the zone is 12 units wide. Model units and not view pixels on
171
+ * purpose: the grab zone then scales with the drawing, exactly like the lane it
172
+ * belongs to, and a pool zoomed out to a thumbnail does not become a strip of
173
+ * overlapping hit zones with no lane left between them.
174
+ */
175
+ export const POOL_LANE_GRAB = 6;
176
+ /**
177
+ * The smallest a lane may be dragged to, in model units of a pool at its
178
+ * REFERENCE height ({@link POOL_REF_HEIGHT}).
179
+ *
180
+ * A floor and not a minimum height: sizes are weights, so this is converted to
181
+ * a weight against the pool's current total before it is applied. 24 units is
182
+ * about one line of a lane name plus its inset — below that the band cannot
183
+ * show what it is, and a lane nothing can be put in and nothing can be read off
184
+ * is one the user did not mean to make.
185
+ */
186
+ export const POOL_LANE_MIN_HEIGHT = 24;
187
+ // The lane-name hit box used to be a corner box declared here
188
+ // (`POOL_LANE_NAME_HIT_WIDTH` / `_HEIGHT`). Since the PO's recette moved the
189
+ // name into a title band, the target IS that band: `element-view.ts` reads it
190
+ // from `backgroundInstanceZoneBand`, so there is nothing left to declare and
191
+ // nothing left that can drift away from what is painted.
192
+ /**
193
+ * The size a fresh pool is created at. Unlike a map, a pool is NOT grown to
194
+ * cover the ones already on the board: pools sit side by side, one per
195
+ * participant, and a second lane that matched the first one's height would
196
+ * claim room the process has not asked for.
197
+ *
198
+ * `actions.ts` and the templates still write these two numbers themselves; the
199
+ * declaration names them so there is somewhere for them to converge.
200
+ */
201
+ export const POOL_REF_WIDTH = 560;
202
+ export const POOL_REF_HEIGHT = 200;
45
203
  /** Sequence-flow connector preset. */
46
204
  export const SEQUENCE_STROKE = '#262626';
47
205
  export const SEQUENCE_WIDTH = 2;
206
+ /**
207
+ * Message-flow connector preset — the dashed line that crosses between pools.
208
+ *
209
+ * Same ink and same weight as the sequence flow: what tells the two apart is
210
+ * the DASH and the endpoints (an open circle where the message leaves, an open
211
+ * arrowhead where it lands), which is exactly the distinction BPMN draws.
212
+ */
213
+ export const MESSAGE_STROKE = '#262626';
214
+ export const MESSAGE_WIDTH = 2;
215
+ /**
216
+ * Association connector preset — the line that ties a note or a data object to
217
+ * the work it is about.
218
+ *
219
+ * ## Dashed, not dotted (simplification, and why it is survivable)
220
+ *
221
+ * BPMN draws a message flow DASHED and an association DOTTED. This editor's
222
+ * `StrokeStyle` has three members — `Solid`, `Dash`, `None` — and the dash
223
+ * pattern is a fixed `[12, 12]` no framework can tighten, so there is no dotted
224
+ * stroke to ask for. Drawing it thinner instead is not available either: a
225
+ * connector's `strokeWidth` is a closed enum (`2 | 4 | … | 12`) the props store
226
+ * validates, and 2 is already the floor.
227
+ *
228
+ * So the association ships with the message flow's own line, and carries the
229
+ * distinction entirely on its ENDPOINTS: a message flow always shows a circle
230
+ * where it leaves and an arrowhead where it lands, an association shows neither
231
+ * at either end. That is a difference the eye reads at a glance and, unlike the
232
+ * dot pattern, it is one the notation itself means — an association has no
233
+ * direction to point in. A rule reads the `role`, which is exact either way.
234
+ */
235
+ export const ASSOCIATION_STROKE = '#262626';
236
+ export const ASSOCIATION_WIDTH = 2;
@@ -1,10 +1,16 @@
1
1
  import { type ElementRenderer } from '@formicoidea/labre-core/blocks/surface';
2
2
  import type { BpmnPoolElementModel } from '@formicoidea/labre-core/model';
3
3
  /**
4
- * Canvas renderer for a BPMN pool: a rounded-rect frame with a vertical name
5
- * band on the left (the participant name is drawn rotated, as in the spec).
6
- * Drawn directly in element space; the band width and font are fixed so they
7
- * stay legible at any pool size. Mirrors the other framework backgrounds.
4
+ * Canvas renderer for the BPMN pool.
5
+ *
6
+ * There is no BPMN drawing code any more: the pool is an INSTANTIATION of the
7
+ * framework-background primitive, configured by the `BPMN_POOL_BACKGROUND`
8
+ * declaration. What used to be ninety lines of hand-traced rounded rectangle,
9
+ * filled band and rotated name is now a declaration any other framework can
10
+ * write for itself.
11
+ *
12
+ * Exported as a function as well as an extension because the fidelity suite
13
+ * drives it directly with a canvas stub.
8
14
  */
9
15
  export declare const bpmnPool: ElementRenderer<BpmnPoolElementModel>;
10
16
  export declare const BpmnPoolRendererExtension: import("@formicoidea/labre-core/store").ExtensionType & {
@@ -1,57 +1,16 @@
1
- import { ElementRendererExtension, } from '@formicoidea/labre-core/blocks/surface';
2
- import { POOL_BAND_FILL, POOL_BAND_WIDTH, POOL_FONT_FAMILY, POOL_FRAME_COLOR, POOL_FRAME_WIDTH, POOL_NAME_COLOR, POOL_NAME_FONT_SIZE, } from './consts.js';
3
- /** Trace a rounded-rectangle path (no dependency on ctx.roundRect). */
4
- function roundedRectPath(ctx, x, y, w, h, r) {
5
- const rr = Math.min(r, w / 2, h / 2);
6
- ctx.beginPath();
7
- ctx.moveTo(x + rr, y);
8
- ctx.lineTo(x + w - rr, y);
9
- ctx.arcTo(x + w, y, x + w, y + rr, rr);
10
- ctx.lineTo(x + w, y + h - rr);
11
- ctx.arcTo(x + w, y + h, x + w - rr, y + h, rr);
12
- ctx.lineTo(x + rr, y + h);
13
- ctx.arcTo(x, y + h, x, y + h - rr, rr);
14
- ctx.lineTo(x, y + rr);
15
- ctx.arcTo(x, y, x + rr, y, rr);
16
- ctx.closePath();
17
- }
1
+ import { createFrameworkBackgroundRenderer, ElementRendererExtension, } from '@formicoidea/labre-core/blocks/surface';
2
+ import { BPMN_POOL_BACKGROUND } from './background.js';
18
3
  /**
19
- * Canvas renderer for a BPMN pool: a rounded-rect frame with a vertical name
20
- * band on the left (the participant name is drawn rotated, as in the spec).
21
- * Drawn directly in element space; the band width and font are fixed so they
22
- * stay legible at any pool size. Mirrors the other framework backgrounds.
4
+ * Canvas renderer for the BPMN pool.
5
+ *
6
+ * There is no BPMN drawing code any more: the pool is an INSTANTIATION of the
7
+ * framework-background primitive, configured by the `BPMN_POOL_BACKGROUND`
8
+ * declaration. What used to be ninety lines of hand-traced rounded rectangle,
9
+ * filled band and rotated name is now a declaration any other framework can
10
+ * write for itself.
11
+ *
12
+ * Exported as a function as well as an extension because the fidelity suite
13
+ * drives it directly with a canvas stub.
23
14
  */
24
- export const bpmnPool = (model, ctx, matrix) => {
25
- const [, , w, h] = model.deserializedXYWH;
26
- const cx = w / 2;
27
- const cy = h / 2;
28
- ctx.setTransform(matrix.translateSelf(cx, cy).rotateSelf(model.rotate).translateSelf(-cx, -cy));
29
- const band = Math.min(POOL_BAND_WIDTH, w);
30
- const inset = POOL_FRAME_WIDTH / 2;
31
- // Name band (left), filled.
32
- ctx.fillStyle = POOL_BAND_FILL;
33
- ctx.fillRect(0, 0, band, h);
34
- // Frame + band divider.
35
- ctx.strokeStyle = POOL_FRAME_COLOR;
36
- ctx.lineWidth = POOL_FRAME_WIDTH;
37
- ctx.lineJoin = 'round';
38
- roundedRectPath(ctx, inset, inset, w - POOL_FRAME_WIDTH, h - POOL_FRAME_WIDTH, 6);
39
- ctx.stroke();
40
- ctx.beginPath();
41
- ctx.moveTo(band, 0);
42
- ctx.lineTo(band, h);
43
- ctx.stroke();
44
- // Participant name, rotated to read up the band (skip when empty / too narrow).
45
- if (model.name && band > 12) {
46
- ctx.save();
47
- ctx.translate(band / 2, h / 2);
48
- ctx.rotate(-Math.PI / 2);
49
- ctx.fillStyle = POOL_NAME_COLOR;
50
- ctx.font = `600 ${POOL_NAME_FONT_SIZE}px ${POOL_FONT_FAMILY}`;
51
- ctx.textAlign = 'center';
52
- ctx.textBaseline = 'middle';
53
- ctx.fillText(model.name, 0, 0);
54
- ctx.restore();
55
- }
56
- };
57
- export const BpmnPoolRendererExtension = ElementRendererExtension('bpmnPool', bpmnPool);
15
+ export const bpmnPool = createFrameworkBackgroundRenderer(BPMN_POOL_BACKGROUND);
16
+ export const BpmnPoolRendererExtension = ElementRendererExtension(BPMN_POOL_BACKGROUND.type, bpmnPool);
@@ -1,21 +1,113 @@
1
1
  import type { BpmnPoolElementModel } from '@formicoidea/labre-core/model';
2
2
  import { GfxElementModelView } from '@formicoidea/labre-core/std/gfx';
3
3
  /**
4
- * View for a BPMN pool. A double-click edits the participant name in place
5
- * (single field — the whole pool is the hit target). Mirrors the inline label
6
- * editor used by the EDGY / Wardley backgrounds.
4
+ * View for a BPMN pool. Three direct gestures live here:
5
+ *
6
+ * - **dblclick in the pool's own title band** — the left margin strip the
7
+ * participant name is written up — edits that name in place;
8
+ * - **dblclick in a lane's title band** edits THAT lane's name instead. A lane
9
+ * name is not in the declaration's hit-test walk (`backgroundLabelHits`,
10
+ * which Wardley uses): it is a function of the MODEL, not of the declaration,
11
+ * so the box comes from `backgroundInstanceZoneBand` — the very rectangle the
12
+ * renderer paints the name in, rather than a second set of metrics that would
13
+ * one day disagree with it;
14
+ * - **drag on an internal lane boundary** moves the separator, taking from one
15
+ * lane and giving to the other.
16
+ *
17
+ * Both renames are ZONED to their band (PO recette, 2026-08-26). The whole pool
18
+ * used to open the participant editor, which was right while a pool had one
19
+ * name; with a name per lane it would mean a double-click in the middle of the
20
+ * flow area renames the participant — neither of the two things the user could
21
+ * have meant, and the kind of write nobody notices until it is in a
22
+ * deliverable. A double-click on open canvas inside the pool now does nothing,
23
+ * and the `text` cursor over either band is what says where the names are.
24
+ *
25
+ * ## How the separator drag takes the gesture
26
+ *
27
+ * `GfxElementModelView.dispatch` reports a drag as handled whenever a handler
28
+ * is REGISTERED, without consulting what the handler returned, and the default
29
+ * tool stands down on that report. A permanently registered `dragstart` would
30
+ * therefore make a pool undraggable. So the drag handlers are ARMED — attached
31
+ * while the pointer is over a boundary of a selected pool, detached the moment
32
+ * it is not — and the pool moves normally everywhere else.
33
+ *
34
+ * Arming happens on `pointermove` AND on `pointerdown`, and neither is a hover
35
+ * requirement: a touch drag emits its first `pointermove` before the drag
36
+ * threshold is crossed (the move controller listens on the host, the drag
37
+ * controller on the document, so the host listener runs first), which is what
38
+ * makes the grab zone work with no hovering at all. The `ns-resize` cursor is a
39
+ * bonus for whoever has a mouse, never the affordance itself.
40
+ *
41
+ * ## The pool must be selected first
42
+ *
43
+ * Both the cursor and the grab are gated on the pool being selected. On an
44
+ * infinite canvas, dragging over an element means "move it"; silently turning a
45
+ * twelve-unit strip of an UNSELECTED pool into a resize handle would take that
46
+ * away from a user who never said they were working on this pool. One click
47
+ * first, and then the strip is live.
48
+ *
49
+ * ponytail: a ROTATED pool is not accounted for — the pointer is converted to
50
+ * element-local coordinates by subtraction, so every hit box here assumes an
51
+ * upright pool. Same reserve `backgroundAxisFacts` documents, for the same
52
+ * reason: nothing rotates a framework background today. Upgrade: rotate the
53
+ * local point by `-model.rotate` about the element centre, at the one function
54
+ * that has the element in hand (`_localPoint`), not a new declared field.
7
55
  */
8
56
  export declare class BpmnPoolView extends GfxElementModelView<BpmnPoolElementModel> {
9
57
  static type: string;
10
58
  private _nameEditor;
59
+ /** The boundary the pointer is over, and the handlers armed for it. */
60
+ private _armed;
61
+ /** Everything a separator drag needs, frozen at `dragstart`. */
62
+ private _drag;
11
63
  onCreated(): void;
12
64
  onDestroyed(): void;
65
+ /** Hand the cursor back on the way out; nothing here owns it for long. */
66
+ private _leave;
67
+ /** The pointer, in element-local model units. */
68
+ private _localPoint;
69
+ /**
70
+ * The boxes the gestures below aim at, all of them delegated to `pool-hit.ts`.
71
+ *
72
+ * That module is pure, so every answer here can be asserted without an
73
+ * editor, a viewport or a canvas; and it derives each box from
74
+ * `backgroundInstanceZones` / `backgroundInstanceZoneBand`, the same two
75
+ * functions the renderer paints from and the audit reports from. The view
76
+ * supplies the pointer and the zoom and nothing else.
77
+ */
78
+ private _bands;
79
+ private _boundaryAt;
80
+ /** Which name this point aims at, if any — lane strip first, see `pool-hit`. */
81
+ private _targetAt;
82
+ private get _editable();
83
+ /**
84
+ * One pass over the pointer, deciding both the cursor and whether a
85
+ * separator drag is armed.
86
+ *
87
+ * The order is the order the gestures win in. A separator sits INSIDE a lane
88
+ * title band at every lane boundary, so the two overlap and something has to
89
+ * give: the separator takes it, because it is a twelve-unit strip the user
90
+ * has to aim at deliberately, while the title band is the whole leading edge
91
+ * and has plenty left over. It is also already gated on the pool being
92
+ * selected, so on an unselected pool the band wins uncontested.
93
+ */
94
+ private _updateHover;
95
+ private _disarm;
96
+ private _onDragStart;
97
+ private _onDragMove;
98
+ private _onDragEnd;
99
+ /**
100
+ * A double-click renames whatever TITLE BAND it landed in, and nothing
101
+ * otherwise (PO recette, 2026-08-26).
102
+ *
103
+ * The whole pool used to open the participant editor. That was right while a
104
+ * pool had one name; now that every lane carries one it would mean a
105
+ * double-click in the middle of the flow area renames the participant — not
106
+ * one of the things the user could have meant, and the kind of write nobody
107
+ * notices until it is in a deliverable. A double-click on open canvas inside
108
+ * the pool now does nothing, which is the honest answer.
109
+ */
13
110
  private _onDblClick;
14
111
  private _openEditor;
15
112
  private _closeEditor;
16
113
  }
17
- /**
18
- * Resize gating: the resize handles are hidden unless `model.resizeEnabled` is
19
- * true (toggled from the toolbar). Moving / selecting stays available.
20
- */
21
- export declare const BpmnPoolInteraction: import("@formicoidea/labre-core/store").ExtensionType;