@formicoidea/labre-framework-ddd-event-storming 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.
- package/dist/actions.d.ts +7 -0
- package/dist/actions.js +12 -22
- package/dist/background.js +2 -2
- package/dist/commands.js +18 -35
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/interchange-headless.d.ts +10 -0
- package/dist/interchange-headless.js +10 -0
- package/dist/roles.d.ts +1 -1
- package/dist/roles.js +1 -1
- package/dist/sticky-size.d.ts +16 -0
- package/dist/sticky-size.js +19 -0
- package/dist/toolbox.d.ts +40 -0
- package/dist/toolbox.js +142 -0
- package/package.json +7 -3
package/dist/actions.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import type { GfxController } from '@formicoidea/labre-core/std/gfx';
|
|
2
|
+
/**
|
|
3
|
+
* Creation / activation actions for the Event Storming toolbox — the BEHAVIOUR
|
|
4
|
+
* layer, depending on nothing but the {@link GfxController}.
|
|
5
|
+
*
|
|
6
|
+
* They emit no telemetry: since PF3 the single emission point is the command
|
|
7
|
+
* registry's `runCommand` (`docs/adr/0008`).
|
|
8
|
+
*/
|
|
2
9
|
/** Create the board at the viewport centre, select it, return to the default tool. */
|
|
3
10
|
export declare function createEventStormingBoard(gfx: GfxController): void;
|
|
4
11
|
/**
|
package/dist/actions.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { backgroundSize, DefaultTool } from '@formicoidea/labre-core/blocks/surface';
|
|
2
2
|
import { ConnectorTool } from '@formicoidea/labre-core/gfx/connector';
|
|
3
|
-
import {
|
|
4
|
-
import { ConnectorMode, PointStyle, StrokeStyle } from '@formicoidea/labre-core/model';
|
|
5
|
-
import { Bound } from '@formicoidea/labre-core/global/gfx';
|
|
3
|
+
import { ConnectorMode } from '@formicoidea/labre-core/model';
|
|
6
4
|
import { EVENT_STORMING_BACKGROUND } from './background.js';
|
|
7
5
|
import { ES_ROLE } from './roles.js';
|
|
6
|
+
import { eventStormingBoardElement, eventStormingFlowStyle } from './toolbox.js';
|
|
8
7
|
/**
|
|
9
8
|
* Creation / activation actions for the Event Storming toolbox — the BEHAVIOUR
|
|
10
9
|
* layer, depending on nothing but the {@link GfxController}.
|
|
@@ -12,22 +11,19 @@ import { ES_ROLE } from './roles.js';
|
|
|
12
11
|
* They emit no telemetry: since PF3 the single emission point is the command
|
|
13
12
|
* registry's `runCommand` (`docs/adr/0008`).
|
|
14
13
|
*/
|
|
15
|
-
const FLOW_STROKE_WIDTH = 2;
|
|
16
14
|
/** Create the board at the viewport centre, select it, return to the default tool. */
|
|
17
15
|
export function createEventStormingBoard(gfx) {
|
|
18
16
|
if (!gfx.surface)
|
|
19
17
|
return;
|
|
20
18
|
const { width, height } = backgroundSize(EVENT_STORMING_BACKGROUND);
|
|
21
19
|
const { centerX, centerY } = gfx.viewport;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
role: EVENT_STORMING_BACKGROUND.role,
|
|
28
|
-
resizeEnabled: EVENT_STORMING_BACKGROUND.geometry.resizable,
|
|
29
|
-
xywh: new Bound(centerX - width / 2, centerY - height / 2, width, height).serialize(),
|
|
20
|
+
// The board's props come from the toolbox (`docs/adr/0045`), the one
|
|
21
|
+
// assembly a host with no editor also calls; the viewport centre is ours.
|
|
22
|
+
const { id: _local, ...props } = eventStormingBoardElement({
|
|
23
|
+
x: centerX - width / 2,
|
|
24
|
+
y: centerY - height / 2,
|
|
30
25
|
});
|
|
26
|
+
const id = gfx.surface.addElement(props);
|
|
31
27
|
gfx.doc.captureSync();
|
|
32
28
|
gfx.tool.setTool(DefaultTool);
|
|
33
29
|
gfx.selection.set({ elements: [id], editing: false });
|
|
@@ -62,16 +58,10 @@ export function activateEventStormingFlow(gfx) {
|
|
|
62
58
|
mode: ConnectorMode.Straight,
|
|
63
59
|
role: ES_ROLE.flow,
|
|
64
60
|
// The look rides on the activation, never through the last-props store:
|
|
65
|
-
// the plain connector tool must keep the user's own style (#144 M1).
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
strokeWidth: FLOW_STROKE_WIDTH,
|
|
70
|
-
frontEndpointStyle: PointStyle.None,
|
|
71
|
-
// The arrow points at what FOLLOWS, which is the target: the role's
|
|
72
|
-
// verb is "leads to", so the source is what happens first.
|
|
73
|
-
rearEndpointStyle: PointStyle.Arrow,
|
|
74
|
-
},
|
|
61
|
+
// the plain connector tool must keep the user's own style (#144 M1). It is
|
|
62
|
+
// the toolbox's (`eventStormingFlowStyle`, `docs/adr/0045`), so a flow
|
|
63
|
+
// drawn here and one built by a host look the same.
|
|
64
|
+
style: eventStormingFlowStyle(),
|
|
75
65
|
});
|
|
76
66
|
// The Event Storming palette stays open (native sub-menu behaviour): it only
|
|
77
67
|
// closes on re-click of the senior button, another senior tool, or Escape.
|
package/dist/background.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ES_STICKIES, FONT_FAMILY } from '@formicoidea/labre-ddd-shared';
|
|
2
|
-
import { NOTATION_NEUTRALS } from '@formicoidea/labre-core/shared/
|
|
1
|
+
import { ES_STICKIES, FONT_FAMILY, } from '@formicoidea/labre-ddd-shared/headless';
|
|
2
|
+
import { NOTATION_NEUTRALS } from '@formicoidea/labre-core/shared/headless';
|
|
3
3
|
import { ES_ROLE } from './roles.js';
|
|
4
4
|
/**
|
|
5
5
|
* The Event Storming board, DECLARED (the `FrameworkBackgroundDef` primitive).
|
package/dist/commands.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { addSticky, esStickySeedKey, ES_HOTSPOT, ES_STICKIES, eventStormingToolbarIcon, LABEL_COLOR, placeDddElement,
|
|
1
|
+
import { addSticky, esStickySeedKey, ES_HOTSPOT, ES_STICKIES, eventStormingToolbarIcon, LABEL_COLOR, placeDddElement, } from '@formicoidea/labre-ddd-shared';
|
|
2
2
|
import { NOTATION_NEUTRALS } from '@formicoidea/labre-core/shared/consts';
|
|
3
3
|
import { translateKey, } from '@formicoidea/labre-core/shared/services';
|
|
4
4
|
import { GfxControllerIdentifier } from '@formicoidea/labre-core/std/gfx';
|
|
5
5
|
import { svg } from 'lit';
|
|
6
6
|
import { activateEventStormingFlow, createEventStormingBoard } from './actions.js';
|
|
7
7
|
import { ES_ROLE, ES_STICKY_ROLE } from './roles.js';
|
|
8
|
+
import { eventStormingStickyOpts } from './toolbox.js';
|
|
8
9
|
/**
|
|
9
10
|
* The automatic legend's own section titles — text stamped onto the board the
|
|
10
11
|
* moment the legend is built, like any other seed, and declared HERE because
|
|
@@ -38,16 +39,6 @@ const squareSwatch = (color) => svg `<svg width="24" height="24" viewBox="0 0 24
|
|
|
38
39
|
const diamondSwatch = (color) => svg `<svg width="24" height="24" viewBox="0 0 24 24"><rect x="6" y="6" width="12" height="12" transform="rotate(45 12 12)" fill="${color}"/></svg>`;
|
|
39
40
|
const flowSwatch = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M4 12 H18" stroke="currentColor" stroke-width="2"/><path d="M16 8 L20 12 L16 16" stroke="currentColor" stroke-width="2" fill="none"/></svg>`;
|
|
40
41
|
const boardSwatch = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none"><rect x="2.5" y="4" width="19" height="16" rx="2" fill="${NOTATION_NEUTRALS.cardFill}" stroke="currentColor" stroke-width="1.6"/><rect x="5" y="7.5" width="4" height="4" rx="1" fill="#F5963B"/><rect x="10.5" y="7.5" width="4" height="4" rx="1" fill="#5BA3DB"/><rect x="16" y="7.5" width="4" height="4" rx="1" fill="#FAF2C9" stroke="#c9bd7f" stroke-width="0.6"/><path d="M4.5 16.5 H19.5" stroke="currentColor" stroke-width="1.2"/><path d="M17.5 14.8 L19.8 16.5 L17.5 18.2" stroke="currentColor" stroke-width="1.2"/></svg>`;
|
|
41
|
-
/**
|
|
42
|
-
* The aggregate is created BIG — 160 against the standard 120.
|
|
43
|
-
*
|
|
44
|
-
* Size is half of how the notation distinguishes it: on a real wall the
|
|
45
|
-
* aggregate is the large pale sticky a run of commands lands on, and the
|
|
46
|
-
* colour ladder in `ES_STICKIES` carries the other half. Declared here rather
|
|
47
|
-
* than in the shared palette because it is a FORMAT, not a colour: the palette
|
|
48
|
-
* says which yellow, the toolbox says how big.
|
|
49
|
-
*/
|
|
50
|
-
const AGGREGATE_SIZE = 160;
|
|
51
42
|
const SPECS = [
|
|
52
43
|
{
|
|
53
44
|
id: 'addBoard',
|
|
@@ -66,20 +57,16 @@ const SPECS = [
|
|
|
66
57
|
iconKey: `ddd-event-storming.sticky.${preset.kind}`,
|
|
67
58
|
element: `sticky:${preset.kind}`,
|
|
68
59
|
icon: squareSwatch(preset.fill),
|
|
69
|
-
run: std => placeDddElement(std, (surface, cx, cy) => addSticky(surface, std, cx, cy,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
// placed before WS5 carries none and is never evaluated
|
|
80
|
-
// (promesse #71).
|
|
81
|
-
role: ES_STICKY_ROLE[preset.kind],
|
|
82
|
-
})),
|
|
60
|
+
run: std => placeDddElement(std, (surface, cx, cy) => addSticky(surface, std, cx, cy,
|
|
61
|
+
// Colours, size (the aggregate is bigger) and role come from the
|
|
62
|
+
// toolbox (`docs/adr/0045`), the one assembly a host with no
|
|
63
|
+
// editor also calls. A sticky placed before WS5 carries no role
|
|
64
|
+
// and is never evaluated (promesse #71).
|
|
65
|
+
eventStormingStickyOpts(preset.kind,
|
|
66
|
+
// Translated HERE and once: the caption is document content the
|
|
67
|
+
// moment it lands (ADR 0023), so the host's catalogue is asked
|
|
68
|
+
// at placement and never again.
|
|
69
|
+
translateKey(std, esStickySeedKey(preset.kind), preset.label)))),
|
|
83
70
|
// Row and command out of the SAME preset, so the colour ladder the legend
|
|
84
71
|
// shows is by construction the colour ladder on the wall — and a tenth
|
|
85
72
|
// sticky kind gets its row with no edit.
|
|
@@ -95,16 +82,12 @@ const SPECS = [
|
|
|
95
82
|
iconKey: 'ddd-event-storming.sticky.hotspot',
|
|
96
83
|
element: 'sticky:hotspot',
|
|
97
84
|
icon: diamondSwatch(ES_HOTSPOT.fill),
|
|
98
|
-
run: std => placeDddElement(std, (surface, cx, cy) => addSticky(surface, std, cx, cy,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
// Typed like the rest, and cited by no grammar triplet on purpose —
|
|
105
|
-
// an arc onto a hotspot is a question being parked. See `rules.ts`.
|
|
106
|
-
role: ES_STICKY_ROLE.hotspot,
|
|
107
|
-
})),
|
|
85
|
+
run: std => placeDddElement(std, (surface, cx, cy) => addSticky(surface, std, cx, cy,
|
|
86
|
+
// A diamond, typed like the rest and cited by no grammar triplet on
|
|
87
|
+
// purpose — an arc onto a hotspot is a question being parked. See
|
|
88
|
+
// `rules.ts`. Translated HERE and once, like every sticky above
|
|
89
|
+
// (ADR 0023).
|
|
90
|
+
eventStormingStickyOpts('hotspot', translateKey(std, esStickySeedKey('hotspot'), ES_HOTSPOT.label)))),
|
|
108
91
|
// In its own preset, a diamond rather than a square, and therefore its own
|
|
109
92
|
// row — appended after the eight by its `order` rather than by hand.
|
|
110
93
|
legend: {
|
package/dist/index.d.ts
CHANGED
|
@@ -11,3 +11,5 @@ export { eventStormingSeniorTool } from './toolbar/senior-tool.js';
|
|
|
11
11
|
export { EdgelessDddEventStormingSeniorButton } from './toolbar/senior-button.js';
|
|
12
12
|
export { DddEventStormingRenderViewExtension, DddEventStormingViewExtension, } from './view.js';
|
|
13
13
|
export { EVENT_STORMING_READING } from './reading.js';
|
|
14
|
+
export { AGGREGATE_SIZE } from './sticky-size.js';
|
|
15
|
+
export { EVENT_STORMING_TOOLBOX, eventStormingBoardElement, eventStormingFlowElement, eventStormingFlowStyle, eventStormingStickyElements, eventStormingStickyOpts, } from './toolbox.js';
|
package/dist/index.js
CHANGED
|
@@ -14,3 +14,6 @@ export { eventStormingSeniorTool } from './toolbar/senior-tool.js';
|
|
|
14
14
|
export { EdgelessDddEventStormingSeniorButton } from './toolbar/senior-button.js';
|
|
15
15
|
export { DddEventStormingRenderViewExtension, DddEventStormingViewExtension, } from './view.js';
|
|
16
16
|
export { EVENT_STORMING_READING } from './reading.js';
|
|
17
|
+
// The toolbar as pure builders (`docs/adr/0045`), also on `./interchange`.
|
|
18
|
+
export { AGGREGATE_SIZE } from './sticky-size.js';
|
|
19
|
+
export { EVENT_STORMING_TOOLBOX, eventStormingBoardElement, eventStormingFlowElement, eventStormingFlowStyle, eventStormingStickyElements, eventStormingStickyOpts, } from './toolbox.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `./interchange` — Event Storming with no editor behind it (ADR 0012, P3 as
|
|
3
|
+
* amended 2026-10-14): its toolbar as pure builders (`docs/adr/0045`), so a
|
|
4
|
+
* host with no editor (the Labre workspace connector, labre-mcp) places the
|
|
5
|
+
* very board, stickies, hotspots and flows a user places from the toolbar.
|
|
6
|
+
* Held by `interchange-headless.unit.spec.ts` in `packages/affine/all`, which
|
|
7
|
+
* bundles this entry and fails on any editor module in its graph.
|
|
8
|
+
*/
|
|
9
|
+
export { AGGREGATE_SIZE } from './sticky-size.js';
|
|
10
|
+
export { EVENT_STORMING_TOOLBOX, eventStormingBoardElement, eventStormingFlowElement, eventStormingFlowStyle, eventStormingStickyElements, eventStormingStickyOpts, } from './toolbox.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `./interchange` — Event Storming with no editor behind it (ADR 0012, P3 as
|
|
3
|
+
* amended 2026-10-14): its toolbar as pure builders (`docs/adr/0045`), so a
|
|
4
|
+
* host with no editor (the Labre workspace connector, labre-mcp) places the
|
|
5
|
+
* very board, stickies, hotspots and flows a user places from the toolbar.
|
|
6
|
+
* Held by `interchange-headless.unit.spec.ts` in `packages/affine/all`, which
|
|
7
|
+
* bundles this entry and fails on any editor module in its graph.
|
|
8
|
+
*/
|
|
9
|
+
export { AGGREGATE_SIZE } from './sticky-size.js';
|
|
10
|
+
export { EVENT_STORMING_TOOLBOX, eventStormingBoardElement, eventStormingFlowElement, eventStormingFlowStyle, eventStormingStickyElements, eventStormingStickyOpts, } from './toolbox.js';
|
package/dist/roles.d.ts
CHANGED
package/dist/roles.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ES_HOTSPOT, ES_STICKIES } from '@formicoidea/labre-ddd-shared';
|
|
1
|
+
import { ES_HOTSPOT, ES_STICKIES } from '@formicoidea/labre-ddd-shared/headless';
|
|
2
2
|
/** camelCase → kebab-case, the WS2 derivation. */
|
|
3
3
|
const kebab = (kind) => kind.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`);
|
|
4
4
|
/**
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The aggregate is created BIG — 160 against the standard 120.
|
|
3
|
+
*
|
|
4
|
+
* Size is half of how the notation distinguishes it: on a real wall the
|
|
5
|
+
* aggregate is the large pale sticky a run of commands lands on, and the
|
|
6
|
+
* colour ladder in `ES_STICKIES` carries the other half. Declared here rather
|
|
7
|
+
* than in the shared palette because it is a FORMAT, not a colour: the palette
|
|
8
|
+
* says which yellow, the toolbox says how big.
|
|
9
|
+
*
|
|
10
|
+
* Its own module, editor-free, so the toolbox (`toolbox.ts`, `docs/adr/0045`)
|
|
11
|
+
* builds a host's aggregate at the size the toolbar places it at; it lived in
|
|
12
|
+
* `commands.ts`, which imports the editor.
|
|
13
|
+
*/
|
|
14
|
+
export declare const AGGREGATE_SIZE = 160;
|
|
15
|
+
/** The side of a sticky of `kind` as the toolbar places it. */
|
|
16
|
+
export declare function eventStormingStickySize(kind: string): number;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { STICKY_SIZE } from '@formicoidea/labre-ddd-shared/headless';
|
|
2
|
+
/**
|
|
3
|
+
* The aggregate is created BIG — 160 against the standard 120.
|
|
4
|
+
*
|
|
5
|
+
* Size is half of how the notation distinguishes it: on a real wall the
|
|
6
|
+
* aggregate is the large pale sticky a run of commands lands on, and the
|
|
7
|
+
* colour ladder in `ES_STICKIES` carries the other half. Declared here rather
|
|
8
|
+
* than in the shared palette because it is a FORMAT, not a colour: the palette
|
|
9
|
+
* says which yellow, the toolbox says how big.
|
|
10
|
+
*
|
|
11
|
+
* Its own module, editor-free, so the toolbox (`toolbox.ts`, `docs/adr/0045`)
|
|
12
|
+
* builds a host's aggregate at the size the toolbar places it at; it lived in
|
|
13
|
+
* `commands.ts`, which imports the editor.
|
|
14
|
+
*/
|
|
15
|
+
export const AGGREGATE_SIZE = 160;
|
|
16
|
+
/** The side of a sticky of `kind` as the toolbar places it. */
|
|
17
|
+
export function eventStormingStickySize(kind) {
|
|
18
|
+
return kind === 'aggregate' ? AGGREGATE_SIZE : STICKY_SIZE;
|
|
19
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type FrameworkToolbox, type SerializedElementProps, type ToolboxPoint } from '@formicoidea/labre-core/interchange';
|
|
2
|
+
import { type StickyOpts } from '@formicoidea/labre-ddd-shared/headless';
|
|
3
|
+
import { PointStyle, StrokeStyle } from '@formicoidea/labre-core/model/headless';
|
|
4
|
+
import { type EventStormingStickyKind } from './roles.js';
|
|
5
|
+
/**
|
|
6
|
+
* What a sticky of `kind` is, as the prefab's options, its words `label`:
|
|
7
|
+
* the kind's colours, its size (the aggregate is bigger), its shape (the
|
|
8
|
+
* hotspot is a diamond) and its role, which is what makes it a domain EVENT
|
|
9
|
+
* rather than an orange square for every rule in `rules.ts`. The toolbar
|
|
10
|
+
* passes the seed in the host's language; a host with no editor its own words
|
|
11
|
+
* or the English seed.
|
|
12
|
+
*/
|
|
13
|
+
export declare function eventStormingStickyOpts(kind: EventStormingStickyKind, label: string): StickyOpts;
|
|
14
|
+
/**
|
|
15
|
+
* A sticky of `kind` whose face is at `at`, named `name` or the toolbar's
|
|
16
|
+
* English seed: the shadow, the face carrying the role and the words, and
|
|
17
|
+
* their group, last.
|
|
18
|
+
*/
|
|
19
|
+
export declare function eventStormingStickyElements(kind: EventStormingStickyKind, at: ToolboxPoint, name?: string, local?: string): SerializedElementProps[];
|
|
20
|
+
/** The board a storm is run on, at `at`. */
|
|
21
|
+
export declare function eventStormingBoardElement(at: ToolboxPoint, local?: string): SerializedElementProps;
|
|
22
|
+
/**
|
|
23
|
+
* How a flow is drawn: presentation only, the meaning is the role. A plain
|
|
24
|
+
* straight line with a rear arrowhead pointing at what FOLLOWS, which is the
|
|
25
|
+
* target: the role's verb is "leads to", so the source is what happens first.
|
|
26
|
+
*/
|
|
27
|
+
export declare function eventStormingFlowStyle(): {
|
|
28
|
+
stroke: string;
|
|
29
|
+
strokeStyle: StrokeStyle;
|
|
30
|
+
strokeWidth: number;
|
|
31
|
+
frontEndpointStyle: PointStyle;
|
|
32
|
+
rearEndpointStyle: PointStyle;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* A flow from what happens first to what follows: the connector the Flow
|
|
36
|
+
* entry arms the tool with.
|
|
37
|
+
*/
|
|
38
|
+
export declare function eventStormingFlowElement(from: string, to: string, label?: string): SerializedElementProps;
|
|
39
|
+
/** Every item of the Event Storming toolbar, in the toolbar's order. */
|
|
40
|
+
export declare const EVENT_STORMING_TOOLBOX: FrameworkToolbox;
|
package/dist/toolbox.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { backgroundSize, } from '@formicoidea/labre-core/interchange';
|
|
2
|
+
import { ES_HOTSPOT, ES_STICKIES, LABEL_COLOR, stickyElements, } from '@formicoidea/labre-ddd-shared/headless';
|
|
3
|
+
import { ConnectorMode, PointStyle, StrokeStyle, } from '@formicoidea/labre-core/model/headless';
|
|
4
|
+
import { Bound } from '@formicoidea/labre-core/global/gfx';
|
|
5
|
+
import { EVENT_STORMING_BACKGROUND } from './background.js';
|
|
6
|
+
import { eventStormingCommandsManifest } from './commands-manifest.js';
|
|
7
|
+
import { ES_ROLE, ES_STICKY_ROLE, } from './roles.js';
|
|
8
|
+
import { eventStormingStickySize } from './sticky-size.js';
|
|
9
|
+
/**
|
|
10
|
+
* The Event Storming toolbar as pure builders (`docs/adr/0045`): the board,
|
|
11
|
+
* the eight colour-coded stickies, the hotspot and the flow, with no editor
|
|
12
|
+
* behind them. A sticky is the very builder the palette's prefab writes
|
|
13
|
+
* (`stickyElements`, `@labre/affine-gfx-ddd-shared/headless`) with the options
|
|
14
|
+
* `commands.ts` passes it ({@link eventStormingStickyOpts}), and
|
|
15
|
+
* `createEventStormingBoard` and `activateEventStormingFlow` read the board
|
|
16
|
+
* and the flow's style from here, so a sticky drawn by a host and one placed
|
|
17
|
+
* from the toolbar are the same elements.
|
|
18
|
+
*/
|
|
19
|
+
/** Every flow is drawn this wide. */
|
|
20
|
+
const FLOW_STROKE_WIDTH = 2;
|
|
21
|
+
/** Each sticky kind's preset: the eight of the shared table, then the hotspot. */
|
|
22
|
+
const STICKY_PRESETS = {
|
|
23
|
+
...Object.fromEntries(ES_STICKIES.map(preset => [preset.kind, preset])),
|
|
24
|
+
hotspot: ES_HOTSPOT,
|
|
25
|
+
};
|
|
26
|
+
/** The sticky kinds in the toolbar's order: the shared table's, hotspot last. */
|
|
27
|
+
const STICKY_KINDS = [
|
|
28
|
+
...ES_STICKIES.map(preset => preset.kind),
|
|
29
|
+
'hotspot',
|
|
30
|
+
];
|
|
31
|
+
/**
|
|
32
|
+
* What a sticky of `kind` is, as the prefab's options, its words `label`:
|
|
33
|
+
* the kind's colours, its size (the aggregate is bigger), its shape (the
|
|
34
|
+
* hotspot is a diamond) and its role, which is what makes it a domain EVENT
|
|
35
|
+
* rather than an orange square for every rule in `rules.ts`. The toolbar
|
|
36
|
+
* passes the seed in the host's language; a host with no editor its own words
|
|
37
|
+
* or the English seed.
|
|
38
|
+
*/
|
|
39
|
+
export function eventStormingStickyOpts(kind, label) {
|
|
40
|
+
const { fill, text } = STICKY_PRESETS[kind];
|
|
41
|
+
return {
|
|
42
|
+
fill,
|
|
43
|
+
text,
|
|
44
|
+
label,
|
|
45
|
+
size: eventStormingStickySize(kind),
|
|
46
|
+
...(kind === 'hotspot' ? { shapeType: 'diamond' } : {}),
|
|
47
|
+
role: ES_STICKY_ROLE[kind],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** The item id of a sticky kind: its role's own slug (`external-system`…). */
|
|
51
|
+
const stickyItemId = (kind) => ES_STICKY_ROLE[kind].slice('es:'.length);
|
|
52
|
+
/**
|
|
53
|
+
* A sticky of `kind` whose face is at `at`, named `name` or the toolbar's
|
|
54
|
+
* English seed: the shadow, the face carrying the role and the words, and
|
|
55
|
+
* their group, last.
|
|
56
|
+
*/
|
|
57
|
+
export function eventStormingStickyElements(kind, at, name, local = stickyItemId(kind)) {
|
|
58
|
+
return stickyElements(at, eventStormingStickyOpts(kind, name?.trim() || STICKY_PRESETS[kind].label), local);
|
|
59
|
+
}
|
|
60
|
+
/** The board a storm is run on, at `at`. */
|
|
61
|
+
export function eventStormingBoardElement(at, local = 'board') {
|
|
62
|
+
const { width, height } = backgroundSize(EVENT_STORMING_BACKGROUND);
|
|
63
|
+
return {
|
|
64
|
+
type: EVENT_STORMING_BACKGROUND.type,
|
|
65
|
+
id: local,
|
|
66
|
+
// The board is a first-class role: rules frame stickies against
|
|
67
|
+
// `es:board`, never against the `eventStorming` element type.
|
|
68
|
+
role: EVENT_STORMING_BACKGROUND.role,
|
|
69
|
+
resizeEnabled: EVENT_STORMING_BACKGROUND.geometry.resizable,
|
|
70
|
+
xywh: new Bound(at.x, at.y, width, height).serialize(),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* How a flow is drawn: presentation only, the meaning is the role. A plain
|
|
75
|
+
* straight line with a rear arrowhead pointing at what FOLLOWS, which is the
|
|
76
|
+
* target: the role's verb is "leads to", so the source is what happens first.
|
|
77
|
+
*/
|
|
78
|
+
export function eventStormingFlowStyle() {
|
|
79
|
+
return {
|
|
80
|
+
stroke: LABEL_COLOR,
|
|
81
|
+
strokeStyle: StrokeStyle.Solid,
|
|
82
|
+
strokeWidth: FLOW_STROKE_WIDTH,
|
|
83
|
+
frontEndpointStyle: PointStyle.None,
|
|
84
|
+
rearEndpointStyle: PointStyle.Arrow,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A flow from what happens first to what follows: the connector the Flow
|
|
89
|
+
* entry arms the tool with.
|
|
90
|
+
*/
|
|
91
|
+
export function eventStormingFlowElement(from, to, label) {
|
|
92
|
+
return {
|
|
93
|
+
type: 'connector',
|
|
94
|
+
role: ES_ROLE.flow,
|
|
95
|
+
mode: ConnectorMode.Straight,
|
|
96
|
+
...eventStormingFlowStyle(),
|
|
97
|
+
source: { id: from },
|
|
98
|
+
target: { id: to },
|
|
99
|
+
...(label?.trim() ? { text: label.trim() } : {}),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** The toolbar command's label, so a host names an item as the toolbar does. */
|
|
103
|
+
function label(command) {
|
|
104
|
+
const id = `ddd-event-storming.${command}`;
|
|
105
|
+
const row = eventStormingCommandsManifest.find(r => r.id === id);
|
|
106
|
+
return {
|
|
107
|
+
labelKey: row?.labelKey ?? id,
|
|
108
|
+
labelFallback: row?.labelFallback ?? id,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const sticky = (kind) => {
|
|
112
|
+
const side = eventStormingStickySize(kind);
|
|
113
|
+
return {
|
|
114
|
+
id: stickyItemId(kind),
|
|
115
|
+
...label(`add${kind[0]?.toUpperCase()}${kind.slice(1)}`),
|
|
116
|
+
texts: ['name'],
|
|
117
|
+
size: { w: side, h: side },
|
|
118
|
+
build: (at, texts, local) => eventStormingStickyElements(kind, at, texts?.name, local),
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
const BOARD_SIZE = backgroundSize(EVENT_STORMING_BACKGROUND);
|
|
122
|
+
/** Every item of the Event Storming toolbar, in the toolbar's order. */
|
|
123
|
+
export const EVENT_STORMING_TOOLBOX = {
|
|
124
|
+
framework: 'ddd-event-storming',
|
|
125
|
+
items: [
|
|
126
|
+
{
|
|
127
|
+
id: 'board',
|
|
128
|
+
...label('addBoard'),
|
|
129
|
+
texts: [],
|
|
130
|
+
size: { w: BOARD_SIZE.width, h: BOARD_SIZE.height },
|
|
131
|
+
build: (at, _texts, local) => [eventStormingBoardElement(at, local)],
|
|
132
|
+
},
|
|
133
|
+
...STICKY_KINDS.map(sticky),
|
|
134
|
+
],
|
|
135
|
+
links: [
|
|
136
|
+
{
|
|
137
|
+
id: 'flow',
|
|
138
|
+
...label('addFlow'),
|
|
139
|
+
build: (from, to, text) => eventStormingFlowElement(from, to, text),
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formicoidea/labre-framework-ddd-event-storming",
|
|
3
3
|
"description": "Labre ddd-event-storming framework for @formicoidea/labre-core.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.60.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"author": "lajola",
|
|
@@ -25,14 +25,18 @@
|
|
|
25
25
|
"./commands-manifest": {
|
|
26
26
|
"types": "./dist/commands-manifest.d.ts",
|
|
27
27
|
"import": "./dist/commands-manifest.js"
|
|
28
|
+
},
|
|
29
|
+
"./interchange": {
|
|
30
|
+
"types": "./dist/interchange-headless.d.ts",
|
|
31
|
+
"import": "./dist/interchange-headless.js"
|
|
28
32
|
}
|
|
29
33
|
},
|
|
30
34
|
"files": [
|
|
31
35
|
"dist"
|
|
32
36
|
],
|
|
33
37
|
"dependencies": {
|
|
34
|
-
"@formicoidea/labre-core": "0.
|
|
35
|
-
"@formicoidea/labre-ddd-shared": "0.
|
|
38
|
+
"@formicoidea/labre-core": "0.60.0",
|
|
39
|
+
"@formicoidea/labre-ddd-shared": "0.60.0",
|
|
36
40
|
"lit": "^3.2.0"
|
|
37
41
|
}
|
|
38
42
|
}
|