@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
@@ -1,12 +1,27 @@
1
1
  import { makeTemplateSnapshot, surfaceText, } from '@formicoidea/labre-core/gfx/template';
2
2
  import { ConnectorMode, FontFamily, PointStyle, ShapeStyle, StrokeStyle, } from '@formicoidea/labre-core/model';
3
- import { END_WIDTH, EVENT_END, EVENT_START, INNER_FONT_SIZE, NEUTRAL_STROKE, NODE_FILL, NODE_SIZE, NODE_STROKE_WIDTH, SEQUENCE_STROKE, SEQUENCE_WIDTH, START_WIDTH, TASK_RADIUS, } from '../consts.js';
4
- /** One BPMN flow-object node, as a surface-element JSON entry. */
3
+ import { END_WIDTH, EVENT_END, EVENT_START, INNER_FONT_SIZE, MESSAGE_STROKE, MESSAGE_WIDTH, NEUTRAL_STROKE, NODE_FILL, NODE_SIZE, NODE_STROKE_WIDTH, SEQUENCE_STROKE, SEQUENCE_WIDTH, START_WIDTH, TASK_RADIUS, } from '../consts.js';
4
+ import { BPMN_ROLE, BPMN_ROLE_OF_KIND } from '../roles.js';
5
+ /**
6
+ * One BPMN flow-object node, as a surface-element JSON entry.
7
+ *
8
+ * Every kind that {@link NodeKind} admits paints its own body natively, as an
9
+ * ellipse, a rounded rect or a diamond. The GLYPH-BODIED kinds (`dataObject`,
10
+ * `dataStore`, `textAnnotation`) do not: they are created unfilled and
11
+ * unstroked and the renderer draws their silhouette, so a card that spelled one
12
+ * out here would insert an invisible rectangle. `group` is out for a neighbouring
13
+ * reason — it is `hollow`, and the branches below all fill. When any of them
14
+ * earns a card, this helper reads `NODE_PRESETS` instead of branching.
15
+ */
5
16
  function node(kind, x, y, text) {
6
17
  const { w, h } = NODE_SIZE[kind];
7
18
  const base = {
8
19
  type: 'bpmnNode',
9
20
  kind,
21
+ // A template must produce the same typed artefacts as the toolbox, or a
22
+ // process started from a preset would read differently from a hand-drawn
23
+ // one.
24
+ role: BPMN_ROLE_OF_KIND[kind],
10
25
  filled: true,
11
26
  fillColor: NODE_FILL,
12
27
  shapeStyle: ShapeStyle.General,
@@ -14,11 +29,26 @@ function node(kind, x, y, text) {
14
29
  xywh: `[${x},${y},${w},${h}]`,
15
30
  };
16
31
  if (kind === 'startEvent')
17
- return { ...base, shapeType: 'ellipse', strokeColor: EVENT_START, strokeWidth: START_WIDTH };
32
+ return {
33
+ ...base,
34
+ shapeType: 'ellipse',
35
+ strokeColor: EVENT_START,
36
+ strokeWidth: START_WIDTH,
37
+ };
18
38
  if (kind === 'endEvent')
19
- return { ...base, shapeType: 'ellipse', strokeColor: EVENT_END, strokeWidth: END_WIDTH };
39
+ return {
40
+ ...base,
41
+ shapeType: 'ellipse',
42
+ strokeColor: EVENT_END,
43
+ strokeWidth: END_WIDTH,
44
+ };
20
45
  if (kind === 'gatewayExclusive')
21
- return { ...base, shapeType: 'diamond', strokeColor: NEUTRAL_STROKE, strokeWidth: NODE_STROKE_WIDTH };
46
+ return {
47
+ ...base,
48
+ shapeType: 'diamond',
49
+ strokeColor: NEUTRAL_STROKE,
50
+ strokeWidth: NODE_STROKE_WIDTH,
51
+ };
22
52
  return {
23
53
  ...base,
24
54
  shapeType: 'rect',
@@ -33,12 +63,21 @@ function node(kind, x, y, text) {
33
63
  };
34
64
  }
35
65
  function pool(x, y, w, h, name = 'Pool') {
36
- return { type: 'bpmnPool', name, xywh: `[${x},${y},${w},${h}]` };
66
+ return {
67
+ type: 'bpmnPool',
68
+ role: BPMN_ROLE.pool,
69
+ name,
70
+ xywh: `[${x},${y},${w},${h}]`,
71
+ };
37
72
  }
38
73
  /** A sequence-flow connector; ids are remapped on insert. */
39
74
  function seq(source, target) {
40
75
  return {
41
76
  type: 'connector',
77
+ // Both ends are BOUND, so this arrow relates two named things and its
78
+ // direction is a claim the template makes: source first, target next
79
+ // (`docs/adr/0010`).
80
+ role: BPMN_ROLE.sequenceFlow,
42
81
  mode: ConnectorMode.Orthogonal,
43
82
  stroke: SEQUENCE_STROKE,
44
83
  strokeWidth: SEQUENCE_WIDTH,
@@ -49,7 +88,40 @@ function seq(source, target) {
49
88
  target: { id: target, position: [0.5, 0.5] },
50
89
  };
51
90
  }
52
- /** A standalone (free) sequence-flow arrow for the prefab card. */
91
+ /**
92
+ * A message-flow connector; ids are remapped on insert.
93
+ *
94
+ * The same shape as {@link seq} and the same claim — both ends are BOUND, so
95
+ * the arrow relates two named things — but a different sentence: "sends a
96
+ * message to", from the participant that sends to the one that receives
97
+ * (`docs/adr/0010`). Its style is the one `activateBpmnMessageFlow` arms the
98
+ * connector tool with, so a message flow dropped from this card and one drawn
99
+ * by hand are indistinguishable in the document.
100
+ */
101
+ function msg(source, target) {
102
+ return {
103
+ type: 'connector',
104
+ role: BPMN_ROLE.messageFlow,
105
+ mode: ConnectorMode.Orthogonal,
106
+ stroke: MESSAGE_STROKE,
107
+ strokeWidth: MESSAGE_WIDTH,
108
+ strokeStyle: StrokeStyle.Dash,
109
+ frontEndpointStyle: PointStyle.Circle,
110
+ rearEndpointStyle: PointStyle.Arrow,
111
+ source: { id: source, position: [0.5, 0.5] },
112
+ target: { id: target, position: [0.5, 0.5] },
113
+ };
114
+ }
115
+ /**
116
+ * A standalone (free) sequence-flow arrow for the prefab card.
117
+ *
118
+ * NEUTRAL on purpose (`docs/adr/0010` § Compatibility, and the same call the
119
+ * Wardley "Link" swatch makes): this is a horizontal stroke bound to nothing —
120
+ * a sample of a STYLE, in a palette. A typed edge claims "this is followed by
121
+ * that", and a stroke attached to neither end has no this and no that to say it
122
+ * about. Drawing it with the sequence-flow tool, or dropping this one and then
123
+ * attaching both of its ends, is what makes it a statement.
124
+ */
53
125
  function freeSeq() {
54
126
  return {
55
127
  type: 'connector',
@@ -63,7 +135,9 @@ function freeSeq() {
63
135
  target: { position: [140, 0] },
64
136
  };
65
137
  }
66
- const single = (el) => ({ a: el });
138
+ const single = (el) => ({
139
+ a: el,
140
+ });
67
141
  const PREVIEW_ATTRS = 'width="100%" height="100%" viewBox="0 0 135 80" xmlns="http://www.w3.org/2000/svg"';
68
142
  const previews = {
69
143
  process: `<svg ${PREVIEW_ATTRS} fill="none"><circle cx="16" cy="40" r="8" stroke="#43a06b" stroke-width="2"/><rect x="34" y="31" width="26" height="18" rx="3" stroke="#262626" stroke-width="1.6"/><path d="M78 31 L88 40 L78 49 L68 40 Z" stroke="#262626" stroke-width="1.4"/><path d="M73 37 L83 43 M83 37 L73 43" stroke="#262626" stroke-width="1.2"/><circle cx="118" cy="40" r="8" stroke="#cf5648" stroke-width="3"/><path d="M24 40 H34 M60 40 H68 M88 40 H110" stroke="#262626" stroke-width="1.2"/></svg>`,
@@ -73,8 +147,17 @@ const previews = {
73
147
  gateway: `<svg ${PREVIEW_ATTRS} fill="none"><path d="M67 16 L92 40 L67 64 L42 40 Z" stroke="#262626" stroke-width="2.4" stroke-linejoin="round"/><path d="M58 31 L76 49 M76 31 L58 49" stroke="#262626" stroke-width="2.2" stroke-linecap="round"/></svg>`,
74
148
  sequence: `<svg ${PREVIEW_ATTRS} fill="none"><path d="M24 40 H96" stroke="#262626" stroke-width="2.4" stroke-linecap="round"/><path d="M94 33 L108 40 L94 47 Z" fill="#262626"/></svg>`,
75
149
  pool: `<svg ${PREVIEW_ATTRS} fill="none"><rect x="14" y="20" width="107" height="40" rx="3" stroke="#262626" stroke-width="2"/><path d="M30 20 V60" stroke="#262626" stroke-width="1.8"/><rect x="14" y="20" width="16" height="40" fill="#f4f4f5"/><path d="M30 20 V60" stroke="#262626" stroke-width="1.8"/></svg>`,
150
+ // Two participants stacked, and the dashed line between them is the whole
151
+ // point of the card: a message flow is the one arrow that crosses a pool.
152
+ // Its source terminator is a FILLED disc, matching what `renderCircle`
153
+ // actually paints rather than the hollow ring the norm asks for — a preview
154
+ // has one job, which is to look like what lands on the board.
155
+ messageExchange: `<svg ${PREVIEW_ATTRS} fill="none"><rect x="14" y="8" width="107" height="27" rx="3" stroke="#262626" stroke-width="1.6"/><rect x="14" y="8" width="11" height="27" fill="#f4f4f5"/><path d="M25 8 V35" stroke="#262626" stroke-width="1.4"/><rect x="14" y="45" width="107" height="27" rx="3" stroke="#262626" stroke-width="1.6"/><rect x="14" y="45" width="11" height="27" fill="#f4f4f5"/><path d="M25 45 V72" stroke="#262626" stroke-width="1.4"/><circle cx="36" cy="21.5" r="4.5" stroke="#43a06b" stroke-width="1.6"/><rect x="52" y="14" width="30" height="15" rx="3" stroke="#262626" stroke-width="1.6"/><rect x="52" y="51" width="30" height="15" rx="3" stroke="#262626" stroke-width="1.6"/><path d="M45 21.5 H52" stroke="#262626" stroke-width="1.4"/><circle cx="67" cy="31.5" r="2.2" fill="#262626"/><path d="M67 34 V48" stroke="#262626" stroke-width="1.4" stroke-dasharray="3 2.4"/><path d="M64 46 L67 50 L70 46" stroke="#262626" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>`,
76
156
  };
77
- /** The lean BPMN basics: a simple worked process + every prefab the menu makes. */
157
+ /**
158
+ * The BPMN basics: two worked scenes — a process end to end and a two-party
159
+ * message exchange — plus a prefab for each of the lean artefacts.
160
+ */
78
161
  function bpmnTemplates() {
79
162
  const process = {
80
163
  pool: pool(0, 0, 640, 200, 'Process'),
@@ -91,6 +174,29 @@ function bpmnTemplates() {
91
174
  c5: seq('task2', 'end'),
92
175
  c6: seq('task3', 'end'),
93
176
  };
177
+ /**
178
+ * Two participants, and the one arrow that is allowed to cross between them.
179
+ *
180
+ * The card exists because the message flow is the piece of BPMN people get
181
+ * wrong first: a sequence flow may never leave its pool, and the thing that
182
+ * does leave is a different statement with a different line. Laying the two
183
+ * pools out one above the other and drawing both flows once is the shortest
184
+ * way to show that — the solid arrow stays home, the dashed one crosses.
185
+ *
186
+ * Stacked vertically with a 40-unit gutter, so the message flow is a straight
187
+ * orthogonal drop between two tasks that already line up.
188
+ */
189
+ const messageExchange = {
190
+ customer: pool(0, 0, 640, 200, 'Customer'),
191
+ supplier: pool(0, 240, 640, 200, 'Supplier'),
192
+ start: node('startEvent', 40, 72),
193
+ ask: node('taskUser', 140, 64, 'Place order'),
194
+ answer: node('taskService', 140, 304, 'Confirm order'),
195
+ // Inside the first participant: what happens, and in what order.
196
+ inside: seq('start', 'ask'),
197
+ // Across the two: who told whom.
198
+ across: msg('ask', 'answer'),
199
+ };
94
200
  const t = (name, preview, elements) => ({
95
201
  name,
96
202
  type: 'template',
@@ -99,6 +205,7 @@ function bpmnTemplates() {
99
205
  });
100
206
  return [
101
207
  t('Simple process', previews.process, process),
208
+ t('Message exchange', previews.messageExchange, messageExchange),
102
209
  t('Start event', previews.startEvent, single(node('startEvent', 0, 0))),
103
210
  t('End event', previews.endEvent, single(node('endEvent', 0, 0))),
104
211
  t('Task', previews.task, single(node('task', 0, 0))),
@@ -1,5 +1,6 @@
1
1
  import { DefaultTool } from '@formicoidea/labre-core/blocks/surface';
2
2
  import { EmptyTool } from '@formicoidea/labre-core/gfx/pointer';
3
+ import { translateKey } from '@formicoidea/labre-core/shared/services';
3
4
  import { EdgelessToolbarToolMixin } from '@formicoidea/labre-core/widgets/edgeless-toolbar';
4
5
  import { SignalWatcher } from '@formicoidea/labre-core/global/lit';
5
6
  import { css, html, LitElement } from 'lit';
@@ -44,7 +45,10 @@ export class EdgelessBpmnSeniorButton extends EdgelessToolbarToolMixin(SignalWat
44
45
  translate: var(--active-x, 0) var(--active-y, 0);
45
46
  rotate: var(--active-r, -2deg);
46
47
  scale: var(--active-s, 1);
47
- transition: transform 0.3s ease, translate 0.3s ease, rotate 0.3s ease,
48
+ transition:
49
+ transform 0.3s ease,
50
+ translate 0.3s ease,
51
+ rotate 0.3s ease,
48
52
  scale 0.3s ease;
49
53
  }
50
54
  .bpmn-card svg {
@@ -71,7 +75,9 @@ export class EdgelessBpmnSeniorButton extends EdgelessToolbarToolMixin(SignalWat
71
75
  render() {
72
76
  return html `<edgeless-toolbar-button
73
77
  class="bpmn-button"
74
- .tooltip=${this.popper ? '' : 'BPMN'}
78
+ .tooltip=${this.popper
79
+ ? ''
80
+ : translateKey(this.edgeless.std, 'com.labre.framework.bpmn', 'BPMN')}
75
81
  .tooltipOffset=${4}
76
82
  .active=${!!this.popper}
77
83
  @click=${this._toggleMenu}
@@ -1,13 +1,39 @@
1
- import { type ToolbarContext } from '@formicoidea/labre-core/shared/services';
1
+ import { ActionPlacement, type ChromeWording, type ToolbarContext } from '@formicoidea/labre-core/shared/services';
2
2
  import { type TemplateResult } from 'lit';
3
3
  export declare const bpmnPoolToolbarConfig: {
4
4
  readonly actions: [{
5
5
  id: string;
6
6
  tooltip: string;
7
+ tooltipWording: ChromeWording | undefined;
7
8
  icon: TemplateResult;
8
9
  active(ctx: ToolbarContext): boolean;
9
10
  run(ctx: ToolbarContext): void;
11
+ }, {
12
+ id: string;
13
+ when: (ctx: ToolbarContext) => boolean;
14
+ generate: (ctx: ToolbarContext) => {
15
+ icon: TemplateResult;
16
+ tooltip: string;
17
+ run: (runCtx: ToolbarContext) => void;
18
+ };
19
+ }, {
20
+ id: string;
21
+ when: (ctx: ToolbarContext) => boolean;
22
+ generate: (ctx: ToolbarContext) => {
23
+ icon: TemplateResult;
24
+ tooltip: string;
25
+ run: (runCtx: ToolbarContext) => void;
26
+ };
27
+ }, {
28
+ id: string;
29
+ placement: ActionPlacement;
30
+ when: (ctx: ToolbarContext) => boolean;
31
+ generate: (ctx: ToolbarContext) => {
32
+ icon: TemplateResult;
33
+ label: string;
34
+ run: (runCtx: ToolbarContext) => void;
35
+ };
10
36
  }];
11
37
  readonly when: (ctx: ToolbarContext) => boolean;
12
38
  };
13
- export declare const bpmnPoolToolbarExtension: import("@formicoidea/labre-core/store").ExtensionType;
39
+ export declare const bpmnPoolToolbarExtension: import("@formicoidea/labre-core/store/index.js").ExtensionType;
@@ -1,8 +1,9 @@
1
1
  import { EdgelessCRUDIdentifier } from '@formicoidea/labre-core/blocks/surface';
2
2
  import { BpmnPoolElementModel } from '@formicoidea/labre-core/model';
3
- import { ToolbarModuleExtension, } from '@formicoidea/labre-core/shared/services';
4
- import { BlockFlavourIdentifier } from '@formicoidea/labre-core/std';
3
+ import { ActionPlacement, BOARD_RESIZE_TOGGLE, ToolbarModuleExtension, translateKey, } from '@formicoidea/labre-core/shared/services';
4
+ import { BlockFlavourIdentifier, getRegisteredCommands, runCommand, } from '@formicoidea/labre-core/std';
5
5
  import { html } from 'lit';
6
+ import { bpmnExportXmlIcon, bpmnLaneAddIcon, bpmnLaneRemoveIcon, } from './icons.js';
6
7
  const ResizeIcon = html `<svg
7
8
  width="24"
8
9
  height="24"
@@ -23,7 +24,12 @@ const ResizeIcon = html `<svg
23
24
  function booleanToggle(id, tooltip, icon, prop) {
24
25
  return {
25
26
  id,
26
- tooltip,
27
+ tooltip: typeof tooltip === 'string' ? tooltip : tooltip[1],
28
+ // The declared wording, when the caller gave one instead of a literal:
29
+ // `combine` resolves it against the host's catalogue and writes it over
30
+ // the English default above, so a playground with no catalogue reads
31
+ // exactly what it read before (#183).
32
+ tooltipWording: typeof tooltip === 'string' ? undefined : tooltip,
27
33
  icon,
28
34
  active(ctx) {
29
35
  const models = ctx.getSurfaceModelsByType(BpmnPoolElementModel);
@@ -42,9 +48,92 @@ function booleanToggle(id, tooltip, icon, prop) {
42
48
  },
43
49
  };
44
50
  }
51
+ /**
52
+ * A toolbar entry that INVOKES a registered command instead of restating what
53
+ * it does — the shape `docs/adr/0010` M3 introduced for the typed-edge
54
+ * inversion, and the reason a lane gesture has one behaviour, one availability
55
+ * rule and one telemetry emission whether it is reached from here, from the
56
+ * palette, from Settings › Shortcuts or from the agent.
57
+ *
58
+ * `generate` rather than a static entry because the i18n seam needs `std`:
59
+ * `translateKey` is what reaches the host's catalogue, and a hard-coded English
60
+ * tooltip would be the one wording a host could not override.
61
+ */
62
+ function commandAction(id, commandId, labelKey, labelFallback, icon) {
63
+ return {
64
+ id,
65
+ when: (ctx) => {
66
+ const command = findCommand(ctx, commandId);
67
+ return command !== undefined && (command.when?.(ctx.std) ?? true);
68
+ },
69
+ generate: (ctx) => {
70
+ const label = translateKey(ctx.std, labelKey, labelFallback);
71
+ return {
72
+ icon,
73
+ tooltip: label,
74
+ run: (runCtx) => {
75
+ const command = findCommand(runCtx, commandId);
76
+ if (!command)
77
+ return;
78
+ runCommand(runCtx.std, command, {
79
+ surface: 'contextual-toolbar',
80
+ source: 'toolbar:general',
81
+ });
82
+ },
83
+ };
84
+ },
85
+ };
86
+ }
87
+ /**
88
+ * The same thing, for the "⋮" menu instead of the row.
89
+ *
90
+ * Two differences, and the widget imposes both: a menu line is drawn from
91
+ * `label` (a tooltip on a line that is already words would be a second copy of
92
+ * them), and `placement: ActionPlacement.More` is what partitions it out of the
93
+ * row in the first place — `renderToolbar` splits on exactly that flag, and the
94
+ * entries it collects come from every module contributing to the element,
95
+ * so a framework can add to the "⋮" without owning it.
96
+ */
97
+ function commandMoreAction(id, commandId, labelKey, labelFallback, icon) {
98
+ return {
99
+ id,
100
+ placement: ActionPlacement.More,
101
+ when: (ctx) => {
102
+ const command = findCommand(ctx, commandId);
103
+ return command !== undefined && (command.when?.(ctx.std) ?? true);
104
+ },
105
+ generate: (ctx) => ({
106
+ icon,
107
+ label: translateKey(ctx.std, labelKey, labelFallback),
108
+ run: (runCtx) => {
109
+ const command = findCommand(runCtx, commandId);
110
+ if (!command)
111
+ return;
112
+ // The same `source` the row's own entries report: the "⋮" is a
113
+ // degradation of the row, not a surface of its own, and the
114
+ // `ElementCreationSource` union deliberately names places rather than
115
+ // widths (`docs/adr/0008`).
116
+ runCommand(runCtx.std, command, {
117
+ surface: 'contextual-toolbar',
118
+ source: 'toolbar:general',
119
+ });
120
+ },
121
+ }),
122
+ };
123
+ }
124
+ const findCommand = (ctx, id) => getRegisteredCommands(ctx.std).find(candidate => candidate.id === id);
45
125
  export const bpmnPoolToolbarConfig = {
46
126
  actions: [
47
- booleanToggle('a.toggle-resize', 'Enable / lock resizing', ResizeIcon, 'resizeEnabled'),
127
+ booleanToggle('a.toggle-resize', BOARD_RESIZE_TOGGLE, ResizeIcon, 'resizeEnabled'),
128
+ // The two lane gestures, next to the resize toggle: everything on this row
129
+ // is about the SHAPE of the pool rather than about what is drawn in it.
130
+ // Add before remove, because that is the order they can be used in — a pool
131
+ // has no lane to remove until one has been added.
132
+ commandAction('b.add-lane', 'bpmn.addLane', 'com.labre.commands.bpmn.addLane', 'Add lane', bpmnLaneAddIcon),
133
+ commandAction('b.remove-lane', 'bpmn.removeLane', 'com.labre.commands.bpmn.removeLane', 'Remove lane', bpmnLaneRemoveIcon),
134
+ // …and, in the "⋮", the one thing you do to a finished process rather than
135
+ // to the shape of a pool: take it away as a file.
136
+ commandMoreAction('z.export-xml', 'bpmn.exportXml', 'com.labre.commands.bpmn.exportXml', 'Export BPMN XML', bpmnExportXmlIcon),
48
137
  ],
49
138
  when: ctx => ctx.getSurfaceModelsByType(BpmnPoolElementModel).length > 0,
50
139
  };
@@ -1,15 +1,82 @@
1
1
  /** Colored BPMN glyph for the main toolbar button: a pool (green name band) with
2
2
  * a single activity inside. */
3
3
  export declare const bpmnToolbarIcon: import("lit-html").TemplateResult<2>;
4
+ /** Export BPMN XML — a document with an arrow leaving it. */
5
+ export declare const bpmnExportXmlIcon: import("lit-html").TemplateResult<2>;
6
+ /**
7
+ * Import BPMN XML — the export's document, with the arrow coming back IN.
8
+ *
9
+ * Deliberately the same page and the same arrow, mirrored: the two commands are
10
+ * one subject in two directions, and a reader who has met one should recognise
11
+ * the other without reading its label.
12
+ */
13
+ export declare const bpmnImportXmlIcon: import("lit-html").TemplateResult<2>;
14
+ /**
15
+ * Import an SVG sketch — the import page again, with the picture frame that
16
+ * says "this arrives as a drawing" rather than as a process.
17
+ *
18
+ * Kept a sibling of {@link bpmnImportXmlIcon} on purpose: they are the same
19
+ * gesture (a file becomes a board) and the difference between them is the TIER,
20
+ * which is what the mountain-in-a-frame glyph is for.
21
+ */
22
+ export declare const bpmnImportSvgIcon: import("lit-html").TemplateResult<2>;
4
23
  /** Start event — thin green ring. */
5
24
  export declare const bpmnStartIcon: import("lit-html").TemplateResult<2>;
6
25
  /** End event — thick red ring. */
7
26
  export declare const bpmnEndIcon: import("lit-html").TemplateResult<2>;
27
+ /** Message start event — thin green ring, envelope inside. */
28
+ export declare const bpmnStartMessageIcon: import("lit-html").TemplateResult<2>;
29
+ /** Timer start event — thin green ring, clock inside (rim + two hands). */
30
+ export declare const bpmnStartTimerIcon: import("lit-html").TemplateResult<2>;
31
+ /** Message end event — thick red ring, envelope inside. */
32
+ export declare const bpmnEndMessageIcon: import("lit-html").TemplateResult<2>;
33
+ /** Terminate end event — thick red ring, solid disc inside. */
34
+ export declare const bpmnEndTerminateIcon: import("lit-html").TemplateResult<2>;
8
35
  /** Task — rounded rectangle. */
9
36
  export declare const bpmnTaskIcon: import("lit-html").TemplateResult<2>;
37
+ /** User task — the rectangle with a person in its top-left corner. */
38
+ export declare const bpmnTaskUserIcon: import("lit-html").TemplateResult<2>;
39
+ /** Service task — the rectangle with a gear in its top-left corner. */
40
+ export declare const bpmnTaskServiceIcon: import("lit-html").TemplateResult<2>;
41
+ /** Sub-process — the rectangle with the collapsed [+] marker on its bottom edge. */
42
+ export declare const bpmnSubProcessIcon: import("lit-html").TemplateResult<2>;
43
+ /** Call activity — the same [+] marker, on the notation's THICKEST border. */
44
+ export declare const bpmnCallActivityIcon: import("lit-html").TemplateResult<2>;
10
45
  /** Exclusive gateway — diamond with an X. */
11
46
  export declare const bpmnGatewayIcon: import("lit-html").TemplateResult<2>;
47
+ /** Parallel gateway — diamond with a +. */
48
+ export declare const bpmnGatewayParallelIcon: import("lit-html").TemplateResult<2>;
49
+ /** Data object — a page with its top-right corner turned down. */
50
+ export declare const bpmnDataObjectIcon: import("lit-html").TemplateResult<2>;
51
+ /** Data store — a cylinder. */
52
+ export declare const bpmnDataStoreIcon: import("lit-html").TemplateResult<2>;
53
+ /** Text annotation — an open bracket down the leading edge, and a note beside it. */
54
+ export declare const bpmnTextAnnotationIcon: import("lit-html").TemplateResult<2>;
12
55
  /** Sequence flow — solid arrow with a filled head. */
13
56
  export declare const bpmnSequenceIcon: import("lit-html").TemplateResult<2>;
57
+ /** Group — a dashed, generously rounded rectangle drawn AROUND things. */
58
+ export declare const bpmnGroupIcon: import("lit-html").TemplateResult<2>;
59
+ /**
60
+ * Message flow — dashed line, disc at the source, open head at the target.
61
+ *
62
+ * The source terminator is drawn FILLED because that is what the canvas paints:
63
+ * `renderCircle` fills with the connector's `fillColor` before stroking it. The
64
+ * norm asks for a hollow ring, and the shared connector renderer is where that
65
+ * would be fixed; until then an icon promising a ring would be advertising a
66
+ * shape the tool does not draw.
67
+ */
68
+ export declare const bpmnMessageIcon: import("lit-html").TemplateResult<2>;
69
+ /**
70
+ * Association — a dashed line with no head at either end.
71
+ *
72
+ * Same weight as the message flow's line, because on canvas it IS the same
73
+ * weight: both are `strokeWidth: 2`. A thinner icon would hint at a distinction
74
+ * the tool cannot draw (`ASSOCIATION_WIDTH` in `../consts.ts` says why).
75
+ */
76
+ export declare const bpmnAssociationIcon: import("lit-html").TemplateResult<2>;
14
77
  /** Pool — rectangle with a left name band. */
15
78
  export declare const bpmnPoolIcon: import("lit-html").TemplateResult<2>;
79
+ /** Add lane — the pool, cut in two, with a plus on the new band. */
80
+ export declare const bpmnLaneAddIcon: import("lit-html").TemplateResult<2>;
81
+ /** Remove lane — the same pool, with a minus on the band that goes. */
82
+ export declare const bpmnLaneRemoveIcon: import("lit-html").TemplateResult<2>;
@@ -7,6 +7,37 @@ export const bpmnToolbarIcon = svg `<svg width="100%" height="100%" viewBox="0 0
7
7
  <line x1="11" y1="13" x2="11" y2="43" stroke="#262626" stroke-width="1.8"/>
8
8
  <rect x="20" y="20" width="24" height="16" rx="3.5" fill="#ffffff" stroke="#262626" stroke-width="2.2"/>
9
9
  </svg>`;
10
+ /** Export BPMN XML — a document with an arrow leaving it. */
11
+ export const bpmnExportXmlIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
12
+ <path d="M13.5 3.5H7a1.5 1.5 0 0 0-1.5 1.5v14A1.5 1.5 0 0 0 7 20.5h3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
13
+ <path d="M13.5 3.5 18.5 8.5V12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
14
+ <path d="M16 20.5v-6M13.5 18l2.5 2.5 2.5-2.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
15
+ </svg>`;
16
+ /**
17
+ * Import BPMN XML — the export's document, with the arrow coming back IN.
18
+ *
19
+ * Deliberately the same page and the same arrow, mirrored: the two commands are
20
+ * one subject in two directions, and a reader who has met one should recognise
21
+ * the other without reading its label.
22
+ */
23
+ export const bpmnImportXmlIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
24
+ <path d="M13.5 3.5H7a1.5 1.5 0 0 0-1.5 1.5v14A1.5 1.5 0 0 0 7 20.5h3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
25
+ <path d="M13.5 3.5 18.5 8.5V12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
26
+ <path d="M16 14.5v6M13.5 17l2.5-2.5 2.5 2.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
27
+ </svg>`;
28
+ /**
29
+ * Import an SVG sketch — the import page again, with the picture frame that
30
+ * says "this arrives as a drawing" rather than as a process.
31
+ *
32
+ * Kept a sibling of {@link bpmnImportXmlIcon} on purpose: they are the same
33
+ * gesture (a file becomes a board) and the difference between them is the TIER,
34
+ * which is what the mountain-in-a-frame glyph is for.
35
+ */
36
+ export const bpmnImportSvgIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
37
+ <rect x="3" y="5" width="14" height="11" rx="1.5" stroke="currentColor" stroke-width="1.5"/>
38
+ <path d="M3.5 13 7 9.5l3 3 2-2 3.5 3.5" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
39
+ <path d="M19 14.5v6M16.5 17l2.5-2.5 2.5 2.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
40
+ </svg>`;
10
41
  /** Start event — thin green ring. */
11
42
  export const bpmnStartIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
12
43
  <circle cx="12" cy="12" r="8" stroke="#43a06b" stroke-width="2"/>
@@ -15,22 +46,132 @@ export const bpmnStartIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24
15
46
  export const bpmnEndIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
16
47
  <circle cx="12" cy="12" r="8" stroke="#cf5648" stroke-width="3.5"/>
17
48
  </svg>`;
49
+ /** Message start event — thin green ring, envelope inside. */
50
+ export const bpmnStartMessageIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
51
+ <circle cx="12" cy="12" r="8" stroke="#43a06b" stroke-width="2"/>
52
+ <rect x="8" y="9.5" width="8" height="5.5" stroke="currentColor" stroke-width="1.1"/>
53
+ <path d="M8 9.5 L12 13 L16 9.5" stroke="currentColor" stroke-width="1.1" stroke-linejoin="round"/>
54
+ </svg>`;
55
+ /** Timer start event — thin green ring, clock inside (rim + two hands). */
56
+ export const bpmnStartTimerIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
57
+ <circle cx="12" cy="12" r="8" stroke="#43a06b" stroke-width="2"/>
58
+ <circle cx="12" cy="12" r="4.2" stroke="currentColor" stroke-width="1.1"/>
59
+ <path d="M12 12 V8.8 M12 12 L14.2 13.6" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/>
60
+ </svg>`;
61
+ /** Message end event — thick red ring, envelope inside. */
62
+ export const bpmnEndMessageIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
63
+ <circle cx="12" cy="12" r="8" stroke="#cf5648" stroke-width="3.5"/>
64
+ <rect x="8.5" y="9.8" width="7" height="4.8" stroke="currentColor" stroke-width="1.1"/>
65
+ <path d="M8.5 9.8 L12 12.8 L15.5 9.8" stroke="currentColor" stroke-width="1.1" stroke-linejoin="round"/>
66
+ </svg>`;
67
+ /** Terminate end event — thick red ring, solid disc inside. */
68
+ export const bpmnEndTerminateIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
69
+ <circle cx="12" cy="12" r="8" stroke="#cf5648" stroke-width="3.5"/>
70
+ <circle cx="12" cy="12" r="3.6" fill="currentColor"/>
71
+ </svg>`;
18
72
  /** Task — rounded rectangle. */
19
73
  export const bpmnTaskIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
20
74
  <rect x="3.5" y="6.5" width="17" height="11" rx="2.5" stroke="currentColor" stroke-width="1.6"/>
21
75
  </svg>`;
76
+ /** User task — the rectangle with a person in its top-left corner. */
77
+ export const bpmnTaskUserIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
78
+ <rect x="3.5" y="6.5" width="17" height="11" rx="2.5" stroke="currentColor" stroke-width="1.6"/>
79
+ <circle cx="7.4" cy="9.9" r="1.15" stroke="currentColor" stroke-width="1"/>
80
+ <path d="M5.7 13.3 A1.7 1.7 0 0 1 9.1 13.3" stroke="currentColor" stroke-width="1"/>
81
+ </svg>`;
82
+ /** Service task — the rectangle with a gear in its top-left corner. */
83
+ export const bpmnTaskServiceIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
84
+ <rect x="3.5" y="6.5" width="17" height="11" rx="2.5" stroke="currentColor" stroke-width="1.6"/>
85
+ <circle cx="7.6" cy="11" r="1.7" stroke="currentColor" stroke-width="1"/>
86
+ <circle cx="7.6" cy="11" r="0.5" stroke="currentColor" stroke-width="0.8"/>
87
+ <path d="M7.6 8.9 V9.3 M7.6 12.7 V13.1 M5.5 11 H5.9 M9.3 11 H9.7 M6.1 9.5 L6.4 9.8 M8.8 12.2 L9.1 12.5 M9.1 9.5 L8.8 9.8 M6.4 12.2 L6.1 12.5" stroke="currentColor" stroke-width="1" stroke-linecap="round"/>
88
+ </svg>`;
89
+ /** Sub-process — the rectangle with the collapsed [+] marker on its bottom edge. */
90
+ export const bpmnSubProcessIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
91
+ <rect x="3.5" y="6.5" width="17" height="11" rx="2.5" stroke="currentColor" stroke-width="1.6"/>
92
+ <rect x="9.6" y="12.6" width="4.8" height="4.8" stroke="currentColor" stroke-width="1.1"/>
93
+ <path d="M12 13.8 V16.2 M10.8 15 H13.2" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/>
94
+ </svg>`;
95
+ /** Call activity — the same [+] marker, on the notation's THICKEST border. */
96
+ export const bpmnCallActivityIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
97
+ <rect x="4" y="7" width="16" height="10" rx="2.5" stroke="currentColor" stroke-width="3"/>
98
+ <rect x="9.6" y="12.2" width="4.8" height="4.8" stroke="currentColor" stroke-width="1.1"/>
99
+ <path d="M12 13.4 V15.8 M10.8 14.6 H13.2" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/>
100
+ </svg>`;
22
101
  /** Exclusive gateway — diamond with an X. */
23
102
  export const bpmnGatewayIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
24
103
  <path d="M12 3 L21 12 L12 21 L3 12 Z" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/>
25
104
  <path d="M9 9 L15 15 M15 9 L9 15" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
26
105
  </svg>`;
106
+ /** Parallel gateway — diamond with a +. */
107
+ export const bpmnGatewayParallelIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
108
+ <path d="M12 3 L21 12 L12 21 L3 12 Z" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/>
109
+ <path d="M12 8 V16 M8 12 H16" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
110
+ </svg>`;
111
+ /** Data object — a page with its top-right corner turned down. */
112
+ export const bpmnDataObjectIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
113
+ <path d="M6 3.5 H14 L18 7.5 V20.5 H6 Z" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/>
114
+ <path d="M14 3.5 V7.5 H18" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"/>
115
+ </svg>`;
116
+ /** Data store — a cylinder. */
117
+ export const bpmnDataStoreIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
118
+ <path d="M4.5 7 V17 C4.5 18.4 8 19.5 12 19.5 C16 19.5 19.5 18.4 19.5 17 V7" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/>
119
+ <ellipse cx="12" cy="7" rx="7.5" ry="2.5" stroke="currentColor" stroke-width="1.6"/>
120
+ </svg>`;
121
+ /** Text annotation — an open bracket down the leading edge, and a note beside it. */
122
+ export const bpmnTextAnnotationIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
123
+ <path d="M9 5 H5.5 V19 H9" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
124
+ <path d="M11.5 9 H18.5 M11.5 12 H18.5 M11.5 15 H16" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/>
125
+ </svg>`;
27
126
  /** Sequence flow — solid arrow with a filled head. */
28
127
  export const bpmnSequenceIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
29
128
  <path d="M3 12 H17" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
30
129
  <path d="M15 8 L21 12 L15 16 Z" fill="currentColor"/>
31
130
  </svg>`;
131
+ /** Group — a dashed, generously rounded rectangle drawn AROUND things. */
132
+ export const bpmnGroupIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
133
+ <rect x="3.5" y="5.5" width="17" height="13" rx="4" stroke="currentColor" stroke-width="1.6" stroke-dasharray="3.4 2.6"/>
134
+ </svg>`;
135
+ /**
136
+ * Message flow — dashed line, disc at the source, open head at the target.
137
+ *
138
+ * The source terminator is drawn FILLED because that is what the canvas paints:
139
+ * `renderCircle` fills with the connector's `fillColor` before stroking it. The
140
+ * norm asks for a hollow ring, and the shared connector renderer is where that
141
+ * would be fixed; until then an icon promising a ring would be advertising a
142
+ * shape the tool does not draw.
143
+ */
144
+ export const bpmnMessageIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
145
+ <circle cx="4.8" cy="12" r="2.2" fill="currentColor"/>
146
+ <path d="M7.4 12 H17.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-dasharray="3 2.6"/>
147
+ <path d="M15.6 8.6 L20 12 L15.6 15.4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
148
+ </svg>`;
149
+ /**
150
+ * Association — a dashed line with no head at either end.
151
+ *
152
+ * Same weight as the message flow's line, because on canvas it IS the same
153
+ * weight: both are `strokeWidth: 2`. A thinner icon would hint at a distinction
154
+ * the tool cannot draw (`ASSOCIATION_WIDTH` in `../consts.ts` says why).
155
+ */
156
+ export const bpmnAssociationIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
157
+ <path d="M3.5 17 L20.5 7" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-dasharray="2.4 2.4"/>
158
+ </svg>`;
32
159
  /** Pool — rectangle with a left name band. */
33
160
  export const bpmnPoolIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
34
161
  <rect x="3.5" y="5.5" width="17" height="13" rx="1.5" stroke="currentColor" stroke-width="1.6"/>
35
162
  <path d="M8 5.5 V18.5" stroke="currentColor" stroke-width="1.6"/>
36
163
  </svg>`;
164
+ /** Add lane — the pool, cut in two, with a plus on the new band. */
165
+ export const bpmnLaneAddIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
166
+ <rect x="3.5" y="5.5" width="17" height="13" rx="1.5" stroke="currentColor" stroke-width="1.6"/>
167
+ <path d="M8 5.5 V18.5" stroke="currentColor" stroke-width="1.6"/>
168
+ <path d="M8 12 H20.5" stroke="currentColor" stroke-width="1.6"/>
169
+ <path d="M14.25 13.25 V17 M12.4 15.1 H16.1" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
170
+ </svg>`;
171
+ /** Remove lane — the same pool, with a minus on the band that goes. */
172
+ export const bpmnLaneRemoveIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
173
+ <rect x="3.5" y="5.5" width="17" height="13" rx="1.5" stroke="currentColor" stroke-width="1.6"/>
174
+ <path d="M8 5.5 V18.5" stroke="currentColor" stroke-width="1.6"/>
175
+ <path d="M8 12 H20.5" stroke="currentColor" stroke-width="1.6"/>
176
+ <path d="M12.4 15.1 H16.1" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
177
+ </svg>`;