@formicoidea/labre-framework-wardley 0.31.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.
Files changed (58) hide show
  1. package/dist/actions.d.ts +63 -20
  2. package/dist/actions.js +190 -57
  3. package/dist/audit-criteria.d.ts +31 -0
  4. package/dist/audit-criteria.js +90 -0
  5. package/dist/background.d.ts +14 -0
  6. package/dist/background.js +338 -0
  7. package/dist/commands.d.ts +9 -0
  8. package/dist/commands.js +352 -0
  9. package/dist/consts.d.ts +10 -4
  10. package/dist/consts.js +10 -9
  11. package/dist/descriptor.d.ts +8 -3
  12. package/dist/descriptor.js +6 -3
  13. package/dist/element-renderer.d.ts +8 -5
  14. package/dist/element-renderer.js +12 -147
  15. package/dist/element-view.d.ts +8 -4
  16. package/dist/element-view.js +30 -22
  17. package/dist/export.d.ts +211 -0
  18. package/dist/export.js +655 -0
  19. package/dist/gradient.d.ts +6 -11
  20. package/dist/gradient.js +59 -48
  21. package/dist/import.d.ts +116 -0
  22. package/dist/import.js +905 -0
  23. package/dist/index.d.ts +27 -1
  24. package/dist/index.js +31 -1
  25. package/dist/interchange.d.ts +80 -0
  26. package/dist/interchange.js +138 -0
  27. package/dist/legend.js +8 -0
  28. package/dist/natures.d.ts +50 -0
  29. package/dist/natures.js +93 -0
  30. package/dist/node/node-renderer.js +1 -1
  31. package/dist/nudges.d.ts +41 -0
  32. package/dist/nudges.js +69 -0
  33. package/dist/profiles.d.ts +2 -0
  34. package/dist/profiles.js +87 -0
  35. package/dist/reading.d.ts +3 -0
  36. package/dist/reading.js +129 -0
  37. package/dist/roles.d.ts +50 -0
  38. package/dist/roles.js +132 -0
  39. package/dist/rules.d.ts +2 -0
  40. package/dist/rules.js +286 -0
  41. package/dist/templates/index.js +66 -10
  42. package/dist/templates/maps.js +146 -22
  43. package/dist/toolbar/config.js +3 -1
  44. package/dist/toolbar/icons.d.ts +20 -0
  45. package/dist/toolbar/icons.js +34 -0
  46. package/dist/toolbar/senior-tool.js +1 -0
  47. package/dist/toolbar/wardley-menu.d.ts +8 -15
  48. package/dist/toolbar/wardley-menu.js +8 -136
  49. package/dist/toolbar/wardley-senior-button.js +12 -6
  50. package/dist/translations.d.ts +16 -0
  51. package/dist/translations.js +24 -0
  52. package/dist/view.d.ts +17 -0
  53. package/dist/view.js +127 -13
  54. package/package.json +2 -2
  55. package/dist/label-layout.d.ts +0 -20
  56. package/dist/label-layout.js +0 -72
  57. package/dist/shortcuts.d.ts +0 -2
  58. package/dist/shortcuts.js +0 -37
