@formicoidea/labre-framework-ddd-context-map 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.
- package/dist/actions.d.ts +38 -0
- package/dist/actions.js +84 -0
- package/dist/background.d.ts +19 -0
- package/dist/background.js +51 -0
- package/dist/commands.js +37 -61
- package/dist/descriptor.d.ts +7 -2
- package/dist/descriptor.js +5 -2
- package/dist/element-renderer.d.ts +17 -0
- package/dist/element-renderer.js +15 -0
- package/dist/element-view.d.ts +17 -0
- package/dist/element-view.js +18 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -1
- package/dist/legend.d.ts +20 -0
- package/dist/legend.js +56 -0
- package/dist/nudges.d.ts +19 -0
- package/dist/nudges.js +55 -0
- package/dist/profiles.d.ts +2 -0
- package/dist/profiles.js +73 -0
- package/dist/roles.d.ts +65 -0
- package/dist/roles.js +64 -0
- package/dist/rules.d.ts +2 -0
- package/dist/rules.js +264 -0
- package/dist/toolbar/board-config.d.ts +30 -0
- package/dist/toolbar/board-config.js +87 -0
- package/dist/toolbar/context-map-menu.d.ts +1 -1
- package/dist/toolbar/context-map-menu.js +1 -1
- package/dist/toolbar/senior-button.d.ts +1 -0
- package/dist/toolbar/senior-button.js +1 -0
- package/dist/toolbar/senior-tool.js +1 -0
- package/dist/translations.d.ts +9 -9
- package/dist/translations.js +16 -11
- package/dist/view.d.ts +17 -1
- package/dist/view.js +60 -2
- package/package.json +3 -3
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { GfxController } from '@formicoidea/labre-core/std/gfx';
|
|
2
|
+
import { type ContextMapPatternKind } from './roles.js';
|
|
3
|
+
/** Create the board at the viewport centre, select it, return to the default tool. */
|
|
4
|
+
export declare function createContextMapBoard(gfx: GfxController): void;
|
|
5
|
+
/**
|
|
6
|
+
* Activate the native connector tool, pre-styled and TYPED for one Context Map
|
|
7
|
+
* pattern. The user then drags from one bounded context to another and the
|
|
8
|
+
* endpoints attach.
|
|
9
|
+
*
|
|
10
|
+
* ## Why this replaces the old palette entry
|
|
11
|
+
*
|
|
12
|
+
* Until WS2 each pattern entry dropped a free-floating GROUP at the viewport
|
|
13
|
+
* centre: a connector between two points in mid-air, an abbreviation tag and,
|
|
14
|
+
* for the U/D patterns, two letters. It looked like the notation and said
|
|
15
|
+
* nothing — the link was attached to nothing, so no rule could read its ends,
|
|
16
|
+
* and the user still had to drag both endpoints onto the contexts by hand.
|
|
17
|
+
*
|
|
18
|
+
* The gesture now IS the statement (`docs/adr/0010`): the tool announces which
|
|
19
|
+
* way to drag (the role's `gestureHint`), the drawn connector carries the
|
|
20
|
+
* pattern's role, and the endpoints are real element references — which is what
|
|
21
|
+
* makes the whole of `rules.ts` possible.
|
|
22
|
+
*
|
|
23
|
+
* ## What the style says, and what the role says
|
|
24
|
+
*
|
|
25
|
+
* Style is presentation: `dashed` for the two "no real integration" patterns
|
|
26
|
+
* (Separate Ways, Big Ball of Mud), a rear arrowhead for the five U/D ones so
|
|
27
|
+
* the sheet still reads at a glance. Meaning is the role, and only the role: a
|
|
28
|
+
* user restyling a link never changes what it means, and a link drawn before
|
|
29
|
+
* WS2 keeps its old look and stays neutral.
|
|
30
|
+
*
|
|
31
|
+
* The abbreviation TAG is not drawn any more. A label riding on the connector is
|
|
32
|
+
* `ConnectorToolOptions.label`, which was cut from v1 — the pattern reads from
|
|
33
|
+
* the hover reveal (M2) and the toolbar until it lands.
|
|
34
|
+
*/
|
|
35
|
+
export declare function activateContextMapRelationship(gfx: GfxController, kind: ContextMapPatternKind, style: {
|
|
36
|
+
upDown: boolean;
|
|
37
|
+
dashed: boolean;
|
|
38
|
+
}): void;
|
package/dist/actions.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { backgroundSize, DefaultTool } from '@formicoidea/labre-core/blocks/surface';
|
|
2
|
+
import { ConnectorTool } from '@formicoidea/labre-core/gfx/connector';
|
|
3
|
+
import { LABEL_COLOR } from '@formicoidea/labre-ddd-shared';
|
|
4
|
+
import { ConnectorMode, PointStyle, StrokeStyle } from '@formicoidea/labre-core/model';
|
|
5
|
+
import { Bound } from '@formicoidea/labre-core/global/gfx';
|
|
6
|
+
import { CONTEXT_MAP_BACKGROUND } from './background.js';
|
|
7
|
+
import { CM_PATTERN_ROLE } from './roles.js';
|
|
8
|
+
/**
|
|
9
|
+
* Creation / activation actions for the Context Map toolbox — the BEHAVIOUR
|
|
10
|
+
* layer, depending on nothing but the {@link GfxController}.
|
|
11
|
+
*
|
|
12
|
+
* They emit no telemetry: since PF3 the single emission point is the command
|
|
13
|
+
* registry's `runCommand` (`docs/adr/0008`).
|
|
14
|
+
*/
|
|
15
|
+
const RELATIONSHIP_STROKE_WIDTH = 2;
|
|
16
|
+
/** Create the board at the viewport centre, select it, return to the default tool. */
|
|
17
|
+
export function createContextMapBoard(gfx) {
|
|
18
|
+
if (!gfx.surface)
|
|
19
|
+
return;
|
|
20
|
+
const { width, height } = backgroundSize(CONTEXT_MAP_BACKGROUND);
|
|
21
|
+
const { centerX, centerY } = gfx.viewport;
|
|
22
|
+
const id = gfx.surface.addElement({
|
|
23
|
+
type: CONTEXT_MAP_BACKGROUND.type,
|
|
24
|
+
// The board is a first-class role: rules frame contexts against
|
|
25
|
+
// `context-map:board`, never against the `contextMap` element type. The
|
|
26
|
+
// declaration owns it, so a templated board and a hand-drawn one agree.
|
|
27
|
+
role: CONTEXT_MAP_BACKGROUND.role,
|
|
28
|
+
resizeEnabled: CONTEXT_MAP_BACKGROUND.geometry.resizable,
|
|
29
|
+
xywh: new Bound(centerX - width / 2, centerY - height / 2, width, height).serialize(),
|
|
30
|
+
});
|
|
31
|
+
gfx.doc.captureSync();
|
|
32
|
+
gfx.tool.setTool(DefaultTool);
|
|
33
|
+
gfx.selection.set({ elements: [id], editing: false });
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Activate the native connector tool, pre-styled and TYPED for one Context Map
|
|
37
|
+
* pattern. The user then drags from one bounded context to another and the
|
|
38
|
+
* endpoints attach.
|
|
39
|
+
*
|
|
40
|
+
* ## Why this replaces the old palette entry
|
|
41
|
+
*
|
|
42
|
+
* Until WS2 each pattern entry dropped a free-floating GROUP at the viewport
|
|
43
|
+
* centre: a connector between two points in mid-air, an abbreviation tag and,
|
|
44
|
+
* for the U/D patterns, two letters. It looked like the notation and said
|
|
45
|
+
* nothing — the link was attached to nothing, so no rule could read its ends,
|
|
46
|
+
* and the user still had to drag both endpoints onto the contexts by hand.
|
|
47
|
+
*
|
|
48
|
+
* The gesture now IS the statement (`docs/adr/0010`): the tool announces which
|
|
49
|
+
* way to drag (the role's `gestureHint`), the drawn connector carries the
|
|
50
|
+
* pattern's role, and the endpoints are real element references — which is what
|
|
51
|
+
* makes the whole of `rules.ts` possible.
|
|
52
|
+
*
|
|
53
|
+
* ## What the style says, and what the role says
|
|
54
|
+
*
|
|
55
|
+
* Style is presentation: `dashed` for the two "no real integration" patterns
|
|
56
|
+
* (Separate Ways, Big Ball of Mud), a rear arrowhead for the five U/D ones so
|
|
57
|
+
* the sheet still reads at a glance. Meaning is the role, and only the role: a
|
|
58
|
+
* user restyling a link never changes what it means, and a link drawn before
|
|
59
|
+
* WS2 keeps its old look and stays neutral.
|
|
60
|
+
*
|
|
61
|
+
* The abbreviation TAG is not drawn any more. A label riding on the connector is
|
|
62
|
+
* `ConnectorToolOptions.label`, which was cut from v1 — the pattern reads from
|
|
63
|
+
* the hover reveal (M2) and the toolbar until it lands.
|
|
64
|
+
*/
|
|
65
|
+
export function activateContextMapRelationship(gfx, kind, style) {
|
|
66
|
+
gfx.tool.setTool(ConnectorTool, {
|
|
67
|
+
mode: ConnectorMode.Straight,
|
|
68
|
+
role: CM_PATTERN_ROLE[kind],
|
|
69
|
+
// The look rides on the activation, never through the last-props store:
|
|
70
|
+
// the plain connector tool must keep the user's own style (#144 M1).
|
|
71
|
+
style: {
|
|
72
|
+
stroke: LABEL_COLOR,
|
|
73
|
+
strokeStyle: style.dashed ? StrokeStyle.Dash : StrokeStyle.Solid,
|
|
74
|
+
strokeWidth: RELATIONSHIP_STROKE_WIDTH,
|
|
75
|
+
frontEndpointStyle: PointStyle.None,
|
|
76
|
+
// The arrow points at the DOWNSTREAM end, which is the target: the
|
|
77
|
+
// role's verb is "is upstream of", so the source is the upstream
|
|
78
|
+
// context.
|
|
79
|
+
rearEndpointStyle: style.upDown ? PointStyle.Arrow : PointStyle.None,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
// The Context Map palette stays open (native sub-menu behaviour): it only
|
|
83
|
+
// closes on re-click of the senior button, another senior tool, or Escape.
|
|
84
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { FrameworkBackgroundDef } from '@formicoidea/labre-core/blocks/surface';
|
|
2
|
+
/**
|
|
3
|
+
* The Context Map board, DECLARED (the `FrameworkBackgroundDef` primitive).
|
|
4
|
+
*
|
|
5
|
+
* The emptiest declaration in the library, and deliberately so: **no axes, no
|
|
6
|
+
* zones**. A Context Map is a graph, not a chart — a bounded context drawn top
|
|
7
|
+
* left says nothing more than one drawn bottom right, and graduating the card
|
|
8
|
+
* would invent a frame of reference the framework does not have. What the
|
|
9
|
+
* declaration is for here is the ROLE and the geometry: `context-map:board` is
|
|
10
|
+
* what a rule frames its subjects against, and it is what a per-map validation
|
|
11
|
+
* profile is written on.
|
|
12
|
+
*
|
|
13
|
+
* The palette carries the notation's two boundary colours even though nothing in
|
|
14
|
+
* this file paints them. Same precedent as the Wardley tone convention: a
|
|
15
|
+
* palette entry is a declared REFERENCE, so the day a `tone-convention` rule
|
|
16
|
+
* asks "is this bubble drawn in the map's own blue" the answer is already
|
|
17
|
+
* written down, in one place, beside the card it belongs to.
|
|
18
|
+
*/
|
|
19
|
+
export declare const CONTEXT_MAP_BACKGROUND: FrameworkBackgroundDef;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { CLOUD, CM_BUBBLE, FONT_FAMILY } from '@formicoidea/labre-ddd-shared';
|
|
2
|
+
import { CONTEXT_MAP_ROLE } from './roles.js';
|
|
3
|
+
/**
|
|
4
|
+
* The Context Map board, DECLARED (the `FrameworkBackgroundDef` primitive).
|
|
5
|
+
*
|
|
6
|
+
* The emptiest declaration in the library, and deliberately so: **no axes, no
|
|
7
|
+
* zones**. A Context Map is a graph, not a chart — a bounded context drawn top
|
|
8
|
+
* left says nothing more than one drawn bottom right, and graduating the card
|
|
9
|
+
* would invent a frame of reference the framework does not have. What the
|
|
10
|
+
* declaration is for here is the ROLE and the geometry: `context-map:board` is
|
|
11
|
+
* what a rule frames its subjects against, and it is what a per-map validation
|
|
12
|
+
* profile is written on.
|
|
13
|
+
*
|
|
14
|
+
* The palette carries the notation's two boundary colours even though nothing in
|
|
15
|
+
* this file paints them. Same precedent as the Wardley tone convention: a
|
|
16
|
+
* palette entry is a declared REFERENCE, so the day a `tone-convention` rule
|
|
17
|
+
* asks "is this bubble drawn in the map's own blue" the answer is already
|
|
18
|
+
* written down, in one place, beside the card it belongs to.
|
|
19
|
+
*/
|
|
20
|
+
export const CONTEXT_MAP_BACKGROUND = {
|
|
21
|
+
type: 'contextMap',
|
|
22
|
+
role: CONTEXT_MAP_ROLE.board,
|
|
23
|
+
geometry: {
|
|
24
|
+
// Wide and free: a context map grows sideways as contexts are found, so
|
|
25
|
+
// neither dimension is locked to the other and the handles are offered from
|
|
26
|
+
// the start — the opposite call from the Wardley map, which is a frame of
|
|
27
|
+
// reference you place things on rather than a sheet you spread out.
|
|
28
|
+
width: 1400,
|
|
29
|
+
height: 900,
|
|
30
|
+
lockAspectRatio: false,
|
|
31
|
+
resizable: true,
|
|
32
|
+
margin: { top: 24, right: 24, bottom: 24, left: 24 },
|
|
33
|
+
},
|
|
34
|
+
chrome: {
|
|
35
|
+
fontFamily: FONT_FAMILY,
|
|
36
|
+
palette: {
|
|
37
|
+
card: '#ffffff',
|
|
38
|
+
cardBorder: '#d5d9e0',
|
|
39
|
+
/** The bounded-context pill: the map's own blue. */
|
|
40
|
+
context: CM_BUBBLE.fill,
|
|
41
|
+
contextBorder: CM_BUBBLE.stroke,
|
|
42
|
+
/** The cloud / Big Ball of Mud: the map's own grey-violet. */
|
|
43
|
+
cloud: CLOUD.fill,
|
|
44
|
+
cloudBorder: CLOUD.stroke,
|
|
45
|
+
},
|
|
46
|
+
surface: {
|
|
47
|
+
fill: '@card',
|
|
48
|
+
border: { color: '@cardBorder', width: 1.5, radius: 12 },
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
package/dist/commands.js
CHANGED
|
@@ -1,60 +1,48 @@
|
|
|
1
|
-
import { addBubble, addCloud,
|
|
1
|
+
import { addBubble, addCloud, CM_RELATIONSHIPS, placeDddElement, } from '@formicoidea/labre-ddd-shared';
|
|
2
|
+
import { GfxControllerIdentifier } from '@formicoidea/labre-core/std/gfx';
|
|
2
3
|
import { svg } from 'lit';
|
|
4
|
+
import { activateContextMapRelationship, createContextMapBoard, } from './actions.js';
|
|
5
|
+
import { CONTEXT_MAP_ROLE } from './roles.js';
|
|
3
6
|
/**
|
|
4
|
-
* The Context Map palette as commands: the bounded-context bubble,
|
|
5
|
-
* the
|
|
7
|
+
* The Context Map palette as commands: the board, the bounded-context bubble,
|
|
8
|
+
* the cloud and the nine relationship patterns (`docs/adr/0008`).
|
|
9
|
+
*
|
|
10
|
+
* Two entries changed shape in WS2 and neither changed its telemetry: the
|
|
11
|
+
* bubble now carries the `context-map:context` role, and the nine patterns arm
|
|
12
|
+
* the connector tool instead of dropping a drawing.
|
|
13
|
+
*
|
|
14
|
+
* The notation legend is deliberately NOT a palette entry any more (PO recette,
|
|
15
|
+
* 27/08/2026): the ONE legend is the automatic one on the selected board's
|
|
16
|
+
* contextual toolbar (`toolbar/board-config.ts`) — the same call Core Domain
|
|
17
|
+
* Chart makes. A palette that could also drop a second, static legend was two
|
|
18
|
+
* answers to one question.
|
|
6
19
|
*/
|
|
20
|
+
const boardSwatch = svg `<svg viewBox="0 0 24 24" fill="none"><rect x="2.5" y="4.5" width="19" height="15" rx="2" fill="#ffffff" stroke="currentColor" stroke-width="1.6"/><rect x="5.5" y="8" width="6" height="3.5" rx="1.75" fill="#e6f0fa" stroke="#2f6fb0" stroke-width="1.1"/><rect x="13" y="13" width="6" height="3.5" rx="1.75" fill="#e6f0fa" stroke="#2f6fb0" stroke-width="1.1"/><path d="M11.5 10.5 L13.5 13.8" stroke="currentColor" stroke-width="1.2"/></svg>`;
|
|
7
21
|
const bubbleSwatch = svg `<svg viewBox="0 0 24 24" fill="none"><rect x="2" y="7" width="20" height="10" rx="5" fill="#e6f0fa" stroke="#2f6fb0" stroke-width="1.6"/></svg>`;
|
|
8
22
|
const cloudSwatch = svg `<svg viewBox="0 0 24 24" fill="none"><path d="M6 17 C3 17 2 14 4.5 12.5 C4 9 8 8 9.5 10 C11 6.5 16 7.5 16 11 C19 10.5 20.5 14 18 16 C18 17 16.5 17 15 17 Z" fill="#f0eef6" stroke="#6d6e71" stroke-width="1.4"/></svg>`;
|
|
9
|
-
const legendSwatch = svg `<svg viewBox="0 0 24 24" fill="none"><rect x="3" y="4" width="18" height="16" rx="2" stroke="currentColor" stroke-width="1.6"/><circle cx="7" cy="9" r="1.6" fill="currentColor"/><circle cx="7" cy="14" r="1.6" fill="currentColor"/><path d="M11 9 H18 M11 14 H18" stroke="currentColor" stroke-width="1.4"/></svg>`;
|
|
10
23
|
const relationSwatch = (dashed, arrow) => svg `<svg viewBox="0 0 24 24" fill="none"><path d="M3 12 H${arrow ? 17 : 21}" stroke="currentColor" stroke-width="2" stroke-dasharray="${dashed ? '3 3' : '0'}"/>${arrow ? svg `<path d="M15 8 L21 12 L15 16" stroke="currentColor" stroke-width="2" fill="none"/>` : ''}</svg>`;
|
|
11
|
-
/** The notation legend's sections, built from the same relationship presets. */
|
|
12
|
-
function legendSections() {
|
|
13
|
-
const patRows = (kinds) => CM_RELATIONSHIPS.filter(r => kinds.includes(r.kind)).map((r) => ({
|
|
14
|
-
swatch: 'line',
|
|
15
|
-
color: '#1f2328',
|
|
16
|
-
label: `${r.abbrev} — ${r.label}`,
|
|
17
|
-
}));
|
|
18
|
-
return [
|
|
19
|
-
{
|
|
20
|
-
title: 'Boundaries',
|
|
21
|
-
rows: [
|
|
22
|
-
{ swatch: 'square', color: CM_BUBBLE.fill, label: 'Bounded Context' },
|
|
23
|
-
{
|
|
24
|
-
swatch: 'square',
|
|
25
|
-
color: CLOUD.fill,
|
|
26
|
-
label: 'System / Big Ball of Mud',
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
title: 'Mutually dependent',
|
|
32
|
-
rows: patRows(['partnership', 'sharedKernel']),
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
title: 'Upstream → Downstream (U/D)',
|
|
36
|
-
rows: patRows([
|
|
37
|
-
'customerSupplier',
|
|
38
|
-
'conformist',
|
|
39
|
-
'acl',
|
|
40
|
-
'ohs',
|
|
41
|
-
'publishedLanguage',
|
|
42
|
-
]),
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
title: 'Separate / no integration',
|
|
46
|
-
rows: patRows(['separateWays', 'bbom']),
|
|
47
|
-
},
|
|
48
|
-
];
|
|
49
|
-
}
|
|
50
24
|
const SPECS = [
|
|
25
|
+
{
|
|
26
|
+
id: 'addBoard',
|
|
27
|
+
label: 'Context Map board',
|
|
28
|
+
iconKey: 'ddd-context-map.board',
|
|
29
|
+
// A NEW telemetry value, and the only one in this file: every other entry
|
|
30
|
+
// below keeps the `element` string it has emitted since ADR 0008.
|
|
31
|
+
element: 'board',
|
|
32
|
+
icon: boardSwatch,
|
|
33
|
+
run: std => createContextMapBoard(std.get(GfxControllerIdentifier)),
|
|
34
|
+
},
|
|
51
35
|
{
|
|
52
36
|
id: 'addBoundedContext',
|
|
53
37
|
label: 'Bounded Context',
|
|
54
38
|
iconKey: 'ddd-context-map.bubble',
|
|
55
39
|
element: 'bounded-context',
|
|
56
40
|
icon: bubbleSwatch,
|
|
57
|
-
run: std => placeDddElement(std, (surface, cx, cy) =>
|
|
41
|
+
run: std => placeDddElement(std, (surface, cx, cy) =>
|
|
42
|
+
// The role is what makes a bubble a bounded CONTEXT rather than a blue
|
|
43
|
+
// pill: every rule in `rules.ts` reads it, and a pill drawn before WS2
|
|
44
|
+
// carries none and is never evaluated (promesse #71).
|
|
45
|
+
addBubble(surface, cx, cy, 'Bounded Context', CONTEXT_MAP_ROLE.context)),
|
|
58
46
|
},
|
|
59
47
|
{
|
|
60
48
|
id: 'addCloud',
|
|
@@ -70,24 +58,12 @@ const SPECS = [
|
|
|
70
58
|
iconKey: `ddd-context-map.relationship.${preset.kind}`,
|
|
71
59
|
element: `relationship:${preset.kind}`,
|
|
72
60
|
icon: relationSwatch(preset.dashed, preset.upDown),
|
|
73
|
-
|
|
61
|
+
// No longer a placement: the nine patterns arm the connector tool and the
|
|
62
|
+
// user DRAWS the relation between two contexts. See
|
|
63
|
+
// `activateContextMapRelationship` for why the free-floating group had to
|
|
64
|
+
// go. The telemetry `element` value is untouched.
|
|
65
|
+
run: std => activateContextMapRelationship(std.get(GfxControllerIdentifier), preset.kind, { upDown: preset.upDown, dashed: preset.dashed }),
|
|
74
66
|
})),
|
|
75
|
-
{
|
|
76
|
-
id: 'addLegend',
|
|
77
|
-
label: 'Legend',
|
|
78
|
-
iconKey: 'ddd-context-map.legend',
|
|
79
|
-
// Deliberately NOT `kind: 'legend'`: this palette entry has always emitted
|
|
80
|
-
// `FrameworkElementAdded` with element `'legend'`, and ADR 0008's
|
|
81
|
-
// no-analytics-breakage rule outranks the taxonomy tidy-up. Promoting it
|
|
82
|
-
// to `FrameworkLegendCreated` is a telemetry change, not a refactor.
|
|
83
|
-
element: 'legend',
|
|
84
|
-
icon: legendSwatch,
|
|
85
|
-
run: std => placeDddElement(std, (surface, cx, cy) => addLegend(surface, std, cx - 140, cy - 210, {
|
|
86
|
-
title: 'Légende',
|
|
87
|
-
sections: legendSections(),
|
|
88
|
-
width: 290,
|
|
89
|
-
})),
|
|
90
|
-
},
|
|
91
67
|
];
|
|
92
68
|
export const contextMapCommands = SPECS.map((spec, order) => ({
|
|
93
69
|
id: `ddd-context-map.${spec.id}`,
|
package/dist/descriptor.d.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { DddContextMapViewExtension } from './view.js';
|
|
1
|
+
import { DddContextMapRenderViewExtension, DddContextMapViewExtension } from './view.js';
|
|
2
2
|
/** Host wiring for the ddd-context-map framework. */
|
|
3
3
|
export declare const dddContextMapFramework: {
|
|
4
4
|
readonly flag: "ddd-context-map";
|
|
5
5
|
readonly telemetryKey: "context-map";
|
|
6
|
-
readonly
|
|
6
|
+
readonly extensions: readonly [{
|
|
7
|
+
readonly viewExtension: typeof DddContextMapRenderViewExtension;
|
|
8
|
+
}, {
|
|
9
|
+
readonly flag: "ddd-context-map";
|
|
10
|
+
readonly viewExtension: typeof DddContextMapViewExtension;
|
|
11
|
+
}];
|
|
7
12
|
};
|
package/dist/descriptor.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { DddContextMapViewExtension } from './view.js';
|
|
1
|
+
import { DddContextMapRenderViewExtension, DddContextMapViewExtension } from './view.js';
|
|
2
2
|
/** Host wiring for the ddd-context-map framework. */
|
|
3
3
|
export const dddContextMapFramework = {
|
|
4
4
|
flag: 'ddd-context-map',
|
|
5
5
|
telemetryKey: 'context-map',
|
|
6
|
-
|
|
6
|
+
extensions: [
|
|
7
|
+
{ viewExtension: DddContextMapRenderViewExtension },
|
|
8
|
+
{ flag: 'ddd-context-map', viewExtension: DddContextMapViewExtension },
|
|
9
|
+
],
|
|
7
10
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ElementRenderer } from '@formicoidea/labre-core/blocks/surface';
|
|
2
|
+
import type { ContextMapBoardElementModel } from '@formicoidea/labre-core/model';
|
|
3
|
+
/**
|
|
4
|
+
* Canvas renderer for the Context Map board.
|
|
5
|
+
*
|
|
6
|
+
* There is no Context Map drawing code: the board is an INSTANTIATION of the
|
|
7
|
+
* framework-background primitive, configured by the `CONTEXT_MAP_BACKGROUND`
|
|
8
|
+
* declaration — which, having no axes and no zones, paints the primitive's own
|
|
9
|
+
* default: a white card with a hairline border.
|
|
10
|
+
*
|
|
11
|
+
* Exported as a function as well as an extension so a test can drive it with a
|
|
12
|
+
* canvas stub.
|
|
13
|
+
*/
|
|
14
|
+
export declare const contextMap: ElementRenderer<ContextMapBoardElementModel>;
|
|
15
|
+
export declare const ContextMapRendererExtension: import("@formicoidea/labre-core/store").ExtensionType & {
|
|
16
|
+
identifier: import("@formicoidea/labre-core/_pkgs/global/di").ServiceIdentifier<ElementRenderer<ContextMapBoardElementModel>>;
|
|
17
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createFrameworkBackgroundRenderer, ElementRendererExtension, } from '@formicoidea/labre-core/blocks/surface';
|
|
2
|
+
import { CONTEXT_MAP_BACKGROUND } from './background.js';
|
|
3
|
+
/**
|
|
4
|
+
* Canvas renderer for the Context Map board.
|
|
5
|
+
*
|
|
6
|
+
* There is no Context Map drawing code: the board is an INSTANTIATION of the
|
|
7
|
+
* framework-background primitive, configured by the `CONTEXT_MAP_BACKGROUND`
|
|
8
|
+
* declaration — which, having no axes and no zones, paints the primitive's own
|
|
9
|
+
* default: a white card with a hairline border.
|
|
10
|
+
*
|
|
11
|
+
* Exported as a function as well as an extension so a test can drive it with a
|
|
12
|
+
* canvas stub.
|
|
13
|
+
*/
|
|
14
|
+
export const contextMap = createFrameworkBackgroundRenderer(CONTEXT_MAP_BACKGROUND);
|
|
15
|
+
export const ContextMapRendererExtension = ElementRendererExtension(CONTEXT_MAP_BACKGROUND.type, contextMap);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ContextMapBoardElementModel } from '@formicoidea/labre-core/model';
|
|
2
|
+
import { GfxElementModelView } from '@formicoidea/labre-core/std/gfx';
|
|
3
|
+
/**
|
|
4
|
+
* View for the Context Map board. Registering it ensures `gfx.view.get(model)`
|
|
5
|
+
* returns a view (required so move / select interactions work).
|
|
6
|
+
*
|
|
7
|
+
* No double-click label editor, unlike the Wardley map: the declaration carries
|
|
8
|
+
* no text at all, so there is nothing on the card to hit-test.
|
|
9
|
+
*/
|
|
10
|
+
export declare class ContextMapView extends GfxElementModelView<ContextMapBoardElementModel> {
|
|
11
|
+
static type: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resize gating, from the primitive: the handles follow `resizeEnabled`, which
|
|
15
|
+
* the declaration seeds to `true` — a board is a sheet you spread out.
|
|
16
|
+
*/
|
|
17
|
+
export declare const ContextMapInteraction: import("@formicoidea/labre-core/store").ExtensionType;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FrameworkBackgroundInteractionExtension } from '@formicoidea/labre-core/blocks/surface';
|
|
2
|
+
import { GfxElementModelView } from '@formicoidea/labre-core/std/gfx';
|
|
3
|
+
import { CONTEXT_MAP_BACKGROUND } from './background.js';
|
|
4
|
+
/**
|
|
5
|
+
* View for the Context Map board. Registering it ensures `gfx.view.get(model)`
|
|
6
|
+
* returns a view (required so move / select interactions work).
|
|
7
|
+
*
|
|
8
|
+
* No double-click label editor, unlike the Wardley map: the declaration carries
|
|
9
|
+
* no text at all, so there is nothing on the card to hit-test.
|
|
10
|
+
*/
|
|
11
|
+
export class ContextMapView extends GfxElementModelView {
|
|
12
|
+
static { this.type = 'contextMap'; }
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Resize gating, from the primitive: the handles follow `resizeEnabled`, which
|
|
16
|
+
* the declaration seeds to `true` — a board is a sheet you spread out.
|
|
17
|
+
*/
|
|
18
|
+
export const ContextMapInteraction = FrameworkBackgroundInteractionExtension(CONTEXT_MAP_BACKGROUND);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
export { contextMapCommandIcons, contextMapCommands } from './commands.js';
|
|
2
|
+
export { CONTEXT_MAP_BACKGROUND } from './background.js';
|
|
3
|
+
export { CONTEXT_MAP_NUDGES } from './nudges.js';
|
|
4
|
+
export { CONTEXT_MAP_PROFILES } from './profiles.js';
|
|
5
|
+
export { CM_PATTERN_ROLE, CONTEXT_MAP_ROLE, CONTEXT_MAP_ROLES, type ContextMapPatternKind, type ContextMapRoleId, } from './roles.js';
|
|
6
|
+
export { CONTEXT_MAP_RULES } from './rules.js';
|
|
2
7
|
export { contextMapTranslationEntries } from './translations.js';
|
|
3
8
|
export { contextMapTemplateCategory } from './templates.js';
|
|
4
9
|
export { contextMapSeniorTool } from './toolbar/senior-tool.js';
|
|
5
10
|
export { EdgelessDddContextMapSeniorButton } from './toolbar/senior-button.js';
|
|
6
|
-
export { DddContextMapViewExtension } from './view.js';
|
|
11
|
+
export { DddContextMapRenderViewExtension, DddContextMapViewExtension, } from './view.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
export { contextMapCommandIcons, contextMapCommands } from './commands.js';
|
|
2
|
+
export { CONTEXT_MAP_BACKGROUND } from './background.js';
|
|
3
|
+
export { CONTEXT_MAP_NUDGES } from './nudges.js';
|
|
4
|
+
export { CONTEXT_MAP_PROFILES } from './profiles.js';
|
|
5
|
+
export { CM_PATTERN_ROLE, CONTEXT_MAP_ROLE, CONTEXT_MAP_ROLES, } from './roles.js';
|
|
6
|
+
export { CONTEXT_MAP_RULES } from './rules.js';
|
|
2
7
|
export { contextMapTranslationEntries } from './translations.js';
|
|
3
8
|
export { contextMapTemplateCategory } from './templates.js';
|
|
4
9
|
export { contextMapSeniorTool } from './toolbar/senior-tool.js';
|
|
5
10
|
export { EdgelessDddContextMapSeniorButton } from './toolbar/senior-button.js';
|
|
6
|
-
export { DddContextMapViewExtension } from './view.js';
|
|
11
|
+
export { DddContextMapRenderViewExtension, DddContextMapViewExtension, } from './view.js';
|
package/dist/legend.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type AutoLegendSpec } from '@formicoidea/labre-ddd-shared';
|
|
2
|
+
/**
|
|
3
|
+
* What the Context Map board's automatic legend can say — a TABLE, and nothing
|
|
4
|
+
* else: the scan, the placement and the box are `createAutoLegend`'s job.
|
|
5
|
+
*
|
|
6
|
+
* Every row is DERIVED from the presets the palette itself draws from
|
|
7
|
+
* ({@link CM_RELATIONSHIPS}, {@link CM_BUBBLE}) and from the role vocabulary's
|
|
8
|
+
* own labels, never restated. A tenth pattern added to `CM_RELATIONSHIPS` gets
|
|
9
|
+
* its legend row here with no edit, the same way it gets its role.
|
|
10
|
+
*
|
|
11
|
+
* ## What is missing, and why
|
|
12
|
+
*
|
|
13
|
+
* The **cloud** (the "System / Big Ball of Mud" blob) carries no role: it is
|
|
14
|
+
* created neutral by `commands.ts`, deliberately — the endpoint grammar treats a
|
|
15
|
+
* relationship drawn onto a cloud as a sketch and stays silent on it. Detection
|
|
16
|
+
* is by role and only by role, so the automatic legend cannot list the cloud and
|
|
17
|
+
* does not pretend to. The palette's static Legend entry still documents it, and
|
|
18
|
+
* the day the cloud earns a role its row lands here in one line.
|
|
19
|
+
*/
|
|
20
|
+
export declare const CONTEXT_MAP_AUTO_LEGEND: AutoLegendSpec;
|
package/dist/legend.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { CM_BUBBLE, CM_RELATIONSHIPS, LABEL_COLOR, roleLabel, } from '@formicoidea/labre-ddd-shared';
|
|
2
|
+
import { CM_PATTERN_ROLE, CONTEXT_MAP_ROLE, CONTEXT_MAP_ROLES } from './roles.js';
|
|
3
|
+
/**
|
|
4
|
+
* What the Context Map board's automatic legend can say — a TABLE, and nothing
|
|
5
|
+
* else: the scan, the placement and the box are `createAutoLegend`'s job.
|
|
6
|
+
*
|
|
7
|
+
* Every row is DERIVED from the presets the palette itself draws from
|
|
8
|
+
* ({@link CM_RELATIONSHIPS}, {@link CM_BUBBLE}) and from the role vocabulary's
|
|
9
|
+
* own labels, never restated. A tenth pattern added to `CM_RELATIONSHIPS` gets
|
|
10
|
+
* its legend row here with no edit, the same way it gets its role.
|
|
11
|
+
*
|
|
12
|
+
* ## What is missing, and why
|
|
13
|
+
*
|
|
14
|
+
* The **cloud** (the "System / Big Ball of Mud" blob) carries no role: it is
|
|
15
|
+
* created neutral by `commands.ts`, deliberately — the endpoint grammar treats a
|
|
16
|
+
* relationship drawn onto a cloud as a sketch and stays silent on it. Detection
|
|
17
|
+
* is by role and only by role, so the automatic legend cannot list the cloud and
|
|
18
|
+
* does not pretend to. The palette's static Legend entry still documents it, and
|
|
19
|
+
* the day the cloud earns a role its row lands here in one line.
|
|
20
|
+
*/
|
|
21
|
+
export const CONTEXT_MAP_AUTO_LEGEND = {
|
|
22
|
+
title: 'Legend',
|
|
23
|
+
width: 290,
|
|
24
|
+
roles: CONTEXT_MAP_ROLES,
|
|
25
|
+
sections: [
|
|
26
|
+
{
|
|
27
|
+
title: 'Boundaries',
|
|
28
|
+
entries: [
|
|
29
|
+
{
|
|
30
|
+
role: CONTEXT_MAP_ROLE.context,
|
|
31
|
+
row: {
|
|
32
|
+
swatch: 'square',
|
|
33
|
+
color: CM_BUBBLE.fill,
|
|
34
|
+
label: roleLabel(CONTEXT_MAP_ROLES, CONTEXT_MAP_ROLE.context),
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
title: 'Relationships',
|
|
41
|
+
// One entry per PATTERN, not one for `context-map:relationship`: a legend
|
|
42
|
+
// that said "Relationship" would document nothing a reader could use. The
|
|
43
|
+
// dashed sample marks the two "no real integration" patterns, exactly as
|
|
44
|
+
// the board draws them.
|
|
45
|
+
entries: CM_RELATIONSHIPS.map(preset => ({
|
|
46
|
+
role: CM_PATTERN_ROLE[preset.kind],
|
|
47
|
+
row: {
|
|
48
|
+
swatch: 'line',
|
|
49
|
+
color: LABEL_COLOR,
|
|
50
|
+
dashed: preset.dashed,
|
|
51
|
+
label: `${preset.abbrev} — ${preset.label}`,
|
|
52
|
+
},
|
|
53
|
+
})),
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
};
|
package/dist/nudges.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { QualityNudge } from '@formicoidea/labre-core/blocks/surface';
|
|
2
|
+
/**
|
|
3
|
+
* Context Mapping **map quality** — the checklist (WS2, level 2).
|
|
4
|
+
*
|
|
5
|
+
* `./rules.ts` is level 1: deterministic, decidable, real time. This file is
|
|
6
|
+
* everything a context map needs that no algorithm can decide. The split is the
|
|
7
|
+
* taxonomy's whole point — ticking is assuming, never verifying.
|
|
8
|
+
*
|
|
9
|
+
* Every one of the four is about whether a PATTERN WAS CHOSEN rather than
|
|
10
|
+
* defaulted to. That is the failure mode of context mapping in practice: the
|
|
11
|
+
* team draws nine links because there are nine integrations, picks the arrow
|
|
12
|
+
* that looks right, and ships a map that records the current wiring instead of
|
|
13
|
+
* the relationships. Nothing on the canvas can tell those two maps apart.
|
|
14
|
+
*
|
|
15
|
+
* Registered from the flag-gated `DddContextMapViewExtension`: a checklist is
|
|
16
|
+
* tooling. Switching the flag off takes it away and leaves the ticks written on
|
|
17
|
+
* the board, unread, until it comes back.
|
|
18
|
+
*/
|
|
19
|
+
export declare const CONTEXT_MAP_NUDGES: readonly QualityNudge[];
|
package/dist/nudges.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Mapping **map quality** — the checklist (WS2, level 2).
|
|
3
|
+
*
|
|
4
|
+
* `./rules.ts` is level 1: deterministic, decidable, real time. This file is
|
|
5
|
+
* everything a context map needs that no algorithm can decide. The split is the
|
|
6
|
+
* taxonomy's whole point — ticking is assuming, never verifying.
|
|
7
|
+
*
|
|
8
|
+
* Every one of the four is about whether a PATTERN WAS CHOSEN rather than
|
|
9
|
+
* defaulted to. That is the failure mode of context mapping in practice: the
|
|
10
|
+
* team draws nine links because there are nine integrations, picks the arrow
|
|
11
|
+
* that looks right, and ships a map that records the current wiring instead of
|
|
12
|
+
* the relationships. Nothing on the canvas can tell those two maps apart.
|
|
13
|
+
*
|
|
14
|
+
* Registered from the flag-gated `DddContextMapViewExtension`: a checklist is
|
|
15
|
+
* tooling. Switching the flag off takes it away and leaves the ticks written on
|
|
16
|
+
* the board, unread, until it comes back.
|
|
17
|
+
*/
|
|
18
|
+
export const CONTEXT_MAP_NUDGES = [
|
|
19
|
+
{
|
|
20
|
+
id: 'context-map.q1-pattern-discussed',
|
|
21
|
+
framework: 'ddd-context-map',
|
|
22
|
+
labelKey: 'com.labre.ddd-context-map.quality.pattern-discussed',
|
|
23
|
+
fallback: 'Every relationship carries a justified, discussed pattern — not the one that was easiest to draw.',
|
|
24
|
+
order: 1,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'context-map.q2-separate-ways-documented',
|
|
28
|
+
framework: 'ddd-context-map',
|
|
29
|
+
labelKey: 'com.labre.ddd-context-map.quality.separate-ways',
|
|
30
|
+
fallback: 'Separate Ways are documented: it is written down why there is no integration.',
|
|
31
|
+
order: 2,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
/**
|
|
35
|
+
* The rule this nudge replaces. "Every downstream of a Big Ball of Mud is
|
|
36
|
+
* protected" is decidable in principle — walk the edges out of the cloud and
|
|
37
|
+
* look for an ACL — and undecidable in practice on THIS canvas: the cloud
|
|
38
|
+
* carries no role (a v1 cut), so there is nothing for a rule to walk from,
|
|
39
|
+
* and a shape somebody drew a mess with is not a claim that it IS one.
|
|
40
|
+
* Level 2 is the honest home for it until the cloud has a role.
|
|
41
|
+
*/
|
|
42
|
+
id: 'context-map.q3-bbom-protected',
|
|
43
|
+
framework: 'ddd-context-map',
|
|
44
|
+
labelKey: 'com.labre.ddd-context-map.quality.bbom-protected',
|
|
45
|
+
fallback: 'Every downstream of a Big Ball of Mud is protected by an Anticorruption Layer.',
|
|
46
|
+
order: 3,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 'context-map.q4-legend',
|
|
50
|
+
framework: 'ddd-context-map',
|
|
51
|
+
labelKey: 'com.labre.ddd-context-map.quality.legend',
|
|
52
|
+
fallback: 'The map has a legend: a reader who does not know the notation can read it.',
|
|
53
|
+
order: 4,
|
|
54
|
+
},
|
|
55
|
+
];
|