@formicoidea/labre-framework-wardley 0.33.0 → 0.34.1

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.
@@ -0,0 +1,18 @@
1
+ import type { ShortcutManifestEntry } from '@formicoidea/labre-core/std';
2
+ /**
3
+ * The Wardley commands as SHORTCUT-MANIFEST rows — id, label, chord, scope,
4
+ * owner — and nothing else.
5
+ *
6
+ * DATA ONLY, and that is the whole point (`docs/adr/0008` § Packaging). A
7
+ * `CommandDescriptor` carries its `run`, so a host settings pane that imports
8
+ * the package entry to list names and chords drags the entire action graph —
9
+ * the import/export machinery, the surface and gfx deep paths — into its
10
+ * chunk. This module has type-only imports, so the published bundle exposes it
11
+ * as `./commands-manifest`: a few hundred bytes that reference nothing.
12
+ *
13
+ * GENERATED-SHAPED, hand-committed: `commands-manifest.unit.spec.ts` asserts
14
+ * row-for-row equality with `toShortcutManifestEntry` over {@link wardleyCommands},
15
+ * so this file cannot drift from the commands it projects. Add a command and
16
+ * the test says exactly what to add here.
17
+ */
18
+ export declare const wardleyCommandsManifest: ShortcutManifestEntry[];
@@ -0,0 +1,146 @@
1
+ /**
2
+ * The Wardley commands as SHORTCUT-MANIFEST rows — id, label, chord, scope,
3
+ * owner — and nothing else.
4
+ *
5
+ * DATA ONLY, and that is the whole point (`docs/adr/0008` § Packaging). A
6
+ * `CommandDescriptor` carries its `run`, so a host settings pane that imports
7
+ * the package entry to list names and chords drags the entire action graph —
8
+ * the import/export machinery, the surface and gfx deep paths — into its
9
+ * chunk. This module has type-only imports, so the published bundle exposes it
10
+ * as `./commands-manifest`: a few hundred bytes that reference nothing.
11
+ *
12
+ * GENERATED-SHAPED, hand-committed: `commands-manifest.unit.spec.ts` asserts
13
+ * row-for-row equality with `toShortcutManifestEntry` over {@link wardleyCommands},
14
+ * so this file cannot drift from the commands it projects. Add a command and
15
+ * the test says exactly what to add here.
16
+ */
17
+ export const wardleyCommandsManifest = [
18
+ {
19
+ id: 'wardley.addBackground',
20
+ owner: 'wardley',
21
+ labelKey: 'com.labre.keyboardShortcuts.wardley.addBackground',
22
+ labelFallback: 'Wardley map background',
23
+ scope: 'edgeless',
24
+ defaultKeys: { mac: ['w', 'b'], other: ['w', 'b'] },
25
+ },
26
+ {
27
+ id: 'wardley.addOpportunityBackground',
28
+ owner: 'wardley',
29
+ labelKey: 'com.labre.commands.wardley.addOpportunityBackground',
30
+ labelFallback: 'Opportunity background (gradient)',
31
+ scope: 'edgeless',
32
+ defaultKeys: { mac: [], other: [] },
33
+ },
34
+ {
35
+ id: 'wardley.addBenefitBackground',
36
+ owner: 'wardley',
37
+ labelKey: 'com.labre.commands.wardley.addBenefitBackground',
38
+ labelFallback: 'Benefit / Investment background (gradient)',
39
+ scope: 'edgeless',
40
+ defaultKeys: { mac: [], other: [] },
41
+ },
42
+ {
43
+ id: 'wardley.addEvolutionBackground',
44
+ owner: 'wardley',
45
+ labelKey: 'com.labre.commands.wardley.addEvolutionBackground',
46
+ labelFallback: 'Evolution background (Wardley presentation)',
47
+ scope: 'edgeless',
48
+ defaultKeys: { mac: [], other: [] },
49
+ },
50
+ {
51
+ id: 'wardley.addComponent',
52
+ owner: 'wardley',
53
+ labelKey: 'com.labre.keyboardShortcuts.wardley.addComponent',
54
+ labelFallback: 'Component',
55
+ scope: 'edgeless',
56
+ defaultKeys: { mac: ['w', 'c'], other: ['w', 'c'] },
57
+ },
58
+ {
59
+ id: 'wardley.addMethod',
60
+ owner: 'wardley',
61
+ labelKey: 'com.labre.keyboardShortcuts.wardley.addMethod',
62
+ labelFallback: 'Component + method',
63
+ scope: 'edgeless',
64
+ defaultKeys: { mac: ['w', 'm'], other: ['w', 'm'] },
65
+ },
66
+ {
67
+ id: 'wardley.addMarket',
68
+ owner: 'wardley',
69
+ labelKey: 'com.labre.commands.wardley.addMarket',
70
+ labelFallback: 'Market',
71
+ scope: 'edgeless',
72
+ defaultKeys: { mac: [], other: [] },
73
+ },
74
+ {
75
+ id: 'wardley.addEcosystem',
76
+ owner: 'wardley',
77
+ labelKey: 'com.labre.commands.wardley.addEcosystem',
78
+ labelFallback: 'Ecosystem',
79
+ scope: 'edgeless',
80
+ defaultKeys: { mac: [], other: [] },
81
+ },
82
+ {
83
+ id: 'wardley.addAnchor',
84
+ owner: 'wardley',
85
+ labelKey: 'com.labre.commands.wardley.addAnchor',
86
+ labelFallback: 'Anchor',
87
+ scope: 'edgeless',
88
+ defaultKeys: { mac: [], other: [] },
89
+ },
90
+ {
91
+ id: 'wardley.addPipeline',
92
+ owner: 'wardley',
93
+ labelKey: 'com.labre.keyboardShortcuts.wardley.addPipeline',
94
+ labelFallback: 'Pipeline',
95
+ scope: 'edgeless',
96
+ defaultKeys: { mac: ['w', 'p'], other: ['w', 'p'] },
97
+ },
98
+ {
99
+ id: 'wardley.linkTool',
100
+ owner: 'wardley',
101
+ labelKey: 'com.labre.keyboardShortcuts.wardley.linkTool',
102
+ labelFallback: 'Link',
103
+ scope: 'edgeless',
104
+ defaultKeys: { mac: ['w', 'l'], other: ['w', 'l'] },
105
+ },
106
+ {
107
+ id: 'wardley.evolutionArrow',
108
+ owner: 'wardley',
109
+ labelKey: 'com.labre.keyboardShortcuts.wardley.evolutionArrow',
110
+ labelFallback: 'Arrow (evolution)',
111
+ scope: 'edgeless',
112
+ defaultKeys: { mac: ['w', 'a'], other: ['w', 'a'] },
113
+ },
114
+ {
115
+ id: 'wardley.addInertia',
116
+ owner: 'wardley',
117
+ labelKey: 'com.labre.keyboardShortcuts.wardley.addInertia',
118
+ labelFallback: 'Inertia',
119
+ scope: 'edgeless',
120
+ defaultKeys: { mac: ['w', 'i'], other: ['w', 'i'] },
121
+ },
122
+ {
123
+ id: 'wardley.importOwm',
124
+ owner: 'wardley',
125
+ labelKey: 'com.labre.commands.wardley.importOwm',
126
+ labelFallback: 'Import Wardley map (OWM)',
127
+ scope: 'edgeless',
128
+ defaultKeys: { mac: [], other: [] },
129
+ },
130
+ {
131
+ id: 'wardley.exportOwm',
132
+ owner: 'wardley',
133
+ labelKey: 'com.labre.commands.wardley.exportOwm',
134
+ labelFallback: 'Export Wardley map (OWM)',
135
+ scope: 'edgeless',
136
+ defaultKeys: { mac: [], other: [] },
137
+ },
138
+ {
139
+ id: 'wardley.importSvg',
140
+ owner: 'wardley',
141
+ labelKey: 'com.labre.commands.wardley.importSvg',
142
+ labelFallback: 'Import SVG sketch',
143
+ scope: 'edgeless',
144
+ defaultKeys: { mac: [], other: [] },
145
+ },
146
+ ];
@@ -1,4 +1,6 @@
1
1
  import type { WardleyBackgroundElementModel } from '@formicoidea/labre-core/model';
