@formicoidea/labre-ddd-shared 0.39.3 → 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/index.d.ts CHANGED
@@ -4,3 +4,4 @@ export * from './shared/prefabs.js';
4
4
  export * from './shared/utils.js';
5
5
  export * from './toolbar/icons.js';
6
6
  export { DddSeniorButtonBase } from './toolbar/senior-buttons.js';
7
+ export * from './translations.js';
package/dist/index.js CHANGED
@@ -4,3 +4,4 @@ export * from './shared/prefabs.js';
4
4
  export * from './shared/utils.js';
5
5
  export * from './toolbar/icons.js';
6
6
  export { DddSeniorButtonBase } from './toolbar/senior-buttons.js';
7
+ export * from './translations.js';
@@ -3,6 +3,20 @@
3
3
  * (sticky, dot, bubble, connector, label) from these presets — no duplicated
4
4
  * component definitions across the Event Storming / Context Map / Core Domain
5
5
  * sub-menus.
6
+ *
7
+ * ## Where each preset's `label` actually gets a key
8
+ *
9
+ * Not here: this file is generic across the three frameworks and declares no
10
+ * `com.labre.*` key of its own. Every preset below is reused, byte for byte,
11
+ * as the `labelFallback` of the placement (or connector-arming) command it
12
+ * feeds in its framework's own `commands.ts` — `ddd-context-map.add<Kind>`,
13
+ * `ddd-core-domain.<preset>`, `ddd-event-storming.<preset>` — which is where
14
+ * the command's own `labelKey` (`com.labre.commands.<framework>.<id>`) lives.
15
+ * `getCommands()` walks registered commands into the translation manifest
16
+ * automatically ("declared data", see
17
+ * `packages/affine/shared/src/services/translation-service/README.md`), so a
18
+ * second key here for the same English word would only be the drift the
19
+ * manifest guard exists to catch.
6
20
  */
7
21
  /** Square sticky side (px, canvas reference). */
8
22
  export declare const STICKY_SIZE = 120;
@@ -156,6 +170,11 @@ export declare const CM_RELATIONSHIPS: readonly [{
156
170
  readonly dashed: true;
157
171
  }];
158
172
  export declare const CLOUD_VERTICES: number[][];
