@formicoidea/labre-framework-bpmn 0.58.0 → 0.60.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.
@@ -24,6 +24,22 @@ export declare const bpmnPoolToolbarConfig: {
24
24
  tooltip: string;
25
25
  run: (runCtx: ToolbarContext) => void;
26
26
  };
27
+ }, {
28
+ id: string;
29
+ when: (ctx: ToolbarContext) => boolean;
30
+ generate: (ctx: ToolbarContext) => {
31
+ icon: TemplateResult;
32
+ tooltip: string;
33
+ run: (runCtx: ToolbarContext) => void;
34
+ };
35
+ }, {
36
+ id: string;
37
+ when: (ctx: ToolbarContext) => boolean;
38
+ generate: (ctx: ToolbarContext) => {
39
+ icon: TemplateResult;
40
+ tooltip: string;
41
+ run: (runCtx: ToolbarContext) => void;
42
+ };
27
43
  }, import("@formicoidea/labre-core/shared/services").ToolbarActionGenerator];
28
44
  readonly when: (ctx: ToolbarContext) => boolean;
29
45
  };
@@ -35,8 +51,8 @@ export declare const bpmnPoolToolbarExtension: import("@formicoidea/labre-core/_
35
51
  * up — the same merge C4's board makes for the same reason).
36
52
  *
37
53
  * `c.legend` and not `b.legend`: the toolbar sorts lexicographically by id
38
- * after partitioning by placement, and `'b.add-lane' < 'b.legend' <
39
- * 'b.remove-lane'` would wedge the button between the two lane gestures. `c.`
54
+ * after partitioning by placement, and `'b.lane-1-add' < 'b.legend' <
55
+ * 'b.lane-4-remove'` would wedge the button between the two lane gestures. `c.`
40
56
  * puts it where it belongs — resize · add lane · remove lane · **Legend** ·
41
57
  * Validation, with Export XML in the "⋮".
42
58
  *
@@ -3,7 +3,7 @@ import { BpmnPoolElementModel } from '@formicoidea/labre-core/model';
3
3
  import { BOARD_RESIZE_TOGGLE, commandMoreAction, ToolbarModuleExtension, translateKey, } from '@formicoidea/labre-core/shared/services';
4
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
+ import { bpmnExportXmlIcon, bpmnLaneAddIcon, bpmnLaneDownIcon, bpmnLaneRemoveIcon, bpmnLaneUpIcon, } from './icons.js';
7
7
  const ResizeIcon = html `<svg
8
8
  width="24"
9
9
  height="24"
@@ -90,10 +90,14 @@ export const bpmnPoolToolbarConfig = {
90
90
  booleanToggle('a.toggle-resize', BOARD_RESIZE_TOGGLE, ResizeIcon, 'resizeEnabled'),
91
91
  // The two lane gestures, next to the resize toggle: everything on this row
92
92
  // is about the SHAPE of the pool rather than about what is drawn in it.
93
- // Add before remove, because that is the order they can be used in — a pool
94
- // has no lane to remove until one has been added.
95
- commandAction('b.add-lane', 'bpmn.addLane', 'com.labre.commands.bpmn.addLane', 'Add lane', bpmnLaneAddIcon),
96
- commandAction('b.remove-lane', 'bpmn.removeLane', 'com.labre.commands.bpmn.removeLane', 'Remove lane', bpmnLaneRemoveIcon),
93
+ // Actions sort by id: add, move up, move down, remove — the order a lane
94
+ // is handled in, with remove last because it is the destructive one.
95
+ commandAction('b.lane-1-add', 'bpmn.addLane', 'com.labre.commands.bpmn.addLane', 'Add lane', bpmnLaneAddIcon),
96
+ commandAction('b.lane-4-remove', 'bpmn.removeLane', 'com.labre.commands.bpmn.removeLane', 'Remove lane', bpmnLaneRemoveIcon),
97
+ // Reorder, beside add and remove: they act on the FOCUSED lane (a click on
98
+ // its title strip) and only show while one is focused and can move.
99
+ commandAction('b.lane-2-up', 'bpmn.moveLaneUp', 'com.labre.commands.bpmn.moveLaneUp', 'Move lane up', bpmnLaneUpIcon),
100
+ commandAction('b.lane-3-down', 'bpmn.moveLaneDown', 'com.labre.commands.bpmn.moveLaneDown', 'Move lane down', bpmnLaneDownIcon),
97
101
  // …and, in the "⋮", the one thing you do to a finished process rather than
98
102
  // to the shape of a pool: take it away as a file.
99
103
  commandMoreAction('z.export-xml', 'bpmn.exportXml', 'com.labre.commands.bpmn.exportXml', 'Export BPMN XML', bpmnExportXmlIcon),
@@ -111,8 +115,8 @@ export const bpmnPoolToolbarExtension = ToolbarModuleExtension({
111
115
  * up — the same merge C4's board makes for the same reason).
112
116
  *
113
117
  * `c.legend` and not `b.legend`: the toolbar sorts lexicographically by id
114
- * after partitioning by placement, and `'b.add-lane' < 'b.legend' <
115
- * 'b.remove-lane'` would wedge the button between the two lane gestures. `c.`
118
+ * after partitioning by placement, and `'b.lane-1-add' < 'b.legend' <
119
+ * 'b.lane-4-remove'` would wedge the button between the two lane gestures. `c.`
116
120
  * puts it where it belongs — resize · add lane · remove lane · **Legend** ·
117
121
  * Validation, with Export XML in the "⋮".
118
122
  *
@@ -87,3 +87,7 @@ export declare const bpmnPoolIcon: import("lit-html").TemplateResult<2>;
87
87
  export declare const bpmnLaneAddIcon: import("lit-html").TemplateResult<2>;
88
88
  /** Remove lane — the same pool, with a minus on the band that goes. */
89
89
  export declare const bpmnLaneRemoveIcon: import("lit-html").TemplateResult<2>;
90
+ /** Move lane up — the pool cut in two, with an arrow rising out of the lower band. */
91
+ export declare const bpmnLaneUpIcon: import("lit-html").TemplateResult<2>;
92
+ /** Move lane down — the same pool, with an arrow falling out of the upper band. */
93
+ export declare const bpmnLaneDownIcon: import("lit-html").TemplateResult<2>;
@@ -179,3 +179,17 @@ export const bpmnLaneRemoveIcon = svg `<svg width="24" height="24" viewBox="0 0
179
179
  <path d="M8 12 H20.5" stroke="currentColor" stroke-width="1.6"/>
180
180
  <path d="M12.4 15.1 H16.1" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
181
181
  </svg>`;
182
+ /** Move lane up — the pool cut in two, with an arrow rising out of the lower band. */
183
+ export const bpmnLaneUpIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
184
+ <rect x="3.5" y="5.5" width="17" height="13" rx="1.5" stroke="currentColor" stroke-width="1.6"/>
185
+ <path d="M8 5.5 V18.5" stroke="currentColor" stroke-width="1.6"/>
186
+ <path d="M8 12 H20.5" stroke="currentColor" stroke-width="1.6"/>
187
+ <path d="M14.25 16.6 V13.6 M12.6 15 L14.25 13.4 L15.9 15" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
188
+ </svg>`;
189
+ /** Move lane down — the same pool, with an arrow falling out of the upper band. */
190
+ export const bpmnLaneDownIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
191
+ <rect x="3.5" y="5.5" width="17" height="13" rx="1.5" stroke="currentColor" stroke-width="1.6"/>
192
+ <path d="M8 5.5 V18.5" stroke="currentColor" stroke-width="1.6"/>
193
+ <path d="M8 12 H20.5" stroke="currentColor" stroke-width="1.6"/>
194
+ <path d="M14.25 7.4 V10.4 M12.6 9 L14.25 10.6 L15.9 9" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
195
+ </svg>`;
@@ -0,0 +1,45 @@
1
+ import type { FrameworkToolbox, SerializedElementProps, ToolboxPoint } from '@formicoidea/labre-core/interchange';
2
+ import type { BpmnNodeKind } from '@formicoidea/labre-core/model';
3
+ import { type BpmnEdgeKey } from './consts.js';
4
+ /**
5
+ * BPMN's toolbar as pure builders (`docs/adr/0045`): what `createBpmnNode`,
6
+ * `createBpmnPool`, the lane gesture and the three flow tools place, with no
7
+ * editor behind them. The actions call these, so an artefact a host places
8
+ * and one placed from the toolbar are the same elements.
9
+ */
10
+ /** The text slot of a flow object, an artefact or a data shape. */
11
+ export interface BpmnNodeTexts {
12
+ /** The name; the kind's English seed when absent. */
13
+ name?: string;
14
+ }
15
+ /**
16
+ * A BPMN artefact at `at` (its top-left), as the toolbar places it.
17
+ *
18
+ * An inscribed kind (activities, the annotation, the group) is ONE element
19
+ * carrying its name inside. An external kind (events, gateways, data shapes)
20
+ * is the bare symbol, its name as a `bpmn:label` text centred under it, and
21
+ * the group that makes the two one artefact, last (R38). The symbol's id is
22
+ * `<local>:node` either way, which is what a flow attaches to.
23
+ */
24
+ export declare function bpmnNodeElements(kind: BpmnNodeKind, at: ToolboxPoint, texts?: BpmnNodeTexts, local?: string): SerializedElementProps[];
25
+ /** The text slots of a pool. */
26
+ export interface BpmnPoolTexts {
27
+ /** The participant's name; `Pool` when absent. */
28
+ name?: string;
29
+ /** One lane name per line, top to bottom; no lane when absent. */
30
+ lanes?: string;
31
+ }
32
+ /**
33
+ * A pool at `at`, at the size the toolbar draws it, with the lanes it is
34
+ * given.
35
+ *
36
+ * Each lane is what one click on "Add lane" appends to a fresh pool: an equal
37
+ * weight of 1, and `Lane N` when its line is blank. Its id is `<local>-lane-N`
38
+ * and not a minted one: a builder mints nothing, and an id unique within the
39
+ * pool is all a lane needs (the importer's own `lane-N` fallback).
40
+ */
41
+ export declare function bpmnPoolElement(at: ToolboxPoint, texts?: BpmnPoolTexts, local?: string): SerializedElementProps;
42
+ /** The connector a flow tool is armed with, between two ends. */
43
+ export declare function bpmnFlowElement(edge: BpmnEdgeKey, from: string, to: string, label?: string): SerializedElementProps;
44
+ /** Every item of the BPMN toolbar that places elements, in the toolbar's order. */
45
+ export declare const BPMN_TOOLBOX: FrameworkToolbox;
@@ -0,0 +1,129 @@
1
+ import { Bound } from '@formicoidea/labre-core/global/gfx';
2
+ import { bpmnCommandsManifest } from './commands-manifest.js';
3
+ import { bpmnLabelMode, LANE_NAME_FALLBACK, NODE_LABEL, NODE_SIZE, POOL_NAME_FALLBACK, POOL_REF_HEIGHT, POOL_REF_WIDTH, } from './consts.js';
4
+ import { bpmnConnectorProps, bpmnLabelBoxFor, bpmnLabelProps, bpmnNodeProps, bpmnPoolProps, } from './presets.js';
5
+ /**
6
+ * A BPMN artefact at `at` (its top-left), as the toolbar places it.
7
+ *
8
+ * An inscribed kind (activities, the annotation, the group) is ONE element
9
+ * carrying its name inside. An external kind (events, gateways, data shapes)
10
+ * is the bare symbol, its name as a `bpmn:label` text centred under it, and
11
+ * the group that makes the two one artefact, last (R38). The symbol's id is
12
+ * `<local>:node` either way, which is what a flow attaches to.
13
+ */
14
+ export function bpmnNodeElements(kind, at, texts = {}, local = kind) {
15
+ const { w, h } = NODE_SIZE[kind];
16
+ const name = texts.name?.trim() || NODE_LABEL[kind];
17
+ const id = (part) => `${local}:${part}`;
18
+ const xywh = new Bound(at.x, at.y, w, h).serialize();
19
+ if (bpmnLabelMode(kind) === 'inscribed') {
20
+ return [{ ...bpmnNodeProps(kind, { xywh, text: name }), id: id('node') }];
21
+ }
22
+ const label = bpmnLabelBoxFor(kind, at.x + w / 2, at.y + h / 2);
23
+ const members = [
24
+ // `text: undefined` and not no key: the symbol is born bare exactly as the
25
+ // toolbar's is, and `bpmnNodeProps` passes the key through unchanged.
26
+ { ...bpmnNodeProps(kind, { xywh, text: undefined }), id: id('node') },
27
+ { ...bpmnLabelProps(name, label.x, label.y), id: id('label') },
28
+ ];
29
+ return [
30
+ ...members,
31
+ {
32
+ type: 'group',
33
+ id: id('group'),
34
+ children: Object.fromEntries(members.map(m => [m.id, true])),
35
+ },
36
+ ];
37
+ }
38
+ /**
39
+ * A pool at `at`, at the size the toolbar draws it, with the lanes it is
40
+ * given.
41
+ *
42
+ * Each lane is what one click on "Add lane" appends to a fresh pool: an equal
43
+ * weight of 1, and `Lane N` when its line is blank. Its id is `<local>-lane-N`
44
+ * and not a minted one: a builder mints nothing, and an id unique within the
45
+ * pool is all a lane needs (the importer's own `lane-N` fallback).
46
+ */
47
+ export function bpmnPoolElement(at, texts = {}, local = 'pool') {
48
+ const names = (texts.lanes ?? '').split('\n').map(line => line.trim());
49
+ const lanes = texts.lanes?.trim()
50
+ ? names.map((name, i) => ({
51
+ id: `${local}-lane-${i + 1}`,
52
+ name: name || LANE_NAME_FALLBACK.replace('{{n}}', String(i + 1)),
53
+ size: 1,
54
+ }))
55
+ : [];
56
+ return {
57
+ ...bpmnPoolProps({
58
+ xywh: new Bound(at.x, at.y, POOL_REF_WIDTH, POOL_REF_HEIGHT).serialize(),
59
+ name: texts.name?.trim() || POOL_NAME_FALLBACK,
60
+ }),
61
+ id: local,
62
+ // Absent until the first lane, as on a pool drawn from the toolbar.
63
+ ...(lanes.length > 0 ? { lanes } : {}),
64
+ };
65
+ }
66
+ /** The connector a flow tool is armed with, between two ends. */
67
+ export function bpmnFlowElement(edge, from, to, label) {
68
+ return {
69
+ ...bpmnConnectorProps(edge),
70
+ source: { id: from },
71
+ target: { id: to },
72
+ ...(label?.trim() ? { text: label.trim() } : {}),
73
+ };
74
+ }
75
+ /** The toolbar command's label, so a host names an item as the toolbar does. */
76
+ function label(commandId) {
77
+ const row = bpmnCommandsManifest.find(r => r.id === commandId);
78
+ return {
79
+ labelKey: row?.labelKey ?? commandId,
80
+ labelFallback: row?.labelFallback ?? commandId,
81
+ };
82
+ }
83
+ const nodeItem = (id, kind, commandId) => ({
84
+ id,
85
+ ...label(commandId),
86
+ texts: ['name'],
87
+ size: NODE_SIZE[kind],
88
+ build: (at, texts, local) => bpmnNodeElements(kind, at, texts, local),
89
+ });
90
+ const flowLink = (id, edge, commandId) => ({
91
+ id,
92
+ ...label(commandId),
93
+ build: (from, to, text) => bpmnFlowElement(edge, from, to, text),
94
+ });
95
+ /** Every item of the BPMN toolbar that places elements, in the toolbar's order. */
96
+ export const BPMN_TOOLBOX = {
97
+ framework: 'bpmn',
98
+ items: [
99
+ nodeItem('start-event', 'startEvent', 'bpmn.addStartEvent'),
100
+ nodeItem('end-event', 'endEvent', 'bpmn.addEndEvent'),
101
+ nodeItem('task', 'task', 'bpmn.addTask'),
102
+ nodeItem('exclusive-gateway', 'gatewayExclusive', 'bpmn.addExclusiveGateway'),
103
+ {
104
+ id: 'pool',
105
+ ...label('bpmn.addPool'),
106
+ texts: ['name', 'lanes'],
107
+ size: { w: POOL_REF_WIDTH, h: POOL_REF_HEIGHT },
108
+ build: (at, texts, local) => [bpmnPoolElement(at, texts, local)],
109
+ },
110
+ nodeItem('user-task', 'taskUser', 'bpmn.addUserTask'),
111
+ nodeItem('service-task', 'taskService', 'bpmn.addServiceTask'),
112
+ nodeItem('sub-process', 'subProcess', 'bpmn.addSubProcess'),
113
+ nodeItem('call-activity', 'callActivity', 'bpmn.addCallActivity'),
114
+ nodeItem('parallel-gateway', 'gatewayParallel', 'bpmn.addParallelGateway'),
115
+ nodeItem('message-start-event', 'startEventMessage', 'bpmn.addMessageStartEvent'),
116
+ nodeItem('timer-start-event', 'startEventTimer', 'bpmn.addTimerStartEvent'),
117
+ nodeItem('message-end-event', 'endEventMessage', 'bpmn.addMessageEndEvent'),
118
+ nodeItem('terminate-end-event', 'endEventTerminate', 'bpmn.addTerminateEndEvent'),
119
+ nodeItem('data-object', 'dataObject', 'bpmn.addDataObject'),
120
+ nodeItem('data-store', 'dataStore', 'bpmn.addDataStore'),
121
+ nodeItem('text-annotation', 'textAnnotation', 'bpmn.addTextAnnotation'),
122
+ nodeItem('group', 'group', 'bpmn.addGroup'),
123
+ ],
124
+ links: [
125
+ flowLink('sequence-flow', 'sequenceFlow', 'bpmn.sequenceFlowTool'),
126
+ flowLink('message-flow', 'messageFlow', 'bpmn.messageFlowTool'),
127
+ flowLink('association', 'association', 'bpmn.associationTool'),
128
+ ],
129
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@formicoidea/labre-framework-bpmn",
3
3
  "description": "Labre bpmn framework for @formicoidea/labre-core.",
4
- "version": "0.58.0",
4
+ "version": "0.60.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "author": "lajola",
@@ -35,7 +35,7 @@
35
35
  "dist"
36
36
  ],
37
37
  "dependencies": {
38
- "@formicoidea/labre-core": "0.58.0",
38
+ "@formicoidea/labre-core": "0.60.0",
39
39
  "lit": "^3.2.0"
40
40
  }
41
41
  }