2
+ import type { EditorHost } from '@formicoidea/labre-core/std';
3
+ import type { PointTestOptions } from '@formicoidea/labre-core/std/gfx';
2
4
  import { GfxElementModelView } from '@formicoidea/labre-core/std/gfx';
3
5
  export declare class WardleyView extends GfxElementModelView<WardleyBackgroundElementModel> {
4
6
  static type: string;
@@ -6,6 +8,26 @@ export declare class WardleyView extends GfxElementModelView<WardleyBackgroundEl
6
8
  private _labelEditor;
7
9
  onCreated(): void;
8
10
  onDestroyed(): void;
11
+ /**
12
+ * The editable label under a MODEL-space point, or null.
13
+ *
14
+ * Which labels exist, where they sit, what they SAY and which are editable
15
+ * all come from the declaration the renderer paints — one source, resolved
16
+ * through the same catalogue, so a label can never be drawn in one place
17
+ * and clicked in another, nor read one thing and open on another.
18
+ */
19
+ private _labelAt;
20
+ /**
21
+ * The map is SELECTED by its border (`WardleyBackgroundElementModel`), but
22
+ * its axis labels must still receive the double-click that renames them.
23
+ *
24
+ * So the two areas differ, and this is where they are allowed to: the pointer
25
+ * router asks the VIEW (`GfxViewEventManager`), and the view adds the zones
26
+ * the declaration draws its labels in. Picking is unaffected —
27
+ * `getElementByPoint` still asks the model, so a click in the middle of the
28
+ * map still goes to whatever the user put there.
29
+ */
30
+ includesPoint(x: number, y: number, options: PointTestOptions, host: EditorHost): boolean;
9
31
  /** Double-click on a label → edit its text in place. */
10
32
  private _onDblClick;
11
33
  /**
@@ -18,11 +18,15 @@ export class WardleyView extends GfxElementModelView {
18
18
  this._closeLabelEditor();
19
19
  super.onDestroyed();
20
20
  }
21
- /** Double-click on a label → edit its text in place. */
22
- _onDblClick(e) {
23
- if (this.model.isLocked())
24
- return;
25
- const [mx, my] = this.gfx.viewport.toModelCoord(e.x, e.y);
21
+ /**
22
+ * The editable label under a MODEL-space point, or null.
23
+ *
24
+ * Which labels exist, where they sit, what they SAY and which are editable
25
+ * all come from the declaration the renderer paints — one source, resolved
26
+ * through the same catalogue, so a label can never be drawn in one place
27
+ * and clicked in another, nor read one thing and open on another.
28
+ */
29
+ _labelAt(mx, my) {
26
30
  const [bx, by, w, h] = this.model.deserializedXYWH;
27
31
  // Convert the model-space point into element-local coordinates, undoing the
28
32
  // element rotation around its center.
@@ -35,15 +39,34 @@ export class WardleyView extends GfxElementModelView {
35
39
  lx = ux - bx;
36
40
  ly = uy - by;
37
41
  }
38
- // Which labels exist, where they sit, what they SAY and which are editable
39
- // all come from the declaration the renderer paints — one source, resolved
40
- // through the same catalogue, so a label can never be drawn in one place
41
- // and clicked in another, nor read one thing and open on another.
42
42
  const hit = hitTestBackgroundLabel(backgroundLabelHits(WARDLEY_BACKGROUND, this.model, w, h, this.gfx.std.getOptional(TranslationProvider)), lx, ly);
43
- if (!hit)
44
- return;
45
43
  // The declaration names the prop; this decides whether it may be written.
46
- if (!isWardleyLabelProp(hit.prop))
44
+ if (!hit || !isWardleyLabelProp(hit.prop))
45
+ return null;
46
+ return { prop: hit.prop, text: hit.text };
47
+ }
48
+ /**
49
+ * The map is SELECTED by its border (`WardleyBackgroundElementModel`), but
50
+ * its axis labels must still receive the double-click that renames them.
51
+ *
52
+ * So the two areas differ, and this is where they are allowed to: the pointer
53
+ * router asks the VIEW (`GfxViewEventManager`), and the view adds the zones
54
+ * the declaration draws its labels in. Picking is unaffected —
55
+ * `getElementByPoint` still asks the model, so a click in the middle of the
56
+ * map still goes to whatever the user put there.
57
+ */
58
+ includesPoint(x, y, options, host) {
59
+ if (super.includesPoint(x, y, options, host))
60
+ return true;
61
+ return this._labelAt(x, y) !== null;
62
+ }
63
+ /** Double-click on a label → edit its text in place. */
64
+ _onDblClick(e) {
65
+ if (this.model.isLocked())
66
+ return;
67
+ const [mx, my] = this.gfx.viewport.toModelCoord(e.x, e.y);
68
+ const hit = this._labelAt(mx, my);
69
+ if (!hit)
47
70
  return;
48
71
  this._openLabelEditor(hit.prop, hit.text, e);
49
72
  }
@@ -1,9 +1,10 @@
1
- import { type ToolbarContext } from '@formicoidea/labre-core/shared/services';
1
+ import { type ChromeWording, type ToolbarContext } from '@formicoidea/labre-core/shared/services';
2
2
  import { type TemplateResult } from 'lit';
3
3
  export declare const wardleyToolbarConfig: {
4
4
  readonly actions: [{
5
5
  id: string;
6
6
  tooltip: string;
7
+ tooltipWording: ChromeWording | undefined;
7
8
  icon: TemplateResult;
8
9
  when: boolean | ((ctx: ToolbarContext) => boolean);
9
10
  active(ctx: ToolbarContext): boolean;
@@ -13,6 +14,7 @@ export declare const wardleyToolbarConfig: {
13
14
  readonly actions: [{
14
15
  id: string;
15
16
  tooltip: string;
17
+ tooltipWording: ChromeWording | undefined;
16
18
  icon: TemplateResult;
17
19
  when: boolean | ((ctx: ToolbarContext) => boolean);
18
20
  active(ctx: ToolbarContext): boolean;
@@ -20,6 +22,7 @@ export declare const wardleyToolbarConfig: {
20
22
  }, {
21
23
  id: string;
22
24
  tooltip: string;
25
+ tooltipWording: ChromeWording | undefined;
23
26
  icon: TemplateResult;
24
27
  when: boolean | ((ctx: ToolbarContext) => boolean);
25
28
  active(ctx: ToolbarContext): boolean;
@@ -27,6 +30,7 @@ export declare const wardleyToolbarConfig: {
27
30
  }, {
28
31
  id: string;
29
32
  tooltip: string;
33
+ tooltipWording: ChromeWording | undefined;
30
34
  icon: TemplateResult;
31
35
  when: boolean | ((ctx: ToolbarContext) => boolean);
32
36
  active(ctx: ToolbarContext): boolean;
@@ -34,6 +38,7 @@ export declare const wardleyToolbarConfig: {
34
38
  }, {
35
39
  id: string;
36
40
  tooltip: string;
41
+ tooltipWording: ChromeWording | undefined;
37
42
  icon: TemplateResult;
38
43
  when: boolean | ((ctx: ToolbarContext) => boolean);
39
44
  active(ctx: ToolbarContext): boolean;
@@ -41,6 +46,7 @@ export declare const wardleyToolbarConfig: {
41
46
  }, {
42
47
  id: string;
43
48
  tooltip: string;
49
+ tooltipWording: ChromeWording | undefined;
44
50
  icon: TemplateResult;
45
51
  when: boolean | ((ctx: ToolbarContext) => boolean);
46
52
  active(ctx: ToolbarContext): boolean;
@@ -51,6 +57,7 @@ export declare const wardleyToolbarConfig: {
51
57
  readonly actions: [{
52
58
  id: string;
53
59
  tooltip: string;
60
+ tooltipWording: ChromeWording | undefined;
54
61
  icon: TemplateResult;
55
62
  when: boolean | ((ctx: ToolbarContext) => boolean);
56
63
  active(ctx: ToolbarContext): boolean;
@@ -58,6 +65,7 @@ export declare const wardleyToolbarConfig: {
58
65
  }, {
59
66
  id: string;
60
67
  tooltip: string;
68
+ tooltipWording: ChromeWording | undefined;
61
69
  icon: TemplateResult;
62
70
  when: boolean | ((ctx: ToolbarContext) => boolean);
63
71
  active(ctx: ToolbarContext): boolean;
@@ -65,7 +73,7 @@ export declare const wardleyToolbarConfig: {
65
73
  }];
66
74
  }, {
67
75
  readonly id: "d.legend";
68
- readonly tooltip: "Generate the legend (components present)";
76
+ readonly tooltipWording: ChromeWording;
69
77
  readonly icon: TemplateResult<2>;
70
78
  readonly run: (ctx: ToolbarContext) => void;
71
79
  }];
@@ -1,6 +1,6 @@
1
1
  import { EdgelessCRUDIdentifier } from '@formicoidea/labre-core/blocks/surface';
2
2
  import { WardleyBackgroundElementModel } from '@formicoidea/labre-core/model';
3
- import { TelemetryProvider, ToolbarModuleExtension, } from '@formicoidea/labre-core/shared/services';
3
+ import { BOARD_LEGEND_COMPONENTS, BOARD_RESIZE_TOGGLE, TelemetryProvider, ToolbarModuleExtension, } from '@formicoidea/labre-core/shared/services';
4
4
  import { BlockFlavourIdentifier } from '@formicoidea/labre-core/std';
5
5
  import { html } from 'lit';
6
6
  import { createWardleyLegend } from '../legend.js';
@@ -129,7 +129,12 @@ const VisibilityIcon = html `<svg
129
129
  function booleanToggle(id, tooltip, icon, prop, when) {
130
130
  return {
131
131
  id,
132
- tooltip,
132
+ tooltip: typeof tooltip === 'string' ? tooltip : tooltip[1],
133
+ // The declared wording, when the caller gave one instead of a literal:
134
+ // `combine` resolves it against the host's catalogue and writes it over
135
+ // the English default above, so a playground with no catalogue reads
136
+ // exactly what it read before (#183).
137
+ tooltipWording: typeof tooltip === 'string' ? undefined : tooltip,
133
138
  icon,
134
139
  when: when ?? true,
135
140
  active(ctx) {
@@ -151,7 +156,7 @@ function booleanToggle(id, tooltip, icon, prop, when) {
151
156
  }
152
157
  export const wardleyToolbarConfig = {
153
158
  actions: [
154
- booleanToggle('a.toggle-resize', 'Enable / lock resizing', ResizeIcon, 'resizeEnabled'),
159
+ booleanToggle('a.toggle-resize', BOARD_RESIZE_TOGGLE, ResizeIcon, 'resizeEnabled'),
155
160
  // Group 1 — evolution (X) side: axis, phase labels, columns, corner
156
161
  // labels, and the gradient toggle.
157
162
  {
@@ -179,7 +184,7 @@ export const wardleyToolbarConfig = {
179
184
  // background's perimeter (+ a gradient-meaning block for gradient variants).
180
185
  {
181
186
  id: 'd.legend',
182
- tooltip: 'Generate the legend (components present)',
187
+ tooltipWording: BOARD_LEGEND_COMPONENTS,
183
188
  icon: wardleyLegendIcon,
184
189
  run(ctx) {
185
190
  const models = ctx.getSurfaceModelsByType(WardleyBackgroundElementModel);
@@ -1,4 +1,4 @@
1
- import { collectTranslationKeys, commandTranslationEntries, mergeTranslationEntries, } from '@formicoidea/labre-core/std';
1
+ import { collectTranslationKeys, commandCategoryTranslationEntries, commandTranslationEntries, mergeTranslationEntries, } from '@formicoidea/labre-core/std';
2
2
  import { WARDLEY_AUDIT_CRITERIA } from './audit-criteria.js';
3
3
  import { WARDLEY_BACKGROUND } from './background.js';
4
4
  import { wardleyCommands } from './commands.js';
@@ -21,4 +21,10 @@ import { WARDLEY_RULES } from './rules.js';
21
21
  * complete in the monorepo and silently 61 % short (107 keys of 175) in the
22
22
  * distribution hosts actually consume.
23
23
  */
24
- export const wardleyTranslationEntries = mergeTranslationEntries(commandTranslationEntries(wardleyCommands), collectTranslationKeys('role', WARDLEY_ROLES), collectTranslationKeys('background', WARDLEY_BACKGROUND), collectTranslationKeys('rule', WARDLEY_RULES), collectTranslationKeys('nudge', WARDLEY_NUDGES), collectTranslationKeys('profile', WARDLEY_PROFILES), collectTranslationKeys('audit-criterion', WARDLEY_AUDIT_CRITERIA), collectTranslationKeys('reading', WARDLEY_READING));
24
+ export const wardleyTranslationEntries = mergeTranslationEntries(commandTranslationEntries(wardleyCommands),
25
+ // The catalogue's own group headers, derived from the very categories
26
+ // these commands declare. They ship WITH the framework because core's
27
+ // registry names no framework category in the bundled distribution, so a
28
+ // host that composed core's manifest alone drew translated entries under
29
+ // English headers (#183).
30
+ commandCategoryTranslationEntries(wardleyCommands), collectTranslationKeys('role', WARDLEY_ROLES), collectTranslationKeys('background', WARDLEY_BACKGROUND), collectTranslationKeys('rule', WARDLEY_RULES), collectTranslationKeys('nudge', WARDLEY_NUDGES), collectTranslationKeys('profile', WARDLEY_PROFILES), collectTranslationKeys('audit-criterion', WARDLEY_AUDIT_CRITERIA), collectTranslationKeys('reading', WARDLEY_READING));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@formicoidea/labre-framework-wardley",
3
3
  "description": "Labre wardley framework for @formicoidea/labre-core.",
4
- "version": "0.33.0",
4
+ "version": "0.34.1",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "author": "lajola",
@@ -21,13 +21,17 @@
21
21
  "./descriptor": {
22
22
  "types": "./dist/descriptor.d.ts",
23
23
  "import": "./dist/descriptor.js"
24
+ },
25
+ "./commands-manifest": {
26
+ "types": "./dist/commands-manifest.d.ts",
27
+ "import": "./dist/commands-manifest.js"
24
28
  }
25
29
  },
26
30
  "files": [
27
31
  "dist"
28
32
  ],
29
33
  "dependencies": {
30
- "@formicoidea/labre-core": "0.33.0",
34
+ "@formicoidea/labre-core": "0.34.1",
31
35
  "lit": "^3.2.0"
32
36
  }
33
37
  }