173
+ /**
174
+ * The cloud (Big Ball of Mud). Its lilac fill is the notation's own; its
175
+ * outline is the shared scale's secondary grey. A cloud created before the scale
176
+ * was adopted keeps the `#6d6e71` outline it was written with.
177
+ */
159
178
  export declare const CLOUD: {
160
179
  w: number;
161
180
  h: number;
@@ -204,6 +223,7 @@ export declare const CD_SUBDOMAINS: readonly [{
204
223
  }];
205
224
  export declare const DOT_SIZE = 26;
206
225
  export declare const MOVEMENT_COLOR = "#ff3333";
207
- export declare const LABEL_COLOR = "#1f2328";
226
+ /** Label and legend text: the shared notation scale's artefact ink. */
227
+ export declare const LABEL_COLOR: string;
208
228
  export declare const LABEL_FONT = "blocksuite:surface:Inter";
209
229
  export declare const LABEL_FONT_SIZE = 14;
@@ -1,8 +1,23 @@
1
+ import { NOTATION_NEUTRALS } from '@formicoidea/labre-core/shared/consts';
1
2
  /**
2
3
  * Shared DDD palette and sizes. Every tool composes the same irreducible units
3
4
  * (sticky, dot, bubble, connector, label) from these presets — no duplicated
4
5
  * component definitions across the Event Storming / Context Map / Core Domain
5
6
  * sub-menus.
7
+ *
8
+ * ## Where each preset's `label` actually gets a key
9
+ *
10
+ * Not here: this file is generic across the three frameworks and declares no
11
+ * `com.labre.*` key of its own. Every preset below is reused, byte for byte,
12
+ * as the `labelFallback` of the placement (or connector-arming) command it
13
+ * feeds in its framework's own `commands.ts` — `ddd-context-map.add<Kind>`,
14
+ * `ddd-core-domain.<preset>`, `ddd-event-storming.<preset>` — which is where
15
+ * the command's own `labelKey` (`com.labre.commands.<framework>.<id>`) lives.
16
+ * `getCommands()` walks registered commands into the translation manifest
17
+ * automatically ("declared data", see
18
+ * `packages/affine/shared/src/services/translation-service/README.md`), so a
19
+ * second key here for the same English word would only be the drift the
20
+ * manifest guard exists to catch.
6
21
  */
7
22
  /** Square sticky side (px, canvas reference). */
8
23
  export const STICKY_SIZE = 120;
@@ -167,7 +182,17 @@ function buildCloud() {
167
182
  return pts;
168
183
  }
169
184
  export const CLOUD_VERTICES = buildCloud();
170
- export const CLOUD = { w: 180, h: 120, fill: '#f0eef6', stroke: '#6d6e71' };
185
+ /**
186
+ * The cloud (Big Ball of Mud). Its lilac fill is the notation's own; its
187
+ * outline is the shared scale's secondary grey. A cloud created before the scale
188
+ * was adopted keeps the `#6d6e71` outline it was written with.
189
+ */
190
+ export const CLOUD = {
191
+ w: 180,
192
+ h: 120,
193
+ fill: '#f0eef6',
194
+ stroke: NOTATION_NEUTRALS.label,
195
+ };
171
196
  /** Team Topologies interaction modes (placeable markers + Notation legend). */
172
197
  export const TEAM_TOPOLOGIES = [
173
198
  {
@@ -190,6 +215,7 @@ export const CD_SUBDOMAINS = [
190
215
  ];
191
216
  export const DOT_SIZE = 26;
192
217
  export const MOVEMENT_COLOR = '#ff3333';
193
- export const LABEL_COLOR = '#1f2328';
218
+ /** Label and legend text: the shared notation scale's artefact ink. */
219
+ export const LABEL_COLOR = NOTATION_NEUTRALS.ink;
194
220
  export const LABEL_FONT = 'blocksuite:surface:Inter';
195
221
  export const LABEL_FONT_SIZE = 14;
@@ -53,20 +53,43 @@ export interface AutoLegendEntry {
53
53
  * off when the parent row is a fair summary of the whole family.
54
54
  */
55
55
  exact?: boolean;
56
+ /**
57
+ * Static prefix kept literal in front of the role's resolved wording — the
58
+ * Context Map relationship abbreviation ("PS — Partnership"). Absent for
59
+ * every other row, whose label IS the role's own wording and nothing else.
60
+ */
61
+ labelPrefix?: string;
56
62
  }
57
63
  export interface AutoLegendSectionSpec {
58
64
  /** Sub-title, dropped along with the section when none of its rows appear. */
59
65
  title?: string;
66
+ /**
67
+ * i18n key for {@link title}, resolved through the host's catalogue at
68
+ * legend-build time when present. Absent for the sections whose title is
69
+ * generic chrome rather than a framework's own word (`'Legend'`, `'Flow'`…),
70
+ * which this lot leaves as they are.
71
+ */
72
+ titleKey?: string;
60
73
  entries: readonly AutoLegendEntry[];
61
74
  }
62
75
  export interface AutoLegendSpec {
63
76
  /**
64
- * Box title. The three DDD tools all say "Legend" (PO recette, 26/08/2026:
65
- * the boxes used to be titled in French, which was the one label in the
66
- * library that was — identifiers and fallback wordings are English here, and
67
- * the day a host ships a locale pack it translates a key, not a leftover).
77
+ * Box title. Every framework with an automatic legend says "Legend" (PO
78
+ * recette, 26/08/2026: the boxes used to be titled in French, which was the
79
+ * one label in the library that was — identifiers and fallback wordings are
80
+ * English here, and the day a host ships a locale pack it translates a key,
81
+ * not a leftover).
68
82
  */
69
83
  title: string;
84
+ /**
85
+ * i18n key for {@link title}, resolved through the host's catalogue at
86
+ * legend-build time — the same mechanism as
87
+ * {@link AutoLegendSectionSpec.titleKey}, one level up. Every framework that
88
+ * says "Legend" reuses `BOARD_LEGEND_TITLE`
89
+ * (`@labre/affine-shared/services`), since it is the SAME word on every
90
+ * board that has one — the three DDD boards, EDGY and C4 alike.
91
+ */
92
+ titleKey?: string;
70
93
  width?: number;
71
94
  /**
72
95
  * The framework's role vocabulary, so a present role is matched against an
@@ -84,6 +107,11 @@ export interface AutoLegendSpec {
84
107
  * A legend row about `es:flow` says "Flow" because that is what the role def
85
108
  * says it is called — the table below never restates a label the vocabulary
86
109
  * already owns, so renaming a role renames its legend row.
110
+ *
111
+ * This is the FALLBACK half only — the English wording a spec bakes in at
112
+ * declaration time, with no `std` in scope to ask a host's catalogue. The
113
+ * catalogue is asked afterwards, once, when the legend is actually drawn: see
114
+ * {@link autoLegendSections}.
87
115
  */
88
116
  export declare function roleLabel(roles: RoleDefs, id: RoleId): string;
89
117
  /**
@@ -105,8 +133,13 @@ export declare function rolesInBound(gfx: GfxController, bound: Bound): Set<Role
105
133
  * "Legend" title and no rows), and it is the honest one — a legend of a board
106
134
  * with nothing on it lists nothing, rather than inventing the full notation the
107
135
  * user has not used.
136
+ *
137
+ * `std` resolves each surviving row's label — and each section's title, where
138
+ * one carries a {@link AutoLegendSectionSpec.titleKey} — through the host's
139
+ * catalogue (see {@link resolveRowLabel}); a spec whose entries carry no
140
+ * `labelKey` at all renders byte-identical to what it always has.
108
141
  */
109
- export declare function autoLegendSections(present: ReadonlySet<RoleId>, spec: AutoLegendSpec): LegendSection[];
142
+ export declare function autoLegendSections(present: ReadonlySet<RoleId>, spec: AutoLegendSpec, std: BlockStdScope): LegendSection[];
110
143
  /**
111
144
  * Build the legend of what is drawn inside `background` and drop it bottom-left
112
145
  * of it, grouped and selected.
@@ -1,3 +1,4 @@
1
+ import { translateKey } from '@formicoidea/labre-core/shared/services';
1
2
  import { Bound } from '@formicoidea/labre-core/global/gfx';
2
3
  import { GfxControllerIdentifier, roleIsA, } from '@formicoidea/labre-core/std/gfx';
3
4
  import { addLegend, measureLegend, } from './prefabs.js';
@@ -7,10 +8,53 @@ import { addLegend, measureLegend, } from './prefabs.js';
7
8
  * A legend row about `es:flow` says "Flow" because that is what the role def
8
9
  * says it is called — the table below never restates a label the vocabulary
9
10
  * already owns, so renaming a role renames its legend row.
11
+ *
12
+ * This is the FALLBACK half only — the English wording a spec bakes in at
13
+ * declaration time, with no `std` in scope to ask a host's catalogue. The
14
+ * catalogue is asked afterwards, once, when the legend is actually drawn: see
15
+ * {@link autoLegendSections}.
10
16
  */
11
17
  export function roleLabel(roles, id) {
12
18
  return roles[id]?.labelFallback ?? id;
13
19
  }
20
+ /**
21
+ * Resolve one row's label through the host's catalogue, at legend-BUILD time
22
+ * — the one point in this module that has a `std` to ask.
23
+ *
24
+ * A row's `label` is baked at spec-declaration time (module scope, no `std`)
25
+ * as the exact English text a catalogue-less playground must keep showing —
26
+ * see {@link roleLabel}. Here, if the row's own role carries a `labelKey`, that
27
+ * baked text becomes the FALLBACK argument of `translateKey` rather than the
28
+ * final word: a host with a catalogue entry for the key overrides it, and a
29
+ * host with none gets back the identical string, letter for letter.
30
+ *
31
+ * `labelPrefix` rows (the Context Map relationship abbreviations, "PS —
32
+ * Partnership") are the one case where the row's baked text is not what gets
33
+ * handed to the catalogue: the role's own `labelFallback` is (the abbreviation
34
+ * itself is never a translatable word), and the prefix is stitched back on
35
+ * after translation.
36
+ */
37
+ function resolveRowLabel(std, roles, entry) {
38
+ const def = roles[entry.role];
39
+ if (!def?.labelKey)
40
+ return entry.row.label;
41
+ if (entry.labelPrefix) {
42
+ const translated = translateKey(std, def.labelKey, def.labelFallback ?? entry.role);
43
+ return `${entry.labelPrefix} — ${translated}`;
44
+ }
45
+ return translateKey(std, def.labelKey, entry.row.label);
46
+ }
47
+ /**
48
+ * Resolve one section's title through the host's catalogue — see
49
+ * {@link resolveRowLabel}. Absent {@link AutoLegendSectionSpec.titleKey} keeps
50
+ * the section's title exactly as declared, unresolved: most section titles are
51
+ * generic chrome ("Legend", "Flow") this lot leaves untranslated.
52
+ */
53
+ function resolveSectionTitle(std, section) {
54
+ return section.titleKey && section.title !== undefined
55
+ ? translateKey(std, section.titleKey, section.title)
56
+ : section.title;
57
+ }
14
58
  /**
15
59
  * Distance from the background's left edge / bottom edge, in model units.
16
60
  * Wardley's numbers, kept identical so the two gestures put the box in the same
@@ -44,17 +88,25 @@ export function rolesInBound(gfx, bound) {
44
88
  * "Legend" title and no rows), and it is the honest one — a legend of a board
45
89
  * with nothing on it lists nothing, rather than inventing the full notation the
46
90
  * user has not used.
91
+ *
92
+ * `std` resolves each surviving row's label — and each section's title, where
93
+ * one carries a {@link AutoLegendSectionSpec.titleKey} — through the host's
94
+ * catalogue (see {@link resolveRowLabel}); a spec whose entries carry no
95
+ * `labelKey` at all renders byte-identical to what it always has.
47
96
  */
48
- export function autoLegendSections(present, spec) {
97
+ export function autoLegendSections(present, spec, std) {
49
98
  const sections = [];
50
99
  for (const section of spec.sections) {
51
100
  const rows = section.entries
52
101
  .filter(entry => entry.exact
53
102
  ? present.has(entry.role)
54
103
  : [...present].some(role => roleIsA(role, entry.role, spec.roles)))
55
- .map(entry => entry.row);
104
+ .map(entry => ({
105
+ ...entry.row,
106
+ label: resolveRowLabel(std, spec.roles, entry),
107
+ }));
56
108
  if (rows.length)
57
- sections.push({ title: section.title, rows });
109
+ sections.push({ title: resolveSectionTitle(std, section), rows });
58
110
  }
59
111
  return sections;
60
112
  }
@@ -70,10 +122,13 @@ export function createAutoLegend(std, background, spec) {
70
122
  if (!surface)
71
123
  return undefined;
72
124
  const bound = Bound.deserialize(background.xywh);
73
- const sections = autoLegendSections(rolesInBound(gfx, bound), spec);
125
+ const sections = autoLegendSections(rolesInBound(gfx, bound), spec, std);
126
+ const title = spec.titleKey
127
+ ? translateKey(std, spec.titleKey, spec.title)
128
+ : spec.title;
74
129
  const { height } = measureLegend(sections, spec.width);
75
130
  std.store.captureSync();
76
- const id = addLegend(surface, std, bound.x + INSET_X, bound.y + bound.h - INSET_BOTTOM - height, { title: spec.title, sections, width: spec.width });
131
+ const id = addLegend(surface, std, bound.x + INSET_X, bound.y + bound.h - INSET_BOTTOM - height, { title, sections, width: spec.width });
77
132
  gfx.selection.set({ elements: [id], editing: false });
78
133
  return id;
79
134
  }
@@ -1,6 +1,7 @@
1
1
  import { DefaultTool } from '@formicoidea/labre-core/blocks/surface';
2
2
  import { createGroupCommand } from '@formicoidea/labre-core/gfx/group';
3
3
  import { ConnectorMode, FontWeight, PointStyle, ShapeStyle, StrokeStyle, TextFitMode, } from '@formicoidea/labre-core/model';
4
+ import { NOTATION_NEUTRALS } from '@formicoidea/labre-core/shared/consts';
4
5
  import { Bound } from '@formicoidea/labre-core/global/gfx';
5
6
  import { GfxControllerIdentifier } from '@formicoidea/labre-core/std/gfx';
6
7
  import * as Y from 'yjs';
@@ -135,8 +136,8 @@ export function addBubble(surface, cx, cy, label, role) {
135
136
  },
136
137
  });
137
138
  }
138
- /** The ink every Core Domain artefact is outlined with. */
139
- const ARTEFACT_STROKE = '#1f2328';
139
+ /** The ink every Core Domain artefact is outlined with: the shared scale's. */
140
+ const ARTEFACT_STROKE = NOTATION_NEUTRALS.ink;
140
141
  /**
141
142
  * What a Core Domain DOT is, as shape options — read by the creation site below
142
143
  * and by the morph, so the two can never disagree about what a platform
@@ -200,7 +201,7 @@ export function addMarker(surface, std, cx, cy, opts) {
200
201
  const { fill, letter, label, role } = opts;
201
202
  const s = MARKER_SIZE;
202
203
  const box = addShape(surface, cx - s / 2, cy - s / 2, s, s, markerShapeOpts(fill, role));
203
- const glyph = addText(surface, cx - s / 2, cy - 9, s, letter, '#1f2328', LABEL_FONT, 15);
204
+ const glyph = addText(surface, cx - s / 2, cy - 9, s, letter, NOTATION_NEUTRALS.ink, LABEL_FONT, 15);
204
205
  const ids = [box, glyph];
205
206
  if (label) {
206
207
  ids.push(addText(surface, cx + s / 2 + 6, cy - LABEL_FONT_SIZE / 2, 150, label, LABEL_COLOR, LABEL_FONT, LABEL_FONT_SIZE, 'left'));
@@ -225,7 +226,7 @@ export function addCloud(surface, std, cx, cy, label) {
225
226
  });
226
227
  if (!label)
227
228
  return cloud;
228
- const lbl = addText(surface, cx - w / 2 + 12, cy - LABEL_FONT_SIZE / 2, w - 24, label, '#3d3d3d', LABEL_FONT, LABEL_FONT_SIZE);
229
+ const lbl = addText(surface, cx - w / 2 + 12, cy - LABEL_FONT_SIZE / 2, w - 24, label, NOTATION_NEUTRALS.ink, LABEL_FONT, LABEL_FONT_SIZE);
229
230
  return groupIds(std, [cloud, lbl]);
230
231
  }
231
232
  /**
@@ -273,8 +274,8 @@ export function addLegend(surface, std, x, y, opts) {
273
274
  const { width: W, height: H } = measureLegend(opts.sections, opts.width);
274
275
  const ids = [
275
276
  addShape(surface, x, y, W, H, {
276
- fill: '#ffffff',
277
- stroke: '#6d6e71',
277
+ fill: NOTATION_NEUTRALS.cardFill,
278
+ stroke: NOTATION_NEUTRALS.legendBorder,
278
279
  strokeWidth: 1.5,
279
280
  radius: 8,
280
281
  }),
@@ -294,19 +295,19 @@ export function addLegend(surface, std, x, y, opts) {
294
295
  ids.push(addShape(surface, sx, midY - SW / 2, SW, SW, {
295
296
  shapeType: 'ellipse',
296
297
  fill: row.color,
297
- stroke: '#1f2328',
298
+ stroke: NOTATION_NEUTRALS.ink,
298
299
  strokeWidth: 1,
299
300
  }));
300
301
  }
301
302
  else if (row.swatch === 'square') {
302
303
  ids.push(addShape(surface, sx, midY - SW / 2, SW, SW, {
303
304
  fill: row.color,
304
- stroke: '#1f2328',
305
+ stroke: NOTATION_NEUTRALS.ink,
305
306
  strokeWidth: 1,
306
307
  radius: 3,
307
308
  }));
308
309
  if (row.letter)
309
- ids.push(addText(surface, sx, midY - 8, SW, row.letter, '#1f2328', LABEL_FONT, 11));
310
+ ids.push(addText(surface, sx, midY - 8, SW, row.letter, NOTATION_NEUTRALS.ink, LABEL_FONT, 11));
310
311
  }
311
312
  else if (row.dashed) {
312
313
  // Two 6-unit segments with a 4-unit gap: the same 16 units as a solid
@@ -1,3 +1,4 @@
1
+ import { NOTATION_NEUTRALS } from '@formicoidea/labre-core/shared/consts';
1
2
  import { html, svg } from 'lit';
2
3
  /**
3
4
  * Contextual-toolbar glyph — "generate the legend of what is on this
@@ -40,12 +41,12 @@ export const eventStormingToolbarIcon = svg `<svg width="100%" height="100%" vie
40
41
  export const coreDomainToolbarIcon = svg `<svg width="100%" height="100%" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
41
42
  <rect x="10" y="8" width="38" height="38" fill="#4d9900" fill-opacity="0.55"/>
42
43
  <rect x="10" y="8" width="14" height="38" fill="#9933ff" fill-opacity="0.55"/>
43
- <path d="M10 46 V8 M10 46 H48" stroke="#1f2328" stroke-width="2.4" stroke-linecap="round"/>
44
+ <path d="M10 46 V8 M10 46 H48" stroke="${NOTATION_NEUTRALS.frameInk}" stroke-width="2.4" stroke-linecap="round"/>
44
45
  <circle cx="38" cy="18" r="4" fill="#9933ff"/>
45
46
  </svg>`;
46
47
  /** Senior-button glyph — Context Map (two bubbles + relation). */
47
48
  export const contextMapToolbarIcon = svg `<svg width="100%" height="100%" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
48
49
  <rect x="6" y="10" width="22" height="14" rx="7" fill="#e6f0fa" stroke="#2f6fb0" stroke-width="1.6"/>
49
50
  <rect x="28" y="32" width="22" height="14" rx="7" fill="#e6f0fa" stroke="#2f6fb0" stroke-width="1.6"/>
50
- <path d="M20 24 L34 32" stroke="#1f2328" stroke-width="1.8"/>
51
+ <path d="M20 24 L34 32" stroke="${NOTATION_NEUTRALS.ink}" stroke-width="1.8"/>
51
52
  </svg>`;
@@ -0,0 +1,59 @@
1
+ import type { ChromeWording } from '@formicoidea/labre-core/shared/services';
2
+ import type { TranslationKeyManifestEntry } from '@formicoidea/labre-core/std';
3
+ /**
4
+ * The i18n key an Event Storming sticky's default label is asked of the
5
+ * host's catalogue under, for the given `ES_STICKIES` / hotspot kind.
6
+ * Exported so `ddd-event-storming/commands.ts` derives the SAME key at
7
+ * placement rather than restating the derivation.
8
+ */
9
+ export declare const esStickySeedKey: (kind: string) => string;
10
+ /**
11
+ * The i18n key a Team Topologies marker's default label is asked of the
12
+ * host's catalogue under, for the given `TEAM_TOPOLOGIES` kind. Exported so
13
+ * `ddd-core-domain/commands.ts` derives the SAME key at placement.
14
+ */
15
+ export declare const teamTopologySeedKey: (kind: string) => string;
16
+ /**
17
+ * The i18n key a Core Domain dot's default label is asked of the host's
18
+ * catalogue under, for the given `CD_SUBDOMAINS` kind. Exported so
19
+ * `ddd-core-domain/commands.ts` derives the SAME key at placement.
20
+ */
21
+ export declare const cdSubdomainSeedKey: (kind: string) => string;
22
+ /**
23
+ * The seeds baked into an Event Storming sticky at creation
24
+ * (`ddd-event-storming/commands.ts`), derived from the shared palette rather
25
+ * than restated — a tenth sticky kind added to {@link ES_STICKIES} gets its
26
+ * seed key with no edit here.
27
+ *
28
+ * This TABLE lives in `ddd-shared` because the palette it is derived from
29
+ * does; the KEYS still name the framework whose creation action actually
30
+ * writes the text, matching `com.labre.<framework>.seed.<slug>` — nothing here
31
+ * invents a "ddd-shared" framework.
32
+ */
33
+ export declare const ES_STICKY_SEEDS: ChromeWording[];
34
+ /**
35
+ * The seed baked into a Team Topologies interaction-mode marker at creation
36
+ * (`ddd-core-domain/commands.ts`), derived from {@link TEAM_TOPOLOGIES}.
37
+ */
38
+ export declare const TEAM_TOPOLOGY_SEEDS: ChromeWording[];
39
+ /**
40
+ * The seed baked into a Core Domain sub-domain / bounded-context dot at
41
+ * creation (`ddd-core-domain/commands.ts`), derived from {@link CD_SUBDOMAINS}.
42
+ */
43
+ export declare const CD_SUBDOMAIN_SEEDS: ChromeWording[];
44
+ /**
45
+ * Every seed derived from a palette THIS package owns, regardless of which DDD
46
+ * framework's creation action writes it. `ddd-shared` carries no
47
+ * `…TranslationEntries` of its own (it registers no command, no role, nothing
48
+ * the manifest walks) — each of the frameworks above spreads this WHOLE list
49
+ * into its own `…TranslationEntries` (`mergeTranslationEntries` de-duplicates
50
+ * the ones it does not use), which is what keeps a DDD framework from ever
51
+ * importing another one just to reach a shared table.
52
+ *
53
+ * Not `TEAM_TOPOLOGIES` / `CD_SUBDOMAINS`-only or `ES_STICKIES`-only: a
54
+ * framework that does not use a slice of this table today may tomorrow (a
55
+ * Context Map that starts drawing Team Topologies markers, say), and the
56
+ * manifest test only cares that every entry here is used by SOME source file —
57
+ * never that every framework that lists it also uses it.
58
+ */
59
+ export declare const dddSharedTranslationEntries: TranslationKeyManifestEntry[];
@@ -0,0 +1,70 @@
1
+ import { CD_SUBDOMAINS, ES_HOTSPOT, ES_STICKIES, TEAM_TOPOLOGIES, } from './shared/consts.js';
2
+ /**
3
+ * camelCase → kebab-case, the same WS2 derivation each framework's own role
4
+ * table uses (see `ddd-event-storming/roles.ts`'s `kebab`).
5
+ */
6
+ const kebab = (kind) => kind.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`);
7
+ /**
8
+ * The i18n key an Event Storming sticky's default label is asked of the
9
+ * host's catalogue under, for the given `ES_STICKIES` / hotspot kind.
10
+ * Exported so `ddd-event-storming/commands.ts` derives the SAME key at
11
+ * placement rather than restating the derivation.
12
+ */
13
+ export const esStickySeedKey = (kind) => `com.labre.ddd-event-storming.seed.${kebab(kind)}`;
14
+ /**
15
+ * The i18n key a Team Topologies marker's default label is asked of the
16
+ * host's catalogue under, for the given `TEAM_TOPOLOGIES` kind. Exported so
17
+ * `ddd-core-domain/commands.ts` derives the SAME key at placement.
18
+ */
19
+ export const teamTopologySeedKey = (kind) => `com.labre.ddd-core-domain.seed.${kind}`;
20
+ /**
21
+ * The i18n key a Core Domain dot's default label is asked of the host's
22
+ * catalogue under, for the given `CD_SUBDOMAINS` kind. Exported so
23
+ * `ddd-core-domain/commands.ts` derives the SAME key at placement.
24
+ */
25
+ export const cdSubdomainSeedKey = (kind) => `com.labre.ddd-core-domain.seed.${kebab(kind)}`;
26
+ /**
27
+ * The seeds baked into an Event Storming sticky at creation
28
+ * (`ddd-event-storming/commands.ts`), derived from the shared palette rather
29
+ * than restated — a tenth sticky kind added to {@link ES_STICKIES} gets its
30
+ * seed key with no edit here.
31
+ *
32
+ * This TABLE lives in `ddd-shared` because the palette it is derived from
33
+ * does; the KEYS still name the framework whose creation action actually
34
+ * writes the text, matching `com.labre.<framework>.seed.<slug>` — nothing here
35
+ * invents a "ddd-shared" framework.
36
+ */
37
+ export const ES_STICKY_SEEDS = [
38
+ ...ES_STICKIES.map((preset) => [esStickySeedKey(preset.kind), preset.label]),
39
+ [esStickySeedKey('hotspot'), ES_HOTSPOT.label],
40
+ ];
41
+ /**
42
+ * The seed baked into a Team Topologies interaction-mode marker at creation
43
+ * (`ddd-core-domain/commands.ts`), derived from {@link TEAM_TOPOLOGIES}.
44
+ */
45
+ export const TEAM_TOPOLOGY_SEEDS = TEAM_TOPOLOGIES.map((preset) => [teamTopologySeedKey(preset.kind), preset.label]);
46
+ /**
47
+ * The seed baked into a Core Domain sub-domain / bounded-context dot at
48
+ * creation (`ddd-core-domain/commands.ts`), derived from {@link CD_SUBDOMAINS}.
49
+ */
50
+ export const CD_SUBDOMAIN_SEEDS = CD_SUBDOMAINS.map((preset) => [cdSubdomainSeedKey(preset.kind), preset.label]);
51
+ /**
52
+ * Every seed derived from a palette THIS package owns, regardless of which DDD
53
+ * framework's creation action writes it. `ddd-shared` carries no
54
+ * `…TranslationEntries` of its own (it registers no command, no role, nothing
55
+ * the manifest walks) — each of the frameworks above spreads this WHOLE list
56
+ * into its own `…TranslationEntries` (`mergeTranslationEntries` de-duplicates
57
+ * the ones it does not use), which is what keeps a DDD framework from ever
58
+ * importing another one just to reach a shared table.
59
+ *
60
+ * Not `TEAM_TOPOLOGIES` / `CD_SUBDOMAINS`-only or `ES_STICKIES`-only: a
61
+ * framework that does not use a slice of this table today may tomorrow (a
62
+ * Context Map that starts drawing Team Topologies markers, say), and the
63
+ * manifest test only cares that every entry here is used by SOME source file —
64
+ * never that every framework that lists it also uses it.
65
+ */
66
+ export const dddSharedTranslationEntries = [
67
+ ...ES_STICKY_SEEDS,
68
+ ...TEAM_TOPOLOGY_SEEDS,
69
+ ...CD_SUBDOMAIN_SEEDS,
70
+ ].map(([key, fallback]) => ({ key, fallback, source: 'seed' }));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@formicoidea/labre-ddd-shared",
3
3
  "description": "Labre ddd-shared — shared building blocks for @formicoidea/labre-core frameworks.",
4
- "version": "0.39.3",
4
+ "version": "0.41.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "author": "lajola",
@@ -19,7 +19,7 @@
19
19
  "dist"
20
20
  ],
21
21
  "dependencies": {
22
- "@formicoidea/labre-core": "0.39.3",
22
+ "@formicoidea/labre-core": "0.41.0",
23
23
  "lit": "^3.2.0"
24
24
  }
25
25
  }