@formicoidea/labre-framework-c4 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.
package/dist/actions.js CHANGED
@@ -2,6 +2,7 @@ import { DefaultTool } from '@formicoidea/labre-core/blocks/surface';
2
2
  import { ConnectorTool } from '@formicoidea/labre-core/gfx/connector';
3
3
  import { createAutoLegend } from '@formicoidea/labre-ddd-shared';
4
4
  import { C4BoardElementModel, ConnectorMode, FontFamily, FontStyle, FontWeight, PointStyle, StrokeStyle, TextAlign, } from '@formicoidea/labre-core/model';
5
+ import { translateKey } from '@formicoidea/labre-core/shared/services';
5
6
  import { downloadBlob } from '@formicoidea/labre-core/shared/utils';
6
7
  import { Bound } from '@formicoidea/labre-core/global/gfx';
7
8
  import { GfxControllerIdentifier, } from '@formicoidea/labre-core/std/gfx';
@@ -10,7 +11,7 @@ import { BOARD_REF_HEIGHT, BOARD_REF_WIDTH, BOUNDARY_LABEL, BOUNDARY_REF_HEIGHT,
10
11
  import { C4_MERMAID_EXPORT, c4BoardFrom, c4SafeFilename } from './interchange.js';
11
12
  import { C4_AUTO_LEGEND } from './legend.js';
12
13
  import { c4NodeProps } from './presets.js';
13
- import { C4_BOUNDARY_ROLE, C4_ROLE } from './roles.js';
14
+ import { C4_BOUNDARY_ROLE, C4_ROLE, c4BoardRoleKey } from './roles.js';
14
15
  import { C4_TYPE_PLACEHOLDER } from './type-line.js';
15
16
  /**
16
17
  * Standalone creation/activation actions for the C4 toolbox — the same shape
@@ -164,6 +165,13 @@ export function createC4Board(std) {
164
165
  // The FRAME the elements are drawn on, and a role of its own: a rule written
165
166
  // on the artefacts must never fall on the sheet holding them.
166
167
  role: C4_ROLE.board,
168
+ // The sheet's own name, written HERE rather than left to the model's
169
+ // default so that a board drawn in a translated host starts in that
170
+ // language (#183). It is content from that moment on — the title is
171
+ // editable on a double-click — so it is asked for once and never
172
+ // re-resolved. The key is the BOARD ROLE's: the two are the same noun, and
173
+ // a second key would ask a host to word "C4 diagram" twice.
174
+ name: translateKey(std, c4BoardRoleKey, 'C4 diagram'),
167
175
  xywh: new Bound(cx - BOARD_REF_WIDTH / 2, cy - BOARD_REF_HEIGHT / 2, BOARD_REF_WIDTH, BOARD_REF_HEIGHT).serialize(),
168
176
  });
169
177
  finish(gfx, id);
@@ -0,0 +1,18 @@
1
+ import type { ShortcutManifestEntry } from '@formicoidea/labre-core/std';
2
+ /**
3
+ * The C4 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 c4Commands},
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 c4CommandsManifest: ShortcutManifestEntry[];
@@ -0,0 +1,130 @@
1
+ /**
2
+ * The C4 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 c4Commands},
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 c4CommandsManifest = [
18
+ {
19
+ id: 'c4.addBoard',
20
+ owner: 'c4',
21
+ labelKey: 'com.labre.commands.c4.addBoard',
22
+ labelFallback: 'C4 board',
23
+ scope: 'edgeless',
24
+ defaultKeys: { mac: [], other: [] },
25
+ },
26
+ {
27
+ id: 'c4.addPerson',
28
+ owner: 'c4',
29
+ labelKey: 'com.labre.commands.c4.addPerson',
30
+ labelFallback: 'Person',
31
+ scope: 'edgeless',
32
+ defaultKeys: { mac: [], other: [] },
33
+ },
34
+ {
35
+ id: 'c4.addPersonExt',
36
+ owner: 'c4',
37
+ labelKey: 'com.labre.commands.c4.addPersonExt',
38
+ labelFallback: 'Person (external)',
39
+ scope: 'edgeless',
40
+ defaultKeys: { mac: [], other: [] },
41
+ },
42
+ {
43
+ id: 'c4.addSystem',
44
+ owner: 'c4',
45
+ labelKey: 'com.labre.commands.c4.addSystem',
46
+ labelFallback: 'Software system',
47
+ scope: 'edgeless',
48
+ defaultKeys: { mac: [], other: [] },
49
+ },
50
+ {
51
+ id: 'c4.addSystemExt',
52
+ owner: 'c4',
53
+ labelKey: 'com.labre.commands.c4.addSystemExt',
54
+ labelFallback: 'Software system (external)',
55
+ scope: 'edgeless',
56
+ defaultKeys: { mac: [], other: [] },
57
+ },
58
+ {
59
+ id: 'c4.addContainer',
60
+ owner: 'c4',
61
+ labelKey: 'com.labre.commands.c4.addContainer',
62
+ labelFallback: 'Container',
63
+ scope: 'edgeless',
64
+ defaultKeys: { mac: [], other: [] },
65
+ },
66
+ {
67
+ id: 'c4.addComponent',
68
+ owner: 'c4',
69
+ labelKey: 'com.labre.commands.c4.addComponent',
70
+ labelFallback: 'Component',
71
+ scope: 'edgeless',
72
+ defaultKeys: { mac: [], other: [] },
73
+ },
74
+ {
75
+ id: 'c4.addDatabase',
76
+ owner: 'c4',
77
+ labelKey: 'com.labre.commands.c4.addDatabase',
78
+ labelFallback: 'Database',
79
+ scope: 'edgeless',
80
+ defaultKeys: { mac: [], other: [] },
81
+ },
82
+ {
83
+ id: 'c4.addMobile',
84
+ owner: 'c4',
85
+ labelKey: 'com.labre.commands.c4.addMobile',
86
+ labelFallback: 'Mobile app',
87
+ scope: 'edgeless',
88
+ defaultKeys: { mac: [], other: [] },
89
+ },
90
+ {
91
+ id: 'c4.addBrowser',
92
+ owner: 'c4',
93
+ labelKey: 'com.labre.commands.c4.addBrowser',
94
+ labelFallback: 'Web browser',
95
+ scope: 'edgeless',
96
+ defaultKeys: { mac: [], other: [] },
97
+ },
98
+ {
99
+ id: 'c4.relationshipTool',
100
+ owner: 'c4',
101
+ labelKey: 'com.labre.commands.c4.relationshipTool',
102
+ labelFallback: 'Relationship',
103
+ scope: 'edgeless',
104
+ defaultKeys: { mac: [], other: [] },
105
+ },
106
+ {
107
+ id: 'c4.addSystemBoundary',
108
+ owner: 'c4',
109
+ labelKey: 'com.labre.commands.c4.addSystemBoundary',
110
+ labelFallback: 'System boundary',
111
+ scope: 'edgeless',
112
+ defaultKeys: { mac: [], other: [] },
113
+ },
114
+ {
115
+ id: 'c4.addContainerBoundary',
116
+ owner: 'c4',
117
+ labelKey: 'com.labre.commands.c4.addContainerBoundary',
118
+ labelFallback: 'Container boundary',
119
+ scope: 'edgeless',
120
+ defaultKeys: { mac: [], other: [] },
121
+ },
122
+ {
123
+ id: 'c4.exportMermaid',
124
+ owner: 'c4',
125
+ labelKey: 'com.labre.commands.c4.exportMermaid',
126
+ labelFallback: 'Export as mermaid',
127
+ scope: 'edgeless',
128
+ defaultKeys: { mac: [], other: [] },
129
+ },
130
+ ];
@@ -1,5 +1,7 @@
1
1
  import type { FrameworkBackgroundDef } from '@formicoidea/labre-core/blocks/surface';
2
2
  import type { C4BoardElementModel, C4BoundaryElementModel } from '@formicoidea/labre-core/model';
3
+ import type { EditorHost } from '@formicoidea/labre-core/std';
4
+ import type { PointTestOptions } from '@formicoidea/labre-core/std/gfx';
3
5
  import { GfxElementModelView } from '@formicoidea/labre-core/std/gfx';
4
6
  /**
5
7
  * The one gesture the two C4 frames carry: a double-click on the name edits it
@@ -29,6 +31,19 @@ declare abstract class C4FrameView<T extends C4BoardElementModel | C4BoundaryEle
29
31
  private _editor;
30
32
  onCreated(): void;
31
33
  onDestroyed(): void;
34
+ /** The editable name label under a MODEL-space point, or null. */
35
+ private _labelAt;
36
+ /**
37
+ * A frame is SELECTED by its border (`FrameworkBackgroundElementModel`, issue
38
+ * #194) — but the name written on its card must still receive the
39
+ * double-click that renames it.
40
+ *
41
+ * Same seam Wardley and EDGY use: the pointer router asks the VIEW, picking
42
+ * asks the MODEL, and a framework declares its own gesture zones beside the
43
+ * code that draws them. Without this the name becomes unrenameable; without
44
+ * the model change the card swallows every click meant for the nodes on it.
45
+ */
46
+ includesPoint(x: number, y: number, options: PointTestOptions, host: EditorHost): boolean;
32
47
  private _onDblClick;
33
48
  /**
34
49
  * @param current the words currently DRAWN, which is what the user aimed at —
@@ -38,10 +38,8 @@ class C4FrameView extends GfxElementModelView {
38
38
  this._closeEditor();
39
39
  super.onDestroyed();
40
40
  }
41
- _onDblClick(e) {
42
- if (this.gfx.std.store.readonly || this.model.isLocked())
43
- return;
44
- const [mx, my] = this.gfx.viewport.toModelCoord(e.x, e.y);
41
+ /** The editable name label under a MODEL-space point, or null. */
42
+ _labelAt(mx, my) {
45
43
  const [bx, by, w, h] = this.model.deserializedXYWH;
46
44
  // Element-local coordinates, undoing the element rotation about its centre.
47
45
  let lx = mx - bx;
@@ -54,7 +52,29 @@ class C4FrameView extends GfxElementModelView {
54
52
  ly = uy - by;
55
53
  }
56
54
  const hit = hitTestBackgroundLabel(backgroundLabelHits(this.def, this.model, w, h, this.gfx.std.getOptional(TranslationProvider)), lx, ly);
57
- if (!hit || hit.prop !== 'name')
55
+ return hit && hit.prop === 'name' ? hit : null;
56
+ }
57
+ /**
58
+ * A frame is SELECTED by its border (`FrameworkBackgroundElementModel`, issue
59
+ * #194) — but the name written on its card must still receive the
60
+ * double-click that renames it.
61
+ *
62
+ * Same seam Wardley and EDGY use: the pointer router asks the VIEW, picking
63
+ * asks the MODEL, and a framework declares its own gesture zones beside the
64
+ * code that draws them. Without this the name becomes unrenameable; without
65
+ * the model change the card swallows every click meant for the nodes on it.
66
+ */
67
+ includesPoint(x, y, options, host) {
68
+ if (super.includesPoint(x, y, options, host))
69
+ return true;
70
+ return this._labelAt(x, y) !== null;
71
+ }
72
+ _onDblClick(e) {
73
+ if (this.gfx.std.store.readonly || this.model.isLocked())
74
+ return;
75
+ const [mx, my] = this.gfx.viewport.toModelCoord(e.x, e.y);
76
+ const hit = this._labelAt(mx, my);
77
+ if (!hit)
58
78
  return;
59
79
  this._openEditor(hit.text, e);
60
80
  }
package/dist/roles.d.ts CHANGED
@@ -82,6 +82,13 @@ export declare const C4_ROLE: {
82
82
  readonly 'container-boundary': "c4:container-boundary";
83
83
  readonly relationship: "c4:relationship";
84
84
  };
85
+ /**
86
+ * The board's own key, exported because `createC4Board` seeds the sheet's NAME
87
+ * from it (#183: a board drawn in a French host should not be called
88
+ * "C4 diagram"). One key for the role and for the seed, because they are the
89
+ * same noun and a host must not be asked to word it twice.
90
+ */
91
+ export declare const c4BoardRoleKey: string;
85
92
  export declare const C4_ROLES: RoleDefs;
86
93
  /**
87
94
  * The `kind` discriminant → the role it means.
package/dist/roles.js CHANGED
@@ -41,6 +41,13 @@ void _everyRoleIsMapped;
41
41
  */
42
42
  /** i18n key stem of a role id: `c4:person` → `com.labre.c4.role.person`. */
43
43
  const roleKey = (id) => `com.labre.c4.role.${id.slice('c4:'.length)}`;
44
+ /**
45
+ * The board's own key, exported because `createC4Board` seeds the sheet's NAME
46
+ * from it (#183: a board drawn in a French host should not be called
47
+ * "C4 diagram"). One key for the role and for the seed, because they are the
48
+ * same noun and a host must not be asked to word it twice.
49
+ */
50
+ export const c4BoardRoleKey = roleKey(C4_ROLE.board);
44
51
  /**
45
52
  * The four levels of the C4 model, flat — see the note at the top of this file
46
53
  * on why composition is not specialisation — plus the one specialisation C4
@@ -65,7 +65,7 @@ import { type TemplateResult } from 'lit';
65
65
  export declare const c4BoardToolbarConfig: {
66
66
  readonly actions: [{
67
67
  readonly id: "a.toggle-resize";
68
- readonly tooltip: "Enable / lock resizing";
68
+ readonly tooltipWording: import("@formicoidea/labre-core/shared/services").ChromeWording;
69
69
  readonly icon: TemplateResult<1>;
70
70
  readonly active: (ctx: ToolbarContext) => boolean;
71
71
  readonly run: (ctx: ToolbarContext) => void;
@@ -91,7 +91,7 @@ export declare const c4BoardToolbarExtension: import("@formicoidea/labre-core/st
91
91
  export declare const c4LegendToolbarConfig: {
92
92
  readonly actions: [{
93
93
  readonly id: "b.legend";
94
- readonly tooltip: "Generate the legend (notation present)";
94
+ readonly tooltipWording: import("@formicoidea/labre-core/shared/services").ChromeWording;
95
95
  readonly icon: TemplateResult<1>;
96
96
  readonly run: (ctx: ToolbarContext) => void;
97
97
  }];
@@ -1,7 +1,7 @@
1
1
  import { EdgelessCRUDIdentifier, validationToolbarConfig, } from '@formicoidea/labre-core/blocks/surface';
2
2
  import { dddLegendIcon } from '@formicoidea/labre-ddd-shared';
3
3
  import { C4BoardElementModel } from '@formicoidea/labre-core/model';
4
- import { ActionPlacement, TelemetryProvider, ToolbarModuleExtension, translateKey, } from '@formicoidea/labre-core/shared/services';
4
+ import { ActionPlacement, BOARD_LEGEND_NOTATION, BOARD_RESIZE_TOGGLE, TelemetryProvider, ToolbarModuleExtension, translateKey, } from '@formicoidea/labre-core/shared/services';
5
5
  import { BlockFlavourIdentifier, getRegisteredCommands, runCommand, } from '@formicoidea/labre-core/std';
6
6
  import { html, nothing } from 'lit';
7
7
  import { createC4Legend } from '../actions.js';
@@ -166,7 +166,7 @@ export const c4BoardToolbarConfig = {
166
166
  actions: [
167
167
  {
168
168
  id: 'a.toggle-resize',
169
- tooltip: 'Enable / lock resizing',
169
+ tooltipWording: BOARD_RESIZE_TOGGLE,
170
170
  icon: ResizeIcon,
171
171
  active(ctx) {
172
172
  const models = ctx.getSurfaceModelsByType(C4BoardElementModel);
@@ -346,7 +346,7 @@ export const c4LegendToolbarConfig = {
346
346
  actions: [
347
347
  {
348
348
  id: 'b.legend',
349
- tooltip: 'Generate the legend (notation present)',
349
+ tooltipWording: BOARD_LEGEND_NOTATION,
350
350
  icon: dddLegendIcon,
351
351
  run(ctx) {
352
352
  createC4Legend(ctx.std);
@@ -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 { C4_BOARD_BACKGROUND, C4_BOUNDARY_BACKGROUND } from './background.js';
3
3
  import { c4Commands } from './commands.js';
4
4
  import { C4_BOARD_LEVEL_MENU } from './levels.js';
@@ -21,7 +21,13 @@ import { C4_RULES } from './rules.js';
21
21
  * means the day one of them gains a declared label the manifest already names
22
22
  * it — which is the whole reason these lists are derived rather than written.
23
23
  */
24
- export const c4TranslationEntries = mergeTranslationEntries(commandTranslationEntries(c4Commands), collectTranslationKeys('role', C4_ROLES), collectTranslationKeys('background', [
24
+ export const c4TranslationEntries = mergeTranslationEntries(commandTranslationEntries(c4Commands),
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(c4Commands), collectTranslationKeys('role', C4_ROLES), collectTranslationKeys('background', [
25
31
  C4_BOARD_BACKGROUND,
26
32
  C4_BOUNDARY_BACKGROUND,
27
33
  // The LEVEL a board declares, and the words the picker offers it under.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@formicoidea/labre-framework-c4",
3
3
  "description": "Labre c4 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,14 +21,18 @@
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",
31
- "@formicoidea/labre-ddd-shared": "0.33.0",
34
+ "@formicoidea/labre-core": "0.34.1",
35
+ "@formicoidea/labre-ddd-shared": "0.34.1",
32
36
  "lit": "^3.2.0"
33
37
  }
34
38
  }