@formicoidea/labre-framework-wardley 0.40.0 → 0.41.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 +29 -0
- package/dist/actions.js +61 -38
- package/dist/import.d.ts +28 -0
- package/dist/import.js +66 -7
- package/dist/legend.d.ts +20 -2
- package/dist/legend.js +118 -29
- package/dist/morph.d.ts +12 -2
- package/dist/morph.js +25 -9
- package/dist/natures.js +19 -0
- package/dist/presets.d.ts +21 -0
- package/dist/presets.js +21 -0
- package/dist/templates/index.d.ts +9 -0
- package/dist/templates/index.js +20 -3
- package/dist/templates/maps.d.ts +94 -0
- package/dist/templates/maps.js +148 -27
- package/dist/toolbar/config.d.ts +2 -0
- package/dist/toolbar/config.js +46 -7
- package/dist/toolbar/node-config.d.ts +26 -2
- package/dist/toolbar/node-config.js +100 -9
- package/dist/translations.js +80 -1
- package/package.json +2 -2
package/dist/morph.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { morphLabel, } from '@formicoidea/labre-core/blocks/surface';
|
|
2
2
|
import { ConnectorElementModel, GroupElementModel, TextElementModel, WardleyNodeElementModel, } from '@formicoidea/labre-core/model';
|
|
3
|
+
import { translateKey } from '@formicoidea/labre-core/shared/services';
|
|
3
4
|
import { wardleyCommandIcons, wardleyCommands } from './commands.js';
|
|
4
|
-
import { wardleyCanonicalBox, wardleyHandleBox, wardleyHandleProps, wardleyMarketDotBoxes, wardleyMarketDotProps, wardleyMarketLinkPairs, wardleyMarketLinkProps, WARDLEY_NODE_LABEL, wardleyMorphClears, wardleyMorphProps, } from './presets.js';
|
|
5
|
+
import { wardleyCanonicalBox, wardleyHandleBox, wardleyHandleProps, wardleyMarketDotBoxes, wardleyMarketDotProps, wardleyMarketLinkPairs, wardleyMarketLinkProps, WARDLEY_NODE_LABEL, wardleyMorphClears, wardleyMorphProps, wardleyNodeLabelKey, } from './presets.js';
|
|
5
6
|
import { WARDLEY_ROLE } from './roles.js';
|
|
6
7
|
/**
|
|
7
8
|
* What a Wardley artefact may BECOME — the declaration behind the "Change type"
|
|
@@ -148,11 +149,26 @@ export function wardleyNodeOfComponent(model) {
|
|
|
148
149
|
*
|
|
149
150
|
* Pure and total over every string: the input is a canvas text element somebody
|
|
150
151
|
* may have typed anything into.
|
|
152
|
+
*
|
|
153
|
+
* `std` is OPTIONAL: "untouched" means equal to the English prompt OR to the
|
|
154
|
+
* host's own resolved wording for `from`'s kind, and the target's prompt is
|
|
155
|
+
* likewise resolved through the host when one is given — mirroring
|
|
156
|
+
* `c4MorphedTypeLine`'s fix for the identical class of gap. With no `std`
|
|
157
|
+
* this behaves exactly as it always has (English only). The morph toolbar's
|
|
158
|
+
* `afterMorph` callback (`MorphSpec`, `packages/affine/blocks/surface`) now
|
|
159
|
+
* hands its callee the inserting editor's `std`, so `rewriteLabel` below
|
|
160
|
+
* passes it straight through.
|
|
151
161
|
*/
|
|
152
|
-
export function wardleyMorphedLabel(from, to, rawText) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
162
|
+
export function wardleyMorphedLabel(from, to, rawText, std) {
|
|
163
|
+
const text = (rawText ?? '').trim();
|
|
164
|
+
const fromPrompt = std
|
|
165
|
+
? translateKey(std, wardleyNodeLabelKey(from), WARDLEY_NODE_LABEL[from])
|
|
166
|
+
: WARDLEY_NODE_LABEL[from];
|
|
167
|
+
if (text !== WARDLEY_NODE_LABEL[from] && text !== fromPrompt)
|
|
168
|
+
return null;
|
|
169
|
+
return std
|
|
170
|
+
? translateKey(std, wardleyNodeLabelKey(to), WARDLEY_NODE_LABEL[to])
|
|
171
|
+
: WARDLEY_NODE_LABEL[to];
|
|
156
172
|
}
|
|
157
173
|
/** The centre of an element, from the box it currently occupies. */
|
|
158
174
|
function centreOf(model) {
|
|
@@ -309,12 +325,12 @@ function removeHandle(group, carrier) {
|
|
|
309
325
|
* inside the caller's `captureSync`, so the rewrite is part of the same single
|
|
310
326
|
* ctrl+z as the kind that made it necessary.
|
|
311
327
|
*/
|
|
312
|
-
function rewriteLabel(group, from, to) {
|
|
328
|
+
function rewriteLabel(group, from, to, std) {
|
|
313
329
|
const label = labelOfComposite(group);
|
|
314
330
|
if (!label || label.isLocked())
|
|
315
331
|
return;
|
|
316
332
|
const text = label.text.toString().trim();
|
|
317
|
-
const next = wardleyMorphedLabel(from, to, text);
|
|
333
|
+
const next = wardleyMorphedLabel(from, to, text, std);
|
|
318
334
|
if (next === null || next === text)
|
|
319
335
|
return;
|
|
320
336
|
label.surface.store.transact(() => {
|
|
@@ -349,7 +365,7 @@ function rewriteLabel(group, from, to) {
|
|
|
349
365
|
* LEAVING comes apart before the one it is arriving at is built, so a
|
|
350
366
|
* market → pipeline never has three dots and a handle at once.
|
|
351
367
|
*/
|
|
352
|
-
export function wardleyMorphComposite(selected, from, to) {
|
|
368
|
+
export function wardleyMorphComposite(selected, from, to, std) {
|
|
353
369
|
if (!(selected instanceof GroupElementModel))
|
|
354
370
|
return;
|
|
355
371
|
const carrier = wardleyNodeOfComponent(selected);
|
|
@@ -367,7 +383,7 @@ export function wardleyMorphComposite(selected, from, to) {
|
|
|
367
383
|
addMarketGlyph(selected, cx, cy);
|
|
368
384
|
if (to === 'pipeline')
|
|
369
385
|
addHandle(selected, carrier, cx, cy);
|
|
370
|
-
rewriteLabel(selected, from, to);
|
|
386
|
+
rewriteLabel(selected, from, to, std);
|
|
371
387
|
}
|
|
372
388
|
/**
|
|
373
389
|
* Wardley's morph declaration, handed to the generic `morphToolbarConfig`.
|
package/dist/natures.js
CHANGED
|
@@ -86,11 +86,14 @@ export const WARDLEY_TAG_DEFS = {
|
|
|
86
86
|
packId: 'wardley-core',
|
|
87
87
|
framework: 'wardley',
|
|
88
88
|
label: 'Wardley',
|
|
89
|
+
labelKey: 'com.labre.wardley.tag-pack.label',
|
|
89
90
|
tags: [
|
|
90
91
|
{
|
|
91
92
|
id: WARDLEY_NATURE_TAG_ID,
|
|
92
93
|
label: 'Nature',
|
|
94
|
+
labelKey: 'com.labre.wardley.tag.nature',
|
|
93
95
|
description: 'What kind of thing this component is: an activity, data, a practice or knowledge.',
|
|
96
|
+
descriptionKey: 'com.labre.wardley.tag.nature.description',
|
|
94
97
|
cardinality: 'single',
|
|
95
98
|
appliesTo: [WARDLEY_ROLE.component],
|
|
96
99
|
// No `order`, on either tag of this pack: an absent order sorts by SEED
|
|
@@ -103,29 +106,39 @@ export const WARDLEY_TAG_DEFS = {
|
|
|
103
106
|
{
|
|
104
107
|
id: WARDLEY_NATURE.activity,
|
|
105
108
|
label: 'Activity',
|
|
109
|
+
labelKey: 'com.labre.wardley.tag.nature.activity',
|
|
106
110
|
description: 'Something that is DONE — a step, a service, a process.',
|
|
111
|
+
descriptionKey: 'com.labre.wardley.tag.nature.activity.description',
|
|
107
112
|
},
|
|
108
113
|
{
|
|
109
114
|
id: WARDLEY_NATURE.data,
|
|
110
115
|
label: 'Data',
|
|
116
|
+
labelKey: 'com.labre.wardley.tag.nature.data',
|
|
111
117
|
description: 'Something that is RECORDED — a dataset, a register.',
|
|
118
|
+
descriptionKey: 'com.labre.wardley.tag.nature.data.description',
|
|
112
119
|
},
|
|
113
120
|
{
|
|
114
121
|
id: WARDLEY_NATURE.practice,
|
|
115
122
|
label: 'Practice',
|
|
123
|
+
labelKey: 'com.labre.wardley.tag.nature.practice',
|
|
116
124
|
description: 'A way of doing — a method, a convention, an operating model.',
|
|
125
|
+
descriptionKey: 'com.labre.wardley.tag.nature.practice.description',
|
|
117
126
|
},
|
|
118
127
|
{
|
|
119
128
|
id: WARDLEY_NATURE.knowledge,
|
|
120
129
|
label: 'Knowledge',
|
|
130
|
+
labelKey: 'com.labre.wardley.tag.nature.knowledge',
|
|
121
131
|
description: 'Something that is KNOWN — a model, a theory, a rule.',
|
|
132
|
+
descriptionKey: 'com.labre.wardley.tag.nature.knowledge.description',
|
|
122
133
|
},
|
|
123
134
|
],
|
|
124
135
|
},
|
|
125
136
|
{
|
|
126
137
|
id: WARDLEY_COMPETITION_TAG_ID,
|
|
127
138
|
label: 'Competition',
|
|
139
|
+
labelKey: 'com.labre.wardley.tag.competition',
|
|
128
140
|
description: "Which of Porter's forces this glyph marks: relative competition, a struggle for survival, or a struggle to establish.",
|
|
141
|
+
descriptionKey: 'com.labre.wardley.tag.competition.description',
|
|
129
142
|
cardinality: 'single',
|
|
130
143
|
appliesTo: [WARDLEY_ROLE.porter],
|
|
131
144
|
values: [
|
|
@@ -135,17 +148,23 @@ export const WARDLEY_TAG_DEFS = {
|
|
|
135
148
|
// shows: a reader picking a value here is choosing what the circle
|
|
136
149
|
// will say, not filling in a form about it.
|
|
137
150
|
label: 'Relative competition (R)',
|
|
151
|
+
labelKey: 'com.labre.wardley.tag.competition.relative',
|
|
138
152
|
description: 'Established players competing against one another on a market that exists.',
|
|
153
|
+
descriptionKey: 'com.labre.wardley.tag.competition.relative.description',
|
|
139
154
|
},
|
|
140
155
|
{
|
|
141
156
|
id: WARDLEY_COMPETITION.struggle,
|
|
142
157
|
label: 'Struggle for survival (L)',
|
|
158
|
+
labelKey: 'com.labre.wardley.tag.competition.struggle',
|
|
143
159
|
description: 'Pressure on a player to stay in a market it is already in.',
|
|
160
|
+
descriptionKey: 'com.labre.wardley.tag.competition.struggle.description',
|
|
144
161
|
},
|
|
145
162
|
{
|
|
146
163
|
id: WARDLEY_COMPETITION.establish,
|
|
147
164
|
label: 'Struggle to establish (E)',
|
|
165
|
+
labelKey: 'com.labre.wardley.tag.competition.establish',
|
|
148
166
|
description: 'Pressure on a newcomer trying to get into a market.',
|
|
167
|
+
descriptionKey: 'com.labre.wardley.tag.competition.establish.description',
|
|
149
168
|
},
|
|
150
169
|
],
|
|
151
170
|
},
|
package/dist/presets.d.ts
CHANGED
|
@@ -72,6 +72,27 @@ export type WardleyLabelledKind = Exclude<WardleyArtefactKind, 'porter' | 'area'
|
|
|
72
72
|
* still carries, and the only string a morph is ever allowed to rewrite.
|
|
73
73
|
*/
|
|
74
74
|
export declare const WARDLEY_NODE_LABEL: Record<WardleyLabelledKind, string>;
|
|
75
|
+
/**
|
|
76
|
+
* The i18n key {@link WARDLEY_NODE_LABEL} is the English default of —
|
|
77
|
+
* resolved at placement (`createWardleyNode` / `createWardleyPipeline` /
|
|
78
|
+
* `createWardleyMarket`), never afterwards. "Pipeline" is the PO's glossary
|
|
79
|
+
* term for Wardley: the French proposal IS the English word.
|
|
80
|
+
*
|
|
81
|
+
* ## The morph's placeholder detection, translated
|
|
82
|
+
*
|
|
83
|
+
* `wardleyMorphedLabel` (`morph.ts`) decides whether to refresh an artefact's
|
|
84
|
+
* name across a morph, and accepts an OPTIONAL `std`: given one, it
|
|
85
|
+
* recognises the stored text as "untouched" whether it reads the English
|
|
86
|
+
* prompt or the host's own resolved wording, and resolves the TARGET kind's
|
|
87
|
+
* prompt through the host too (the same fix `c4MorphedTypeLine` carries,
|
|
88
|
+
* `gfx/c4/src/type-line.ts`). `MorphSpec.afterMorph`
|
|
89
|
+
* (`packages/affine/blocks/surface`) now hands its callee the morph
|
|
90
|
+
* toolbar's own `std`, so `rewriteLabel` passes it straight through: on a
|
|
91
|
+
* host running a French catalogue, morphing an untouched TRANSLATED node
|
|
92
|
+
* rewrites its name to the target kind's own translated prompt, exactly as a
|
|
93
|
+
* standalone playground already rewrote the English one.
|
|
94
|
+
*/
|
|
95
|
+
export declare const wardleyNodeLabelKey: (kind: WardleyLabelledKind) => string;
|
|
75
96
|
/** A box centred on a point — how every Wardley creation site places a node. */
|
|
76
97
|
export declare function wardleyCenteredBox(cx: number, cy: number, w: number, h: number): string;
|
|
77
98
|
/** The canonical box of one kind, centred where the artefact already stands. */
|
package/dist/presets.js
CHANGED
|
@@ -65,6 +65,27 @@ export const WARDLEY_NODE_LABEL = {
|
|
|
65
65
|
accelerator: ACCELERATOR_LABEL,
|
|
66
66
|
decelerator: DECELERATOR_LABEL,
|
|
67
67
|
};
|
|
68
|
+
/**
|
|
69
|
+
* The i18n key {@link WARDLEY_NODE_LABEL} is the English default of —
|
|
70
|
+
* resolved at placement (`createWardleyNode` / `createWardleyPipeline` /
|
|
71
|
+
* `createWardleyMarket`), never afterwards. "Pipeline" is the PO's glossary
|
|
72
|
+
* term for Wardley: the French proposal IS the English word.
|
|
73
|
+
*
|
|
74
|
+
* ## The morph's placeholder detection, translated
|
|
75
|
+
*
|
|
76
|
+
* `wardleyMorphedLabel` (`morph.ts`) decides whether to refresh an artefact's
|
|
77
|
+
* name across a morph, and accepts an OPTIONAL `std`: given one, it
|
|
78
|
+
* recognises the stored text as "untouched" whether it reads the English
|
|
79
|
+
* prompt or the host's own resolved wording, and resolves the TARGET kind's
|
|
80
|
+
* prompt through the host too (the same fix `c4MorphedTypeLine` carries,
|
|
81
|
+
* `gfx/c4/src/type-line.ts`). `MorphSpec.afterMorph`
|
|
82
|
+
* (`packages/affine/blocks/surface`) now hands its callee the morph
|
|
83
|
+
* toolbar's own `std`, so `rewriteLabel` passes it straight through: on a
|
|
84
|
+
* host running a French catalogue, morphing an untouched TRANSLATED node
|
|
85
|
+
* rewrites its name to the target kind's own translated prompt, exactly as a
|
|
86
|
+
* standalone playground already rewrote the English one.
|
|
87
|
+
*/
|
|
88
|
+
export const wardleyNodeLabelKey = (kind) => `com.labre.wardley.seed.${kind}`;
|
|
68
89
|
/**
|
|
69
90
|
* The fill a kind is born with. White for every circle that means "a thing on
|
|
70
91
|
* the value chain"; the method's grey is the one that carries meaning — it
|
|
@@ -1,2 +1,11 @@
|
|
|
1
1
|
import { type TemplateCategory } from '@formicoidea/labre-core/gfx/template';
|
|
2
|
+
import type { ChromeWording } from '@formicoidea/labre-core/shared/services';
|
|
3
|
+
/**
|
|
4
|
+
* The two hand-drawn palette swatches' own tile names (`Template.nameKey`):
|
|
5
|
+
* neither derives from a command, since `linkTool` / `evolutionArrow`
|
|
6
|
+
* activate a tool rather than draw anything (see `tpl` below and its
|
|
7
|
+
* docstring).
|
|
8
|
+
*/
|
|
9
|
+
export declare const WARDLEY_TEMPLATE_NAME_LINK: ChromeWording;
|
|
10
|
+
export declare const WARDLEY_TEMPLATE_NAME_EVOLUTION_ARROW: ChromeWording;
|
|
2
11
|
export declare const wardleyTemplateCategory: TemplateCategory;
|
package/dist/templates/index.js
CHANGED
|
@@ -73,12 +73,27 @@ const arrowPreview = (rightwards) => `<svg ${ATTRS} fill="none"><path d="${right
|
|
|
73
73
|
: 'M103 32 H55 V23 L32 40 L55 57 V48 H103 Z'}" fill="#bfbfbf" stroke="${NODE_STROKE}" stroke-width="1.8" stroke-linejoin="round"/></svg>`;
|
|
74
74
|
/** The zone, in its Peace wash — the pair differs on the outline and on nothing else. */
|
|
75
75
|
const areaPreview = (outline) => `<svg ${ATTRS} fill="none">${outline}</svg>`;
|
|
76
|
+
/**
|
|
77
|
+
* The two hand-drawn palette swatches' own tile names (`Template.nameKey`):
|
|
78
|
+
* neither derives from a command, since `linkTool` / `evolutionArrow`
|
|
79
|
+
* activate a tool rather than draw anything (see `tpl` below and its
|
|
80
|
+
* docstring).
|
|
81
|
+
*/
|
|
82
|
+
export const WARDLEY_TEMPLATE_NAME_LINK = [
|
|
83
|
+
'com.labre.wardley.template.link',
|
|
84
|
+
'Link',
|
|
85
|
+
];
|
|
86
|
+
export const WARDLEY_TEMPLATE_NAME_EVOLUTION_ARROW = [
|
|
87
|
+
'com.labre.wardley.template.evolution-arrow',
|
|
88
|
+
'Evolution arrow',
|
|
89
|
+
];
|
|
76
90
|
/** A hand-composed template — what is left once the artefacts are derived. */
|
|
77
|
-
function tpl(name, preview, elements) {
|
|
91
|
+
function tpl(name, preview, elements, nameKey) {
|
|
78
92
|
return {
|
|
79
93
|
name,
|
|
80
94
|
type: 'template',
|
|
81
95
|
preview,
|
|
96
|
+
nameKey,
|
|
82
97
|
content: makeTemplateSnapshot(elements, name),
|
|
83
98
|
};
|
|
84
99
|
}
|
|
@@ -99,6 +114,8 @@ function areaTemplate(id, preview) {
|
|
|
99
114
|
}
|
|
100
115
|
export const wardleyTemplateCategory = {
|
|
101
116
|
name: 'Wardley',
|
|
117
|
+
// Reuses the senior button's own key — see `TemplateCategory.nameKey`.
|
|
118
|
+
nameKey: 'com.labre.framework.wardley',
|
|
102
119
|
templates: [
|
|
103
120
|
...wardleyMaps,
|
|
104
121
|
templateFromCommand(byId('wardley.addBackground'), bgPreview(), 'Map background'),
|
|
@@ -126,10 +143,10 @@ export const wardleyTemplateCategory = {
|
|
|
126
143
|
// artefact to record — the user draws it.
|
|
127
144
|
tpl('Link', `<svg ${ATTRS} fill="none"><path d="M24 40 H110" stroke="${LINK_GREY}" stroke-width="2.4"/></svg>`, {
|
|
128
145
|
a: connect({ position: [0, 0] }, { position: [160, 0] }, { typed: false }),
|
|
129
|
-
}),
|
|
146
|
+
}, WARDLEY_TEMPLATE_NAME_LINK[0]),
|
|
130
147
|
tpl('Evolution arrow', `<svg ${ATTRS} fill="none"><path d="M24 40 H100" stroke="${WARDLEY_RED}" stroke-width="2.4" stroke-dasharray="6 4"/><path d="M98 33 L112 40 L98 47 Z" fill="${WARDLEY_RED}"/></svg>`, {
|
|
131
148
|
a: connect({ position: [0, 0] }, { position: [160, 0] }, { evolution: true, typed: false }),
|
|
132
|
-
}),
|
|
149
|
+
}, WARDLEY_TEMPLATE_NAME_EVOLUTION_ARROW[0]),
|
|
133
150
|
areaTemplate('wardley.addAreaRect', areaPreview('<rect x="24" y="16" width="87" height="48" rx="2" fill="#c6dbfc" fill-opacity="0.25" stroke="#5b9cf6" stroke-width="1.5"/>')),
|
|
134
151
|
areaTemplate('wardley.addAreaPolygon', areaPreview('<path d="M67 12 L110 43 L94 68 H40 L24 43 Z" fill="#c6dbfc" fill-opacity="0.25" stroke="#5b9cf6" stroke-width="1.5" stroke-linejoin="round"/>')),
|
|
135
152
|
],
|
package/dist/templates/maps.d.ts
CHANGED
|
@@ -1,2 +1,96 @@
|
|
|
1
1
|
import { type Template } from '@formicoidea/labre-core/gfx/template';
|
|
2
|
+
import { type ChromeWording } from '@formicoidea/labre-core/shared/services';
|
|
3
|
+
/**
|
|
4
|
+
* The seeds the two worked maps write — declared once so the builders below
|
|
5
|
+
* and the manifest (`../translations.ts`) read the very same fallback, never
|
|
6
|
+
* a restated literal. `com.labre.wardley.example.<map>.<slug>`, per
|
|
7
|
+
* `docs/adr/0016`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const TEA_SHOP_SEED: {
|
|
10
|
+
readonly title: {
|
|
11
|
+
readonly key: "com.labre.wardley.example.tea-shop.title";
|
|
12
|
+
readonly fallback: "Tea Shop";
|
|
13
|
+
};
|
|
14
|
+
readonly annotations: {
|
|
15
|
+
readonly key: "com.labre.wardley.example.tea-shop.annotations";
|
|
16
|
+
readonly fallback: "Annotations:\n1. Standardising power lets kettles evolve faster\n2. Hot water is obvious and well known";
|
|
17
|
+
};
|
|
18
|
+
readonly business: {
|
|
19
|
+
readonly key: "com.labre.wardley.example.tea-shop.business";
|
|
20
|
+
readonly fallback: "Business";
|
|
21
|
+
};
|
|
22
|
+
readonly public: {
|
|
23
|
+
readonly key: "com.labre.wardley.example.tea-shop.public";
|
|
24
|
+
readonly fallback: "Public";
|
|
25
|
+
};
|
|
26
|
+
readonly cupOfTea: {
|
|
27
|
+
readonly key: "com.labre.wardley.example.tea-shop.cup-of-tea";
|
|
28
|
+
readonly fallback: "Cup of Tea";
|
|
29
|
+
};
|
|
30
|
+
readonly cup: {
|
|
31
|
+
readonly key: "com.labre.wardley.example.tea-shop.cup";
|
|
32
|
+
readonly fallback: "Cup";
|
|
33
|
+
};
|
|
34
|
+
readonly tea: {
|
|
35
|
+
readonly key: "com.labre.wardley.example.tea-shop.tea";
|
|
36
|
+
readonly fallback: "Tea";
|
|
37
|
+
};
|
|
38
|
+
readonly hotWater: {
|
|
39
|
+
readonly key: "com.labre.wardley.example.tea-shop.hot-water";
|
|
40
|
+
readonly fallback: "Hot Water";
|
|
41
|
+
};
|
|
42
|
+
readonly water: {
|
|
43
|
+
readonly key: "com.labre.wardley.example.tea-shop.water";
|
|
44
|
+
readonly fallback: "Water";
|
|
45
|
+
};
|
|
46
|
+
readonly kettle: {
|
|
47
|
+
readonly key: "com.labre.wardley.example.tea-shop.kettle";
|
|
48
|
+
readonly fallback: "Kettle";
|
|
49
|
+
};
|
|
50
|
+
readonly electricKettle: {
|
|
51
|
+
readonly key: "com.labre.wardley.example.tea-shop.electric-kettle";
|
|
52
|
+
readonly fallback: "Electric Kettle";
|
|
53
|
+
};
|
|
54
|
+
readonly power: {
|
|
55
|
+
readonly key: "com.labre.wardley.example.tea-shop.power";
|
|
56
|
+
readonly fallback: "Power";
|
|
57
|
+
};
|
|
58
|
+
readonly limitedBy: {
|
|
59
|
+
readonly key: "com.labre.wardley.example.tea-shop.limited-by";
|
|
60
|
+
readonly fallback: "limited by";
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
export declare const KODAK_INERTIA_SEED: {
|
|
64
|
+
readonly title: {
|
|
65
|
+
readonly key: "com.labre.wardley.example.kodak-inertia.title";
|
|
66
|
+
readonly fallback: "Wardley map of Kodak's 2005 inertia to digital";
|
|
67
|
+
};
|
|
68
|
+
readonly user: {
|
|
69
|
+
readonly key: "com.labre.wardley.example.kodak-inertia.user";
|
|
70
|
+
readonly fallback: "User";
|
|
71
|
+
};
|
|
72
|
+
readonly captureAMoment: {
|
|
73
|
+
readonly key: "com.labre.wardley.example.kodak-inertia.capture-a-moment";
|
|
74
|
+
readonly fallback: "Capture a moment";
|
|
75
|
+
};
|
|
76
|
+
readonly filmCamera: {
|
|
77
|
+
readonly key: "com.labre.wardley.example.kodak-inertia.film-camera";
|
|
78
|
+
readonly fallback: "Film camera";
|
|
79
|
+
};
|
|
80
|
+
readonly digitalCamera: {
|
|
81
|
+
readonly key: "com.labre.wardley.example.kodak-inertia.digital-camera";
|
|
82
|
+
readonly fallback: "Digital camera";
|
|
83
|
+
};
|
|
84
|
+
readonly photographicFilm: {
|
|
85
|
+
readonly key: "com.labre.wardley.example.kodak-inertia.photographic-film";
|
|
86
|
+
readonly fallback: "Photographic film";
|
|
87
|
+
};
|
|
88
|
+
readonly digitalStorage: {
|
|
89
|
+
readonly key: "com.labre.wardley.example.kodak-inertia.digital-storage";
|
|
90
|
+
readonly fallback: "Digital storage";
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
/** The two worked maps' own tile names (`Template.nameKey`). */
|
|
94
|
+
export declare const WARDLEY_TEMPLATE_NAME_TEA_SHOP: ChromeWording;
|
|
95
|
+
export declare const WARDLEY_TEMPLATE_NAME_KODAK_INERTIA: ChromeWording;
|
|
2
96
|
export declare const wardleyMaps: Template[];
|
package/dist/templates/maps.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { makeTemplateSnapshot, surfaceText, surfaceYMap, } from '@formicoidea/labre-core/gfx/template';
|
|
2
2
|
import { ConnectorMode, FontFamily, PointStyle, ShapeStyle, StrokeStyle, TextAlign, } from '@formicoidea/labre-core/model';
|
|
3
|
+
import { translateKey, } from '@formicoidea/labre-core/shared/services';
|
|
3
4
|
import { COLORS } from '../consts.js';
|
|
4
5
|
import { INERTIA_COLOR, LINK_GREY, LINK_STROKE_WIDTH, NODE_FILL, NODE_SIZE, NODE_STROKE, WARDLEY_RED, } from '../node/consts.js';
|
|
5
6
|
import { backgroundPlot, backgroundZoneBoundaries, } from '@formicoidea/labre-core/blocks/surface';
|
|
@@ -217,14 +218,119 @@ function title(str) {
|
|
|
217
218
|
}
|
|
218
219
|
const ATTRS = 'width="100%" height="100%" viewBox="0 0 135 80" xmlns="http://www.w3.org/2000/svg"';
|
|
219
220
|
const mapPreview = (extra) => `<svg ${ATTRS} fill="none"><path d="M22 12 V64 H120" stroke="${COLORS.axis}" stroke-width="2"/>${extra}</svg>`;
|
|
220
|
-
|
|
221
|
+
/**
|
|
222
|
+
* The seeds the two worked maps write — declared once so the builders below
|
|
223
|
+
* and the manifest (`../translations.ts`) read the very same fallback, never
|
|
224
|
+
* a restated literal. `com.labre.wardley.example.<map>.<slug>`, per
|
|
225
|
+
* `docs/adr/0016`.
|
|
226
|
+
*/
|
|
227
|
+
export const TEA_SHOP_SEED = {
|
|
228
|
+
title: {
|
|
229
|
+
key: 'com.labre.wardley.example.tea-shop.title',
|
|
230
|
+
fallback: 'Tea Shop',
|
|
231
|
+
},
|
|
232
|
+
annotations: {
|
|
233
|
+
key: 'com.labre.wardley.example.tea-shop.annotations',
|
|
234
|
+
fallback: 'Annotations:\n1. Standardising power lets kettles evolve faster\n2. Hot water is obvious and well known',
|
|
235
|
+
},
|
|
236
|
+
business: {
|
|
237
|
+
key: 'com.labre.wardley.example.tea-shop.business',
|
|
238
|
+
fallback: 'Business',
|
|
239
|
+
},
|
|
240
|
+
public: {
|
|
241
|
+
key: 'com.labre.wardley.example.tea-shop.public',
|
|
242
|
+
fallback: 'Public',
|
|
243
|
+
},
|
|
244
|
+
cupOfTea: {
|
|
245
|
+
key: 'com.labre.wardley.example.tea-shop.cup-of-tea',
|
|
246
|
+
fallback: 'Cup of Tea',
|
|
247
|
+
},
|
|
248
|
+
cup: { key: 'com.labre.wardley.example.tea-shop.cup', fallback: 'Cup' },
|
|
249
|
+
tea: { key: 'com.labre.wardley.example.tea-shop.tea', fallback: 'Tea' },
|
|
250
|
+
hotWater: {
|
|
251
|
+
key: 'com.labre.wardley.example.tea-shop.hot-water',
|
|
252
|
+
fallback: 'Hot Water',
|
|
253
|
+
},
|
|
254
|
+
water: { key: 'com.labre.wardley.example.tea-shop.water', fallback: 'Water' },
|
|
255
|
+
kettle: {
|
|
256
|
+
key: 'com.labre.wardley.example.tea-shop.kettle',
|
|
257
|
+
fallback: 'Kettle',
|
|
258
|
+
},
|
|
259
|
+
electricKettle: {
|
|
260
|
+
key: 'com.labre.wardley.example.tea-shop.electric-kettle',
|
|
261
|
+
fallback: 'Electric Kettle',
|
|
262
|
+
},
|
|
263
|
+
power: { key: 'com.labre.wardley.example.tea-shop.power', fallback: 'Power' },
|
|
264
|
+
limitedBy: {
|
|
265
|
+
key: 'com.labre.wardley.example.tea-shop.limited-by',
|
|
266
|
+
fallback: 'limited by',
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
export const KODAK_INERTIA_SEED = {
|
|
270
|
+
title: {
|
|
271
|
+
key: 'com.labre.wardley.example.kodak-inertia.title',
|
|
272
|
+
fallback: "Wardley map of Kodak's 2005 inertia to digital",
|
|
273
|
+
},
|
|
274
|
+
user: {
|
|
275
|
+
key: 'com.labre.wardley.example.kodak-inertia.user',
|
|
276
|
+
fallback: 'User',
|
|
277
|
+
},
|
|
278
|
+
captureAMoment: {
|
|
279
|
+
key: 'com.labre.wardley.example.kodak-inertia.capture-a-moment',
|
|
280
|
+
fallback: 'Capture a moment',
|
|
281
|
+
},
|
|
282
|
+
filmCamera: {
|
|
283
|
+
key: 'com.labre.wardley.example.kodak-inertia.film-camera',
|
|
284
|
+
fallback: 'Film camera',
|
|
285
|
+
},
|
|
286
|
+
digitalCamera: {
|
|
287
|
+
key: 'com.labre.wardley.example.kodak-inertia.digital-camera',
|
|
288
|
+
fallback: 'Digital camera',
|
|
289
|
+
},
|
|
290
|
+
photographicFilm: {
|
|
291
|
+
key: 'com.labre.wardley.example.kodak-inertia.photographic-film',
|
|
292
|
+
fallback: 'Photographic film',
|
|
293
|
+
},
|
|
294
|
+
digitalStorage: {
|
|
295
|
+
key: 'com.labre.wardley.example.kodak-inertia.digital-storage',
|
|
296
|
+
fallback: 'Digital storage',
|
|
297
|
+
},
|
|
298
|
+
};
|
|
299
|
+
/**
|
|
300
|
+
* One seed's resolved text — the host's catalogue when `std` is a real
|
|
301
|
+
* inserting editor, the English fallback when building the module's own
|
|
302
|
+
* `content` (no editor exists yet at that point).
|
|
303
|
+
*/
|
|
304
|
+
function seedText(std, def) {
|
|
305
|
+
return std ? translateKey(std, def.key, def.fallback) : def.fallback;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* A shipped map — what is left once the artefacts are derived.
|
|
309
|
+
*
|
|
310
|
+
* `build` takes the OPTIONAL inserting editor: called with none, at module
|
|
311
|
+
* load, for the English `content`; called again with the real `std` as
|
|
312
|
+
* {@link Template.localize}, so the two builds read the very same layout and
|
|
313
|
+
* differ only in the words a seed resolves to (`docs/adr/0016`).
|
|
314
|
+
*/
|
|
315
|
+
function tpl(name, preview, build, nameKey) {
|
|
221
316
|
return {
|
|
222
317
|
name,
|
|
223
318
|
type: 'template',
|
|
224
319
|
preview,
|
|
225
|
-
|
|
320
|
+
nameKey,
|
|
321
|
+
content: makeTemplateSnapshot(build(), name),
|
|
322
|
+
localize: std => makeTemplateSnapshot(build(std), name),
|
|
226
323
|
};
|
|
227
324
|
}
|
|
325
|
+
/** The two worked maps' own tile names (`Template.nameKey`). */
|
|
326
|
+
export const WARDLEY_TEMPLATE_NAME_TEA_SHOP = [
|
|
327
|
+
'com.labre.wardley.template.tea-shop',
|
|
328
|
+
'Tea Shop',
|
|
329
|
+
];
|
|
330
|
+
export const WARDLEY_TEMPLATE_NAME_KODAK_INERTIA = [
|
|
331
|
+
'com.labre.wardley.template.kodak-inertia',
|
|
332
|
+
'Kodak inertia',
|
|
333
|
+
];
|
|
228
334
|
function ann(e, v) {
|
|
229
335
|
const cx = ex(e);
|
|
230
336
|
const cy = vy(v);
|
|
@@ -254,48 +360,56 @@ function annTxt(e, v, n) {
|
|
|
254
360
|
};
|
|
255
361
|
}
|
|
256
362
|
// ── Tea Shop (the canonical map) ──────────────────────────────────────
|
|
257
|
-
function teaShop() {
|
|
363
|
+
function teaShop(std) {
|
|
364
|
+
const s = (def) => seedText(std, def);
|
|
258
365
|
return {
|
|
259
366
|
bg: bg(),
|
|
260
|
-
title: title(
|
|
367
|
+
title: title(s(TEA_SHOP_SEED.title)),
|
|
261
368
|
annBox: panel(120, 200, 420, 64),
|
|
262
|
-
annText: freeText(132, 208, 400,
|
|
369
|
+
annText: freeText(132, 208, 400, s(TEA_SHOP_SEED.annotations), 13),
|
|
263
370
|
business: stake(0.62, 0.93),
|
|
264
|
-
businessL: lbl(0.62, 0.93,
|
|
371
|
+
businessL: lbl(0.62, 0.93, s(TEA_SHOP_SEED.business), {
|
|
265
372
|
align: 'center',
|
|
266
373
|
dy: -28,
|
|
267
374
|
w: 120,
|
|
268
375
|
}),
|
|
269
376
|
businessG: pair('business', 'businessL'),
|
|
270
377
|
public: stake(0.78, 0.93),
|
|
271
|
-
publicL: lbl(0.78, 0.93,
|
|
378
|
+
publicL: lbl(0.78, 0.93, s(TEA_SHOP_SEED.public), {
|
|
379
|
+
align: 'center',
|
|
380
|
+
dy: -28,
|
|
381
|
+
w: 120,
|
|
382
|
+
}),
|
|
272
383
|
publicG: pair('public', 'publicL'),
|
|
273
384
|
cupOfTea: comp(0.62, 0.74),
|
|
274
|
-
cupOfTeaL: lbl(0.62, 0.74,
|
|
385
|
+
cupOfTeaL: lbl(0.62, 0.74, s(TEA_SHOP_SEED.cupOfTea), { align: 'right' }),
|
|
275
386
|
cupOfTeaG: pair('cupOfTea', 'cupOfTeaL'),
|
|
276
387
|
cup: comp(0.8, 0.7),
|
|
277
|
-
cupL: lbl(0.8, 0.7,
|
|
388
|
+
cupL: lbl(0.8, 0.7, s(TEA_SHOP_SEED.cup)),
|
|
278
389
|
cupG: pair('cup', 'cupL'),
|
|
279
390
|
tea: comp(0.83, 0.6),
|
|
280
|
-
teaL: lbl(0.83, 0.6,
|
|
391
|
+
teaL: lbl(0.83, 0.6, s(TEA_SHOP_SEED.tea)),
|
|
281
392
|
teaG: pair('tea', 'teaL'),
|
|
282
393
|
hotWater: comp(0.8, 0.47),
|
|
283
|
-
hotWaterL: lbl(0.8, 0.47,
|
|
394
|
+
hotWaterL: lbl(0.8, 0.47, s(TEA_SHOP_SEED.hotWater)),
|
|
284
395
|
hotWaterG: pair('hotWater', 'hotWaterL'),
|
|
285
396
|
water: comp(0.81, 0.34),
|
|
286
|
-
waterL: lbl(0.81, 0.34,
|
|
397
|
+
waterL: lbl(0.81, 0.34, s(TEA_SHOP_SEED.water)),
|
|
287
398
|
waterG: pair('water', 'waterL'),
|
|
288
399
|
kettle: comp(0.36, 0.38),
|
|
289
|
-
kettleL: lbl(0.36, 0.38,
|
|
400
|
+
kettleL: lbl(0.36, 0.38, s(TEA_SHOP_SEED.kettle), {
|
|
401
|
+
align: 'right',
|
|
402
|
+
dy: 6,
|
|
403
|
+
}),
|
|
290
404
|
kettleG: pair('kettle', 'kettleL'),
|
|
291
405
|
electric: future(0.56, 0.38),
|
|
292
|
-
electricL: lbl(0.56, 0.38,
|
|
406
|
+
electricL: lbl(0.56, 0.38, s(TEA_SHOP_SEED.electricKettle)),
|
|
293
407
|
electricG: pair('electric', 'electricL'),
|
|
294
408
|
power: comp(0.7, 0.1),
|
|
295
|
-
powerL: lbl(0.7, 0.1,
|
|
409
|
+
powerL: lbl(0.7, 0.1, s(TEA_SHOP_SEED.power), { align: 'right', dy: 6 }),
|
|
296
410
|
powerG: pair('power', 'powerL'),
|
|
297
411
|
powerFut: future(0.88, 0.1),
|
|
298
|
-
powerFutL: lbl(0.88, 0.1,
|
|
412
|
+
powerFutL: lbl(0.88, 0.1, s(TEA_SHOP_SEED.power)),
|
|
299
413
|
powerFutG: pair('powerFut', 'powerFutL'),
|
|
300
414
|
// ABOVE the link it annotates, not across it. Written on the line it reads
|
|
301
415
|
// as a label nobody can read — which is the finding W3 raises, and it was
|
|
@@ -303,7 +417,7 @@ function teaShop() {
|
|
|
303
417
|
//
|
|
304
418
|
// NEUTRAL: it is a remark about a LINK, not the name of an artefact, so it
|
|
305
419
|
// travels with nothing and nothing measures it (see `LblOpts.neutral`).
|
|
306
|
-
limitedBy: lbl(0.56, 0.43,
|
|
420
|
+
limitedBy: lbl(0.56, 0.43, s(TEA_SHOP_SEED.limitedBy), {
|
|
307
421
|
align: 'center',
|
|
308
422
|
w: 120,
|
|
309
423
|
size: 13,
|
|
@@ -327,7 +441,8 @@ function teaShop() {
|
|
|
327
441
|
};
|
|
328
442
|
}
|
|
329
443
|
// ── Kodak inertia (2005) ──────────────────────────────────────────────
|
|
330
|
-
function kodak() {
|
|
444
|
+
function kodak(std) {
|
|
445
|
+
const s = (def) => seedText(std, def);
|
|
331
446
|
// The future dependency `capture → storage` is the movement Kodak resisted,
|
|
332
447
|
// and the inertia bar belongs where that dependency crosses into commodity —
|
|
333
448
|
// the boundary the capability refused to cross. It used to sit 105 units away
|
|
@@ -341,30 +456,36 @@ function kodak() {
|
|
|
341
456
|
const [barE, barV] = crossing(CAPTURE, STORAGE, 2);
|
|
342
457
|
return {
|
|
343
458
|
bg: bg(),
|
|
344
|
-
title: title(
|
|
459
|
+
title: title(s(KODAK_INERTIA_SEED.title)),
|
|
345
460
|
user: stake(0.54, 0.92),
|
|
346
|
-
userL: lbl(0.54, 0.92,
|
|
461
|
+
userL: lbl(0.54, 0.92, s(KODAK_INERTIA_SEED.user)),
|
|
347
462
|
userG: pair('user', 'userL'),
|
|
348
463
|
capture: dot(CAPTURE[0], CAPTURE[1], 3),
|
|
349
464
|
// To the LEFT, like the other two capability names: to the right of this
|
|
350
465
|
// node runs the future dependency towards digital storage, and a name
|
|
351
466
|
// written across the line that carries the whole argument is exactly the
|
|
352
467
|
// case W3 exists for.
|
|
353
|
-
captureL: lbl(CAPTURE[0], CAPTURE[1],
|
|
468
|
+
captureL: lbl(CAPTURE[0], CAPTURE[1], s(KODAK_INERTIA_SEED.captureAMoment), {
|
|
354
469
|
align: 'right',
|
|
355
470
|
}),
|
|
356
471
|
captureG: pair('capture', 'captureL'),
|
|
357
472
|
film: comp(0.52, 0.62),
|
|
358
|
-
filmL: lbl(0.52, 0.62,
|
|
473
|
+
filmL: lbl(0.52, 0.62, s(KODAK_INERTIA_SEED.filmCamera), {
|
|
474
|
+
align: 'right',
|
|
475
|
+
}),
|
|
359
476
|
filmG: pair('film', 'filmL'),
|
|
360
477
|
digital: future(0.74, 0.62),
|
|
361
|
-
digitalL: lbl(0.74, 0.62,
|
|
478
|
+
digitalL: lbl(0.74, 0.62, s(KODAK_INERTIA_SEED.digitalCamera), {
|
|
479
|
+
color: WARDLEY_RED,
|
|
480
|
+
}),
|
|
362
481
|
digitalG: pair('digital', 'digitalL'),
|
|
363
482
|
roll: comp(0.52, 0.4),
|
|
364
|
-
rollL: lbl(0.52, 0.4,
|
|
483
|
+
rollL: lbl(0.52, 0.4, s(KODAK_INERTIA_SEED.photographicFilm), {
|
|
484
|
+
align: 'right',
|
|
485
|
+
}),
|
|
365
486
|
rollG: pair('roll', 'rollL'),
|
|
366
487
|
storage: future(STORAGE[0], STORAGE[1]),
|
|
367
|
-
storageL: lbl(STORAGE[0], STORAGE[1],
|
|
488
|
+
storageL: lbl(STORAGE[0], STORAGE[1], s(KODAK_INERTIA_SEED.digitalStorage), {
|
|
368
489
|
color: WARDLEY_RED,
|
|
369
490
|
}),
|
|
370
491
|
storageG: pair('storage', 'storageL'),
|
|
@@ -378,6 +499,6 @@ function kodak() {
|
|
|
378
499
|
};
|
|
379
500
|
}
|
|
380
501
|
export const wardleyMaps = [
|
|
381
|
-
tpl('Tea Shop', mapPreview(`<circle cx="78" cy="24" r="3" fill="${NODE_FILL}" stroke="${NODE_STROKE}"/><circle cx="50" cy="44" r="3" fill="${NODE_FILL}" stroke="${NODE_STROKE}"/><circle cx="86" cy="40" r="3" fill="${NODE_FILL}" stroke="${NODE_STROKE}"/><circle cx="92" cy="58" r="3" fill="${NODE_FILL}" stroke="${NODE_STROKE}"/><path d="M78 24 L50 44 M78 24 L86 40 L92 58" stroke="${LINK_GREY}"/><path d="M50 44 h22" stroke="${WARDLEY_RED}" stroke-dasharray="3 2"/>`), teaShop
|
|
382
|
-
tpl('Kodak inertia', mapPreview(`<circle cx="56" cy="22" r="3" fill="${NODE_FILL}" stroke="${NODE_STROKE}"/><circle cx="54" cy="40" r="3" fill="${NODE_FILL}" stroke="${NODE_STROKE}"/><circle cx="86" cy="40" r="3" fill="${NODE_FILL}" stroke="${WARDLEY_RED}"/><rect x="76" y="35" width="2.5" height="11" fill="${INERTIA_COLOR}"/><path d="M57 40 h17" stroke="${WARDLEY_RED}" stroke-dasharray="3 2"/>`), kodak
|
|
502
|
+
tpl('Tea Shop', mapPreview(`<circle cx="78" cy="24" r="3" fill="${NODE_FILL}" stroke="${NODE_STROKE}"/><circle cx="50" cy="44" r="3" fill="${NODE_FILL}" stroke="${NODE_STROKE}"/><circle cx="86" cy="40" r="3" fill="${NODE_FILL}" stroke="${NODE_STROKE}"/><circle cx="92" cy="58" r="3" fill="${NODE_FILL}" stroke="${NODE_STROKE}"/><path d="M78 24 L50 44 M78 24 L86 40 L92 58" stroke="${LINK_GREY}"/><path d="M50 44 h22" stroke="${WARDLEY_RED}" stroke-dasharray="3 2"/>`), teaShop, WARDLEY_TEMPLATE_NAME_TEA_SHOP[0]),
|
|
503
|
+
tpl('Kodak inertia', mapPreview(`<circle cx="56" cy="22" r="3" fill="${NODE_FILL}" stroke="${NODE_STROKE}"/><circle cx="54" cy="40" r="3" fill="${NODE_FILL}" stroke="${NODE_STROKE}"/><circle cx="86" cy="40" r="3" fill="${NODE_FILL}" stroke="${WARDLEY_RED}"/><rect x="76" y="35" width="2.5" height="11" fill="${INERTIA_COLOR}"/><path d="M57 40 h17" stroke="${WARDLEY_RED}" stroke-dasharray="3 2"/>`), kodak, WARDLEY_TEMPLATE_NAME_KODAK_INERTIA[0]),
|
|
383
504
|
];
|
package/dist/toolbar/config.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type ChromeWording, type ToolbarContext } from '@formicoidea/labre-core/shared/services';
|
|
2
2
|
import { type TemplateResult } from 'lit';
|
|
3
|
+
/** Every wording above, for `translations.ts`'s manifest contribution. */
|
|
4
|
+
export declare const WARDLEY_TOOLBAR_WORDINGS: readonly ChromeWording[];
|
|
3
5
|
export declare const wardleyToolbarConfig: {
|
|
4
6
|
readonly actions: [{
|
|
5
7
|
id: string;
|