@@ -0,0 +1,338 @@
1
+ import { ARROW, AXIS_LABELS, CARD_RADIUS, COLORS, FONT_FAMILY, FONTS, LINE, MARGIN, OFFSETS, PHASE_LABELS, REF_WIDTH, } from './consts.js';
2
+ import { WARDLEY_WASHES } from './gradient.js';
3
+ import { WARDLEY_RED } from './node/consts.js';
4
+ import { WARDLEY_ROLE } from './roles.js';
5
+ /**
6
+ * The Wardley map background, DECLARED (PF2.12).
7
+ *
8
+ * This file is the whole of what makes a Wardley background look like a Wardley
9
+ * background. There is no Wardley rendering code left: the primitive
10
+ * (`FrameworkBackgroundDef` / `createFrameworkBackgroundRenderer` in
11
+ * `@labre/affine-block-surface`) paints this declaration, and would paint any
12
+ * other framework's the same way.
13
+ *
14
+ * Nothing here changes the DOCUMENT. The persisted element type is still
15
+ * `wardley` and its props are untouched — `variant`, `banded`, the ten label
16
+ * texts, the six visibility toggles — they are simply named by the declaration
17
+ * instead of being read by hand-written drawing code. A map authored before
18
+ * this file existed opens with the same geometry, the same zones and the same
19
+ * words.
20
+ *
21
+ * ## i18n
22
+ *
23
+ * Every label declares BOTH a `labelKey` (the vocabulary, for a host that ships
24
+ * a locale) and a `prop` (the user's own text, which always wins).
25
+ *
26
+ * For the key to be REACHABLE the prop has to be able to be absent, so the ten
27
+ * label fields on `WardleyBackgroundElementModel` default to `undefined`: an
28
+ * `undefined` default is written nowhere (see `field.ts`), so a map the user
29
+ * has never renamed carries no label key at all and falls through to the
30
+ * vocabulary. The moment the user edits a label in place, the prop is written
31
+ * and wins forever after — which is exactly the old behaviour, arrived at from
32
+ * the other side.
33
+ *
34
+ * A map authored before this change carries all ten props with their English
35
+ * values and is completely unaffected.
36
+ */
37
+ /**
38
+ * Green, for the benefit half of the tone convention (Q5).
39
+ *
40
+ * Declared here rather than in `node/consts.ts` because nothing DRAWS it: no
41
+ * Wardley artefact is created green, and the framework has no "benefit" role
42
+ * yet. It exists so the convention has a reference colour to be judged against
43
+ * — the day an artefact of that kind is created, it takes this entry, and the
44
+ * check-up already knows about it.
45
+ *
46
+ * Picked in the same register as {@link WARDLEY_RED}, so a map using both reads
47
+ * as one palette rather than as two decisions.
48
+ */
49
+ const BENEFIT_GREEN = '#2f9e63';
50
+ /**
51
+ * The colour code: every colour below is named, never repeated as a hex.
52
+ *
53
+ * The last three entries are the **tone convention** (PF13.8 / Q5), and they are
54
+ * palette entries for a reason: the check-up rule names them
55
+ * (`ToneConventionDef.palette`) instead of restating a colour, so the convention
56
+ * and the map are restyled together, in one place, by whoever owns the frame.
57
+ * Nothing paints them — see {@link BENEFIT_GREEN} — which is exactly what a
58
+ * declared REFERENCE looks like.
59
+ */
60
+ const PALETTE = {
61
+ card: COLORS.card,
62
+ cardBorder: COLORS.cardBorder,
63
+ axis: COLORS.axis,
64
+ divider: COLORS.divider,
65
+ label: COLORS.label,
66
+ band0: COLORS.band[0],
67
+ band1: COLORS.band[1],
68
+ band2: COLORS.band[2],
69
+ band3: COLORS.band[3],
70
+ /** The landscape: everything the map is MADE of, drawn in greys. */
71
+ landscape: COLORS.label,
72
+ /** Reserved for what is moving — change points, investments, costs. */
73
+ change: WARDLEY_RED,
74
+ /** Reserved for benefits and functional differences. */
75
+ benefit: BENEFIT_GREEN,
76
+ };
77
+ const AXIS_TEXT = { size: FONTS.axis, color: '@axis' };
78
+ const PHASE_TEXT = { size: FONTS.phase, color: '@label' };
79
+ const DIRECTION_TEXT = { size: FONTS.direction, color: '@label' };
80
+ const VISIBILITY_TEXT = { size: FONTS.visibility, color: '@label' };
81
+ /**
82
+ * The four evolution phases, as named zones of the plot. `banded` tints them,
83
+ * `showColumnLabels` names them; the dashed dividers between them are the
84
+ * graduations of the evolution axis, declared with it.
85
+ */
86
+ const EVOLUTION_ZONES = [
87
+ {
88
+ id: 'genesis',
89
+ rect: { x: 0, y: 0, w: 0.175, h: 1 },
90
+ fill: '@band0',
91
+ fillVisibleProp: 'banded',
92
+ label: {
93
+ id: 'phase0',
94
+ prop: 'phase0',
95
+ labelKey: 'com.labre.wardley.background.phase.genesis',
96
+ fallback: PHASE_LABELS.genesis,
97
+ anchor: { x: 0, y: 1, dx: OFFSETS.phasePad, dy: OFFSETS.phaseBaseline },
98
+ style: PHASE_TEXT,
99
+ align: 'left',
100
+ visibleProp: 'showColumnLabels',
101
+ },
102
+ },
103
+ {
104
+ id: 'custom-built',
105
+ rect: { x: 0.175, y: 0, w: 0.225, h: 1 },
106
+ fill: '@band1',
107
+ fillVisibleProp: 'banded',
108
+ label: {
109
+ id: 'phase1',
110
+ prop: 'phase1',
111
+ labelKey: 'com.labre.wardley.background.phase.custom-built',
112
+ fallback: PHASE_LABELS.customBuilt,
113
+ anchor: {
114
+ x: 0.175,
115
+ y: 1,
116
+ dx: OFFSETS.phasePad,
117
+ dy: OFFSETS.phaseBaseline,
118
+ },
119
+ style: PHASE_TEXT,
120
+ align: 'left',
121
+ visibleProp: 'showColumnLabels',
122
+ },
123
+ },
124
+ {
125
+ id: 'product',
126
+ rect: { x: 0.4, y: 0, w: 0.3, h: 1 },
127
+ fill: '@band2',
128
+ fillVisibleProp: 'banded',
129
+ label: {
130
+ id: 'phase2',
131
+ prop: 'phase2',
132
+ labelKey: 'com.labre.wardley.background.phase.product',
133
+ fallback: PHASE_LABELS.product,
134
+ anchor: { x: 0.4, y: 1, dx: OFFSETS.phasePad, dy: OFFSETS.phaseBaseline },
135
+ style: PHASE_TEXT,
136
+ align: 'left',
137
+ visibleProp: 'showColumnLabels',
138
+ },
139
+ },
140
+ {
141
+ id: 'commodity',
142
+ rect: { x: 0.7, y: 0, w: 0.3, h: 1 },
143
+ fill: '@band3',
144
+ fillVisibleProp: 'banded',
145
+ label: {
146
+ id: 'phase3',
147
+ prop: 'phase3',
148
+ labelKey: 'com.labre.wardley.background.phase.commodity',
149
+ fallback: PHASE_LABELS.commodity,
150
+ anchor: { x: 0.7, y: 1, dx: OFFSETS.phasePad, dy: OFFSETS.phaseBaseline },
151
+ style: PHASE_TEXT,
152
+ align: 'left',
153
+ visibleProp: 'showColumnLabels',
154
+ },
155
+ },
156
+ ];
157
+ /**
158
+ * The two axes. Evolution runs along the bottom with its phase dividers as
159
+ * graduations; Value Chain runs up the left edge. Both arrows point "forward",
160
+ * i.e. towards more evolved / more visible.
161
+ *
162
+ * The end labels (Uncharted / Industrialized, Visible / Invisible) carry their
163
+ * own visibility: naming where an axis leads has always been a separate toggle
164
+ * from drawing the axis, and the declaration keeps it that way.
165
+ */
166
+ const WARDLEY_AXES = [
167
+ {
168
+ id: 'evolution',
169
+ orientation: 'horizontal',
170
+ at: 1,
171
+ arrow: 'forward',
172
+ arrowSize: ARROW,
173
+ stroke: { color: '@axis', width: LINE.axis },
174
+ visibleProp: 'showXAxis',
175
+ title: {
176
+ id: 'xAxisTitle',
177
+ prop: 'xAxisTitle',
178
+ labelKey: 'com.labre.wardley.background.axis.evolution',
179
+ fallback: AXIS_LABELS.xAxis,
180
+ anchor: {
181
+ x: 1,
182
+ y: 1,
183
+ dx: -OFFSETS.evolutionPadRight,
184
+ dy: OFFSETS.phaseBaseline,
185
+ },
186
+ style: AXIS_TEXT,
187
+ align: 'right',
188
+ },
189
+ endLabels: [
190
+ {
191
+ id: 'evolutionStart',
192
+ prop: 'evolutionStart',
193
+ labelKey: 'com.labre.wardley.background.evolution.start',
194
+ fallback: AXIS_LABELS.evolutionStart,
195
+ anchor: {
196
+ x: 0,
197
+ y: 0,
198
+ dx: OFFSETS.directionPadLeft,
199
+ dy: OFFSETS.directionTop,
200
+ },
201
+ style: DIRECTION_TEXT,
202
+ align: 'left',
203
+ visibleProp: 'showCornerLabels',
204
+ },
205
+ {
206
+ id: 'evolutionEnd',
207
+ prop: 'evolutionEnd',
208
+ labelKey: 'com.labre.wardley.background.evolution.end',
209
+ fallback: AXIS_LABELS.evolutionEnd,
210
+ anchor: {
211
+ x: 1,
212
+ y: 0,
213
+ dx: -OFFSETS.directionPadRight,
214
+ dy: OFFSETS.directionTop,
215
+ },
216
+ style: DIRECTION_TEXT,
217
+ align: 'right',
218
+ visibleProp: 'showCornerLabels',
219
+ },
220
+ ],
221
+ ticks: {
222
+ ticks: [{ at: 0.175 }, { at: 0.4 }, { at: 0.7 }],
223
+ stroke: { color: '@divider', width: LINE.divider, dash: [5, 5] },
224
+ visibleProp: 'showColumnDividers',
225
+ },
226
+ },
227
+ {
228
+ id: 'value-chain',
229
+ orientation: 'vertical',
230
+ at: 0,
231
+ arrow: 'forward',
232
+ arrowSize: ARROW,
233
+ stroke: { color: '@axis', width: LINE.axis },
234
+ visibleProp: 'showYAxis',
235
+ title: {
236
+ id: 'yAxisTitle',
237
+ prop: 'yAxisTitle',
238
+ labelKey: 'com.labre.wardley.background.axis.value-chain',
239
+ fallback: AXIS_LABELS.yAxis,
240
+ anchor: { x: 0, y: 0.5, dx: -OFFSETS.yHug, dy: 0 },
241
+ style: AXIS_TEXT,
242
+ vertical: true,
243
+ },
244
+ endLabels: [
245
+ {
246
+ id: 'visibilityHigh',
247
+ prop: 'visibilityHigh',
248
+ labelKey: 'com.labre.wardley.background.visibility.high',
249
+ fallback: AXIS_LABELS.visibilityHigh,
250
+ anchor: { x: 0, y: 0, dx: -OFFSETS.yHug, dy: OFFSETS.visibleTop },
251
+ style: VISIBILITY_TEXT,
252
+ vertical: true,
253
+ visibleProp: 'showVisibilityLabels',
254
+ },
255
+ {
256
+ id: 'visibilityLow',
257
+ prop: 'visibilityLow',
258
+ labelKey: 'com.labre.wardley.background.visibility.low',
259
+ fallback: AXIS_LABELS.visibilityLow,
260
+ anchor: { x: 0, y: 1, dx: -OFFSETS.yHug, dy: -OFFSETS.invisibleBottom },
261
+ style: VISIBILITY_TEXT,
262
+ vertical: true,
263
+ visibleProp: 'showVisibilityLabels',
264
+ },
265
+ ],
266
+ },
267
+ ];
268
+ export const WARDLEY_BACKGROUND = {
269
+ type: 'wardley',
270
+ // The map is a first-class role: validation rules position artefacts against
271
+ // `wardley:map`, never against the `wardley` element type.
272
+ role: WARDLEY_ROLE.map,
273
+ variantProp: 'variant',
274
+ geometry: {
275
+ width: REF_WIDTH,
276
+ height: (REF_WIDTH * 9) / 16,
277
+ lockAspectRatio: true,
278
+ // A map is a frame you place things on, not a shape you nudge: the handles
279
+ // stay locked until the user asks for them from the toolbar.
280
+ resizable: false,
281
+ margin: MARGIN,
282
+ },
283
+ chrome: {
284
+ fontFamily: FONT_FAMILY,
285
+ palette: PALETTE,
286
+ surface: {
287
+ fill: '@card',
288
+ border: { color: '@cardBorder', width: LINE.card, radius: CARD_RADIUS },
289
+ },
290
+ washes: WARDLEY_WASHES,
291
+ },
292
+ zones: EVOLUTION_ZONES,
293
+ axes: WARDLEY_AXES,
294
+ /**
295
+ * The **zone of punctuated equilibrium**: how wide, as a ratio of the plot,
296
+ * the frontier between two evolution phases really is.
297
+ *
298
+ * Wardley's point is that a phase transition is not a coordinate. Things do
299
+ * not become products at `x = 0.4`; they resist, then move, and the inertia
300
+ * that resists lives AROUND the frontier. A rule asking "is this symbol at
301
+ * the transition" therefore measures against this band, not against the
302
+ * dashed line the renderer draws.
303
+ *
304
+ * `0.1` of the plot — ±5% either side of the divider — chosen on the PO
305
+ * recette of 01/08/2026, where two bars dropped by eye on the "Product" and
306
+ * "Commodity" dividers had to come out green. In model units that is ±76 on
307
+ * the 1600-wide reference map (against the 40 absolute units it replaces) and
308
+ * ±36 on an 800-wide one — the same band to the eye at every size, which is
309
+ * the whole reason it is a ratio. Still narrow enough to mean something: the
310
+ * narrowest gap between two transitions is 0.225 of the plot, so its middle
311
+ * stays 0.0625 of the plot clear of either band.
312
+ */
313
+ transitionBandWidth: 0.1,
314
+ };
315
+ /**
316
+ * The props the in-place label editor is allowed to write.
317
+ *
318
+ * A closed list, not `string`: the hit test reports whatever `prop` a
319
+ * declaration names, and since #73 an element preserves keys it does not
320
+ * declare — so a typo in the declaration would happily persist a junk key onto
321
+ * every map it was double-clicked on. This is the gate between "the
322
+ * declaration says so" and "the document gets it".
323
+ */
324
+ export const WARDLEY_LABEL_PROPS = [
325
+ 'xAxisTitle',
326
+ 'yAxisTitle',
327
+ 'evolutionStart',
328
+ 'evolutionEnd',
329
+ 'visibilityHigh',
330
+ 'visibilityLow',
331
+ 'phase0',
332
+ 'phase1',
333
+ 'phase2',
334
+ 'phase3',
335
+ ];
336
+ export function isWardleyLabelProp(prop) {
337
+ return WARDLEY_LABEL_PROPS.includes(prop);
338
+ }
@@ -0,0 +1,9 @@
1
+ import type { CommandDescriptor } from '@formicoidea/labre-core/std';
2
+ import type { TemplateResult } from 'lit';
3
+ /**
4
+ * The Wardley registry: the thirteen toolbox entries, then the two directions
5
+ * of the OWM DSL and the SVG fallback (`docs/adr/0012`).
6
+ */
7
+ export declare const wardleyCommands: CommandDescriptor[];
8
+ /** `iconKey` → template. Never travels through either manifest (ADR 0008). */
9
+ export declare const wardleyCommandIcons: Record<string, TemplateResult>;