@diagrammo/dgmo 0.21.1 → 0.22.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/README.md +16 -6
- package/dist/advanced.cjs +2003 -466
- package/dist/advanced.d.cts +5714 -0
- package/dist/advanced.d.ts +5714 -0
- package/dist/advanced.js +1999 -466
- package/dist/auto.cjs +2048 -449
- package/dist/auto.d.cts +39 -0
- package/dist/auto.d.ts +39 -0
- package/dist/auto.js +121 -121
- package/dist/auto.mjs +2050 -450
- package/dist/cli.cjs +170 -170
- package/dist/editor.cjs +13 -16
- package/dist/editor.js +13 -16
- package/dist/highlight.cjs +15 -13
- package/dist/highlight.js +15 -13
- package/dist/index.cjs +2032 -435
- package/dist/index.d.cts +339 -0
- package/dist/index.d.ts +339 -0
- package/dist/index.js +2034 -436
- package/dist/internal.cjs +2003 -466
- package/dist/internal.d.cts +5714 -0
- package/dist/internal.d.ts +5714 -0
- package/dist/internal.js +1999 -466
- package/dist/map-data/water-bodies.json +1 -0
- package/docs/language-reference.md +20 -9
- package/gallery/fixtures/map-categorical-world.dgmo +16 -0
- package/gallery/fixtures/map-categorical.dgmo +0 -1
- package/gallery/fixtures/map-choropleth.dgmo +0 -1
- package/gallery/fixtures/map-coastline.dgmo +7 -0
- package/gallery/fixtures/map-colorize.dgmo +11 -0
- package/gallery/fixtures/map-direct-color.dgmo +0 -1
- package/gallery/fixtures/map-reference-world.dgmo +11 -0
- package/gallery/fixtures/map-region-scope.dgmo +0 -3
- package/gallery/fixtures/map-route.dgmo +0 -1
- package/package.json +1 -1
- package/src/advanced.ts +12 -1
- package/src/boxes-and-lines/renderer.ts +39 -12
- package/src/cli.ts +1 -1
- package/src/completion.ts +32 -25
- package/src/cycle/renderer.ts +14 -1
- package/src/d3.ts +8 -2
- package/src/editor/highlight-api.ts +4 -0
- package/src/editor/keywords.ts +13 -16
- package/src/infra/renderer.ts +35 -7
- package/src/map/colorize.ts +54 -0
- package/src/map/context-labels.ts +429 -0
- package/src/map/data/types.ts +34 -0
- package/src/map/data/water-bodies.json +1 -0
- package/src/map/dimensions.ts +117 -0
- package/src/map/geo-query.ts +21 -3
- package/src/map/geo.ts +47 -1
- package/src/map/layout.ts +1300 -251
- package/src/map/load-data.ts +10 -2
- package/src/map/parser.ts +42 -116
- package/src/map/renderer.ts +512 -13
- package/src/map/resolved-types.ts +16 -2
- package/src/map/resolver.ts +208 -59
- package/src/map/types.ts +30 -32
- package/src/mindmap/renderer.ts +10 -1
- package/src/palettes/atlas.ts +77 -0
- package/src/palettes/blueprint.ts +73 -0
- package/src/palettes/color-utils.ts +58 -1
- package/src/palettes/index.ts +12 -3
- package/src/palettes/slate.ts +73 -0
- package/src/palettes/tidewater.ts +73 -0
- package/src/render.ts +8 -1
- package/src/tech-radar/renderer.ts +3 -0
- package/src/tech-radar/types.ts +3 -0
- package/src/utils/d3-types.ts +5 -0
- package/src/utils/legend-layout.ts +21 -4
- package/src/utils/legend-types.ts +7 -0
- package/src/utils/reserved-key-registry.ts +3 -0
- package/src/palettes/bold.ts +0 -67
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { PaletteConfig } from './types';
|
|
2
|
+
import { registerPalette } from './registry';
|
|
3
|
+
|
|
4
|
+
// ============================================================
|
|
5
|
+
// Atlas Palette Definition
|
|
6
|
+
// ============================================================
|
|
7
|
+
//
|
|
8
|
+
// Inspired by vintage classroom pull-down maps and school atlases:
|
|
9
|
+
// soft, slightly-aged political fills on warm manila paper, sepia ink
|
|
10
|
+
// borders, and a muted steel-blue "pull-down map ocean". The accent
|
|
11
|
+
// rotation is the classic set of pastels cartographers use to keep
|
|
12
|
+
// adjacent regions distinct without shouting.
|
|
13
|
+
//
|
|
14
|
+
// Light mode is the star (paper-and-ink). Dark mode shifts the ground to
|
|
15
|
+
// deep-ocean navy — the "map at night / globe" register — and brightens
|
|
16
|
+
// the same pastels so they read on the darker field.
|
|
17
|
+
|
|
18
|
+
export const atlasPalette: PaletteConfig = {
|
|
19
|
+
id: 'atlas',
|
|
20
|
+
name: 'Atlas',
|
|
21
|
+
light: {
|
|
22
|
+
bg: '#f3ead3', // warm manila / parchment
|
|
23
|
+
surface: '#ece0c0', // deeper paper (cards, panels)
|
|
24
|
+
overlay: '#e8dab8', // popovers, dropdowns
|
|
25
|
+
border: '#bcaa86', // muted sepia rule line
|
|
26
|
+
text: '#463a26', // aged sepia-brown ink
|
|
27
|
+
textMuted: '#7a6a4f', // faded annotation ink
|
|
28
|
+
textOnFillLight: '#f7f1de', // parchment (light text on dark fills)
|
|
29
|
+
textOnFillDark: '#3a2e1c', // deep ink (dark text on light fills)
|
|
30
|
+
primary: '#5b7a99', // pull-down map ocean (steel-blue)
|
|
31
|
+
secondary: '#7e9a6f', // lowland sage / celadon
|
|
32
|
+
accent: '#b07f7c', // dusty rose
|
|
33
|
+
destructive: '#b25a45', // brick / terracotta
|
|
34
|
+
colors: {
|
|
35
|
+
red: '#bf6a52', // terracotta brick
|
|
36
|
+
orange: '#cf9a5c', // map tan / ochre
|
|
37
|
+
yellow: '#cdb35e', // straw / muted lemon
|
|
38
|
+
green: '#7e9a6f', // sage / celadon lowland
|
|
39
|
+
blue: '#5b7a99', // steel-blue ocean
|
|
40
|
+
purple: '#9a7fa6', // dusty lilac / mauve
|
|
41
|
+
teal: '#6fa094', // muted seafoam
|
|
42
|
+
cyan: '#79a7b5', // shallow-water blue
|
|
43
|
+
gray: '#8a7d68', // warm taupe
|
|
44
|
+
black: '#463a26', // ink
|
|
45
|
+
white: '#ece0c0', // paper
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
dark: {
|
|
49
|
+
bg: '#1e2a33', // deep map ocean (night globe)
|
|
50
|
+
surface: '#27353f', // raised ocean
|
|
51
|
+
overlay: '#2e3d48', // popovers, dropdowns
|
|
52
|
+
border: '#3d4f5c', // depth-contour line
|
|
53
|
+
text: '#e8dcc0', // parchment ink, inverted
|
|
54
|
+
textMuted: '#a89a7d', // faded label
|
|
55
|
+
textOnFillLight: '#f7f1de', // parchment
|
|
56
|
+
textOnFillDark: '#1a242c', // deep ocean ink
|
|
57
|
+
primary: '#7ba0bf', // brighter ocean
|
|
58
|
+
secondary: '#9bb588', // sage, lifted
|
|
59
|
+
accent: '#cf9a96', // dusty rose, lifted
|
|
60
|
+
destructive: '#c9745c', // brick, lifted
|
|
61
|
+
colors: {
|
|
62
|
+
red: '#cf7a60', // terracotta
|
|
63
|
+
orange: '#d9a96a', // tan / ochre
|
|
64
|
+
yellow: '#d8c074', // straw
|
|
65
|
+
green: '#9bb588', // sage lowland
|
|
66
|
+
blue: '#7ba0bf', // ocean
|
|
67
|
+
purple: '#b59ac0', // lilac / mauve
|
|
68
|
+
teal: '#85b3a6', // seafoam
|
|
69
|
+
cyan: '#92bccb', // shallow-water blue
|
|
70
|
+
gray: '#9a8d76', // warm taupe
|
|
71
|
+
black: '#27353f', // raised ocean
|
|
72
|
+
white: '#e8dcc0', // parchment
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
registerPalette(atlasPalette);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { PaletteConfig } from './types';
|
|
2
|
+
import { registerPalette } from './registry';
|
|
3
|
+
|
|
4
|
+
// ============================================================
|
|
5
|
+
// Blueprint Palette Definition
|
|
6
|
+
// ============================================================
|
|
7
|
+
//
|
|
8
|
+
// A cyanotype engineering-drawing palette — the technical register the set
|
|
9
|
+
// was missing. Dark mode is the iconic one: chalk-pastel "colored-pencil"
|
|
10
|
+
// accents drafted on a deep blueprint-blue ground (reads unmistakably as a
|
|
11
|
+
// technical drawing — ideal for infra, C4, ER, flowcharts). Light mode is
|
|
12
|
+
// the reversed draft: blueprint-blue ink and lines on pale drafting white.
|
|
13
|
+
|
|
14
|
+
export const blueprintPalette: PaletteConfig = {
|
|
15
|
+
id: 'blueprint',
|
|
16
|
+
name: 'Blueprint',
|
|
17
|
+
light: {
|
|
18
|
+
bg: '#f4f8fb', // pale drafting white (faint cyan)
|
|
19
|
+
surface: '#e6eef4', // drafting panel
|
|
20
|
+
overlay: '#dde9f1', // popovers, dropdowns
|
|
21
|
+
border: '#aac3d6', // pale blue grid line
|
|
22
|
+
text: '#123a5e', // blueprint navy ink
|
|
23
|
+
textMuted: '#4f7390', // faint draft note
|
|
24
|
+
textOnFillLight: '#f4f8fb', // drafting white
|
|
25
|
+
textOnFillDark: '#0c2f4d', // deep blueprint navy
|
|
26
|
+
primary: '#1f5e8c', // blueprint blue
|
|
27
|
+
secondary: '#5b7d96', // steel
|
|
28
|
+
accent: '#b08a3e', // draftsman's ochre highlight
|
|
29
|
+
destructive: '#c0504d', // correction red
|
|
30
|
+
colors: {
|
|
31
|
+
red: '#c25a4e', // correction red
|
|
32
|
+
orange: '#c2823e', // ochre
|
|
33
|
+
yellow: '#c2a843', // pencil gold
|
|
34
|
+
green: '#4f8a6b', // drafting green
|
|
35
|
+
blue: '#1f5e8c', // blueprint blue
|
|
36
|
+
purple: '#6f5e96', // indigo pencil
|
|
37
|
+
teal: '#3a8a8a', // teal
|
|
38
|
+
cyan: '#3f8fb5', // cyan
|
|
39
|
+
gray: '#7e8e98', // graphite
|
|
40
|
+
black: '#123a5e', // navy ink
|
|
41
|
+
white: '#e6eef4', // panel
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
dark: {
|
|
45
|
+
bg: '#103a5e', // deep blueprint blue (cyanotype ground)
|
|
46
|
+
surface: '#16466e', // raised sheet
|
|
47
|
+
overlay: '#1c5180', // popovers, dropdowns
|
|
48
|
+
border: '#3a6f96', // grid line
|
|
49
|
+
text: '#eaf2f8', // chalk white
|
|
50
|
+
textMuted: '#9fc0d6', // faint chalk note
|
|
51
|
+
textOnFillLight: '#eaf2f8', // chalk white
|
|
52
|
+
textOnFillDark: '#0c2f4d', // deep blueprint navy
|
|
53
|
+
primary: '#7fb8d8', // chalk cyan
|
|
54
|
+
secondary: '#9fb8c8', // pale steel
|
|
55
|
+
accent: '#d8c27a', // chalk amber
|
|
56
|
+
destructive: '#e08a7a', // chalk correction red
|
|
57
|
+
colors: {
|
|
58
|
+
red: '#e0907e', // chalk red
|
|
59
|
+
orange: '#e0ab78', // chalk amber
|
|
60
|
+
yellow: '#e3d089', // chalk gold
|
|
61
|
+
green: '#93c79e', // chalk green
|
|
62
|
+
blue: '#8ec3e0', // chalk cyan-blue
|
|
63
|
+
purple: '#b6a6d8', // chalk indigo
|
|
64
|
+
teal: '#84c7c2', // chalk teal
|
|
65
|
+
cyan: '#9fd6e0', // chalk cyan
|
|
66
|
+
gray: '#aebecb', // chalk graphite
|
|
67
|
+
black: '#16466e', // raised sheet
|
|
68
|
+
white: '#eaf2f8', // chalk white
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
registerPalette(blueprintPalette);
|
|
@@ -182,7 +182,7 @@ export function relativeLuminance(hex: string): number {
|
|
|
182
182
|
* Range: 1.0 (identical) to 21.0 (black on white). Internal helper used by
|
|
183
183
|
* `contrastText`'s pastel branch.
|
|
184
184
|
*/
|
|
185
|
-
function contrastRatio(a: string, b: string): number {
|
|
185
|
+
export function contrastRatio(a: string, b: string): number {
|
|
186
186
|
const la = relativeLuminance(a);
|
|
187
187
|
const lb = relativeLuminance(b);
|
|
188
188
|
const lighter = Math.max(la, lb);
|
|
@@ -308,3 +308,60 @@ export function getSegmentColors(
|
|
|
308
308
|
hslToHex(Math.round((startHue + i * step) % 360), avgS, avgL)
|
|
309
309
|
);
|
|
310
310
|
}
|
|
311
|
+
|
|
312
|
+
// ============================================================
|
|
313
|
+
// Political map fills (map colorize, §24B)
|
|
314
|
+
// ============================================================
|
|
315
|
+
|
|
316
|
+
/** Mix-toward-surface bands (% of the raw swatch retained) for political fills,
|
|
317
|
+
* mode-aware. Colorize fills must stay ON-PALETTE — they're soft tints of the
|
|
318
|
+
* palette's OWN named hues, not wheel-generated colours. The retained-% is kept
|
|
319
|
+
* clear of the water backdrop's own blue tint (WATER_TINT_*), so a country fill
|
|
320
|
+
* never coincides with the ocean. The first band is the normal soft tint; later
|
|
321
|
+
* bands only come into play if a map needs more colours than the palette has
|
|
322
|
+
* distinct land hues (rare — first-fit coloring needs ≤6 on the shipped graphs). */
|
|
323
|
+
const POLITICAL_TINT_BANDS = {
|
|
324
|
+
light: [32, 48, 64, 80],
|
|
325
|
+
dark: [44, 58, 72, 86],
|
|
326
|
+
} as const;
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Generate `count` political-fill tints from the active palette's OWN hues
|
|
330
|
+
* (§24B colorize). Each is a palette swatch softened toward the surface, so the
|
|
331
|
+
* fills always read as that palette (Atlas tints look like Atlas, not neon wheel
|
|
332
|
+
* samples). Hues are ordered LAND-FIRST — blue/cyan (the ocean-adjacent hues) go
|
|
333
|
+
* last, so country fills never read as water; they are only reached if a map
|
|
334
|
+
* needs >6 colours (it never does — first-fit needs ≤6, palettes ship ≥6 land
|
|
335
|
+
* hues). `count` distinct colours come from walking the deduped hues; if more are
|
|
336
|
+
* needed, additional lightness BANDS of the same hues are appended (still
|
|
337
|
+
* on-palette). Deterministic; resvg-safe (hex out).
|
|
338
|
+
*/
|
|
339
|
+
export function politicalTints(
|
|
340
|
+
palette: PaletteColors,
|
|
341
|
+
count: number,
|
|
342
|
+
isDark: boolean
|
|
343
|
+
): string[] {
|
|
344
|
+
if (count <= 0) return [];
|
|
345
|
+
const base = isDark ? palette.surface : palette.bg;
|
|
346
|
+
const c = palette.colors;
|
|
347
|
+
// Land-first: greens/earth tones lead; water-like blue & cyan trail.
|
|
348
|
+
const swatches = [
|
|
349
|
+
...new Set([
|
|
350
|
+
c.green,
|
|
351
|
+
c.yellow,
|
|
352
|
+
c.orange,
|
|
353
|
+
c.purple,
|
|
354
|
+
c.red,
|
|
355
|
+
c.teal,
|
|
356
|
+
c.cyan,
|
|
357
|
+
c.blue,
|
|
358
|
+
]),
|
|
359
|
+
];
|
|
360
|
+
const bands = isDark ? POLITICAL_TINT_BANDS.dark : POLITICAL_TINT_BANDS.light;
|
|
361
|
+
const out: string[] = [];
|
|
362
|
+
for (const pct of bands) {
|
|
363
|
+
if (out.length >= count) break;
|
|
364
|
+
for (const s of swatches) out.push(mix(s, base, pct));
|
|
365
|
+
}
|
|
366
|
+
return out.slice(0, count);
|
|
367
|
+
}
|
package/src/palettes/index.ts
CHANGED
|
@@ -23,13 +23,16 @@ export {
|
|
|
23
23
|
} from './color-utils';
|
|
24
24
|
|
|
25
25
|
// Re-export palette definitions (alphabetical)
|
|
26
|
-
export {
|
|
26
|
+
export { atlasPalette } from './atlas';
|
|
27
|
+
export { blueprintPalette } from './blueprint';
|
|
27
28
|
export { catppuccinPalette } from './catppuccin';
|
|
28
29
|
export { gruvboxPalette } from './gruvbox';
|
|
29
30
|
export { nordPalette } from './nord';
|
|
30
31
|
export { oneDarkPalette } from './one-dark';
|
|
31
32
|
export { rosePinePalette } from './rose-pine';
|
|
33
|
+
export { slatePalette } from './slate';
|
|
32
34
|
export { solarizedPalette } from './solarized';
|
|
35
|
+
export { tidewaterPalette } from './tidewater';
|
|
33
36
|
export { tokyoNightPalette } from './tokyo-night';
|
|
34
37
|
|
|
35
38
|
export { draculaPalette } from './dracula';
|
|
@@ -39,7 +42,8 @@ export { monokaiPalette } from './monokai';
|
|
|
39
42
|
// Public namespace — `palettes` for use with render()
|
|
40
43
|
// ============================================================
|
|
41
44
|
|
|
42
|
-
import {
|
|
45
|
+
import { atlasPalette } from './atlas';
|
|
46
|
+
import { blueprintPalette } from './blueprint';
|
|
43
47
|
import { catppuccinPalette } from './catppuccin';
|
|
44
48
|
import { draculaPalette } from './dracula';
|
|
45
49
|
import { gruvboxPalette } from './gruvbox';
|
|
@@ -47,7 +51,9 @@ import { monokaiPalette } from './monokai';
|
|
|
47
51
|
import { nordPalette } from './nord';
|
|
48
52
|
import { oneDarkPalette } from './one-dark';
|
|
49
53
|
import { rosePinePalette } from './rose-pine';
|
|
54
|
+
import { slatePalette } from './slate';
|
|
50
55
|
import { solarizedPalette } from './solarized';
|
|
56
|
+
import { tidewaterPalette } from './tidewater';
|
|
51
57
|
import { tokyoNightPalette } from './tokyo-night';
|
|
52
58
|
|
|
53
59
|
import type { PaletteConfig } from './types';
|
|
@@ -62,6 +68,10 @@ import type { PaletteConfig } from './types';
|
|
|
62
68
|
* used by share URLs and the CLI `--palette` flag.
|
|
63
69
|
*/
|
|
64
70
|
export const palettes = {
|
|
71
|
+
atlas: atlasPalette,
|
|
72
|
+
blueprint: blueprintPalette,
|
|
73
|
+
slate: slatePalette,
|
|
74
|
+
tidewater: tidewaterPalette,
|
|
65
75
|
nord: nordPalette,
|
|
66
76
|
catppuccin: catppuccinPalette,
|
|
67
77
|
solarized: solarizedPalette,
|
|
@@ -71,5 +81,4 @@ export const palettes = {
|
|
|
71
81
|
rosePine: rosePinePalette,
|
|
72
82
|
dracula: draculaPalette,
|
|
73
83
|
monokai: monokaiPalette,
|
|
74
|
-
bold: boldPalette,
|
|
75
84
|
} as const satisfies Record<string, PaletteConfig>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { PaletteConfig } from './types';
|
|
2
|
+
import { registerPalette } from './registry';
|
|
3
|
+
|
|
4
|
+
// ============================================================
|
|
5
|
+
// Slate Palette Definition
|
|
6
|
+
// ============================================================
|
|
7
|
+
//
|
|
8
|
+
// A restrained, presentation-grade palette for professional decks and
|
|
9
|
+
// reports — the "not very stylistic" option done tastefully. Clean white
|
|
10
|
+
// (or deep slate) ground, one confident corporate blue, neutral cool-gray
|
|
11
|
+
// surfaces, and a categorical rotation tuned to a single perceived weight
|
|
12
|
+
// so no series shouts. Replaces the harsh primary-RGB feel of "bold".
|
|
13
|
+
|
|
14
|
+
export const slatePalette: PaletteConfig = {
|
|
15
|
+
id: 'slate',
|
|
16
|
+
name: 'Slate',
|
|
17
|
+
light: {
|
|
18
|
+
bg: '#ffffff', // clean slide white
|
|
19
|
+
surface: '#f3f5f8', // light cool-gray panel
|
|
20
|
+
overlay: '#eaeef3', // popovers, dropdowns
|
|
21
|
+
border: '#d4dae1', // hairline rule
|
|
22
|
+
text: '#1f2933', // near-black slate (softer than pure black)
|
|
23
|
+
textMuted: '#5b6672', // secondary label
|
|
24
|
+
textOnFillLight: '#ffffff', // light text on dark fills
|
|
25
|
+
textOnFillDark: '#1f2933', // dark text on light fills
|
|
26
|
+
primary: '#3b6ea5', // confident corporate blue
|
|
27
|
+
secondary: '#5b6672', // slate gray
|
|
28
|
+
accent: '#3a9188', // muted teal accent
|
|
29
|
+
destructive: '#c0504d', // brick red
|
|
30
|
+
colors: {
|
|
31
|
+
red: '#c0504d', // brick
|
|
32
|
+
orange: '#cc7a33', // muted amber
|
|
33
|
+
yellow: '#c9a227', // gold (not neon)
|
|
34
|
+
green: '#5b9357', // forest / sage
|
|
35
|
+
blue: '#3b6ea5', // corporate blue
|
|
36
|
+
purple: '#7d5ba6', // muted violet
|
|
37
|
+
teal: '#3a9188', // teal
|
|
38
|
+
cyan: '#4f96c4', // steel cyan
|
|
39
|
+
gray: '#7e8a97', // cool gray
|
|
40
|
+
black: '#1f2933', // slate ink
|
|
41
|
+
white: '#f3f5f8', // panel
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
dark: {
|
|
45
|
+
bg: '#161b22', // deep slate (keynote dark)
|
|
46
|
+
surface: '#202833', // raised panel
|
|
47
|
+
overlay: '#29323e', // popovers, dropdowns
|
|
48
|
+
border: '#38424f', // divider
|
|
49
|
+
text: '#e6eaef', // off-white
|
|
50
|
+
textMuted: '#9aa5b1', // secondary label
|
|
51
|
+
textOnFillLight: '#ffffff', // light text on dark fills
|
|
52
|
+
textOnFillDark: '#161b22', // dark text on light fills
|
|
53
|
+
primary: '#5b9bd5', // lifted corporate blue
|
|
54
|
+
secondary: '#8593a3', // slate gray, lifted
|
|
55
|
+
accent: '#45b3a3', // teal, lifted
|
|
56
|
+
destructive: '#e07b6e', // brick, lifted
|
|
57
|
+
colors: {
|
|
58
|
+
red: '#e07b6e', // brick
|
|
59
|
+
orange: '#e0975a', // amber
|
|
60
|
+
yellow: '#d9bd5a', // gold
|
|
61
|
+
green: '#74b56e', // forest / sage
|
|
62
|
+
blue: '#5b9bd5', // corporate blue
|
|
63
|
+
purple: '#a585c9', // violet
|
|
64
|
+
teal: '#45b3a3', // teal
|
|
65
|
+
cyan: '#62b0d9', // steel cyan
|
|
66
|
+
gray: '#95a1ae', // cool gray
|
|
67
|
+
black: '#202833', // raised panel
|
|
68
|
+
white: '#e6eaef', // off-white
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
registerPalette(slatePalette);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { PaletteConfig } from './types';
|
|
2
|
+
import { registerPalette } from './registry';
|
|
3
|
+
|
|
4
|
+
// ============================================================
|
|
5
|
+
// Tidewater Palette Definition
|
|
6
|
+
// ============================================================
|
|
7
|
+
//
|
|
8
|
+
// A nautical, maritime-chart palette — on-brand with Diagrammo's seafaring
|
|
9
|
+
// voice. Weathered sea-mist paper with deep ship's-log navy ink, rope/manila
|
|
10
|
+
// tan, brass, signal-flag red, and sea-glass greens (light). Dark mode dives
|
|
11
|
+
// to a night-harbor deep-sea ground with the same rigging lifted to read on
|
|
12
|
+
// the dark water.
|
|
13
|
+
|
|
14
|
+
export const tidewaterPalette: PaletteConfig = {
|
|
15
|
+
id: 'tidewater',
|
|
16
|
+
name: 'Tidewater',
|
|
17
|
+
light: {
|
|
18
|
+
bg: '#eceff0', // weathered sea-mist paper
|
|
19
|
+
surface: '#e0e4e3', // worn deck panel
|
|
20
|
+
overlay: '#dadfdf', // popovers, dropdowns
|
|
21
|
+
border: '#a9b2b3', // muted slate rule
|
|
22
|
+
text: '#18313f', // ship's-log navy ink
|
|
23
|
+
textMuted: '#51636b', // faded log entry
|
|
24
|
+
textOnFillLight: '#f3f5f3', // weathered white
|
|
25
|
+
textOnFillDark: '#162c38', // deep navy
|
|
26
|
+
primary: '#1f4e6b', // deep-sea navy
|
|
27
|
+
secondary: '#b08a4f', // rope / manila tan
|
|
28
|
+
accent: '#c69a3e', // brass
|
|
29
|
+
destructive: '#c1433a', // signal-flag red
|
|
30
|
+
colors: {
|
|
31
|
+
red: '#c1433a', // signal-flag red
|
|
32
|
+
orange: '#cc7a38', // weathered amber
|
|
33
|
+
yellow: '#d6bf5a', // brass gold
|
|
34
|
+
green: '#4f8a6b', // sea-glass green
|
|
35
|
+
blue: '#1f4e6b', // deep-sea navy
|
|
36
|
+
purple: '#6a5a8c', // twilight harbor
|
|
37
|
+
teal: '#3d8c8c', // sea-glass teal
|
|
38
|
+
cyan: '#4f9bb5', // shallow water
|
|
39
|
+
gray: '#8a8d86', // driftwood gray
|
|
40
|
+
black: '#18313f', // navy ink
|
|
41
|
+
white: '#e0e4e3', // deck panel
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
dark: {
|
|
45
|
+
bg: '#0f2230', // night-harbor deep sea
|
|
46
|
+
surface: '#16303f', // raised hull
|
|
47
|
+
overlay: '#1d3a4a', // popovers, dropdowns
|
|
48
|
+
border: '#2c4856', // rigging line
|
|
49
|
+
text: '#e6ebe8', // weathered white
|
|
50
|
+
textMuted: '#9aaab0', // faded label
|
|
51
|
+
textOnFillLight: '#f3f5f3', // weathered white
|
|
52
|
+
textOnFillDark: '#0f2230', // deep sea
|
|
53
|
+
primary: '#4f9bc4', // lifted sea blue
|
|
54
|
+
secondary: '#c9a46a', // rope tan, lifted
|
|
55
|
+
accent: '#d9b25a', // brass, lifted
|
|
56
|
+
destructive: '#e06a5e', // signal red, lifted
|
|
57
|
+
colors: {
|
|
58
|
+
red: '#e06a5e', // signal-flag red
|
|
59
|
+
orange: '#df9a52', // amber
|
|
60
|
+
yellow: '#e0c662', // brass gold
|
|
61
|
+
green: '#6fb58c', // sea-glass green
|
|
62
|
+
blue: '#4f9bc4', // sea blue
|
|
63
|
+
purple: '#9486bf', // twilight harbor
|
|
64
|
+
teal: '#5cb0ac', // sea-glass teal
|
|
65
|
+
cyan: '#62b4cf', // shallow water
|
|
66
|
+
gray: '#9aa39c', // driftwood gray
|
|
67
|
+
black: '#16303f', // raised hull
|
|
68
|
+
white: '#e6ebe8', // weathered white
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
registerPalette(tidewaterPalette);
|
package/src/render.ts
CHANGED
|
@@ -88,6 +88,9 @@ export async function render(
|
|
|
88
88
|
legendState?: { activeGroup?: string; hiddenAttributes?: string[] };
|
|
89
89
|
/** View state for export — controls interactive state (collapse, swimlanes, etc.) */
|
|
90
90
|
viewState?: CompactViewState;
|
|
91
|
+
/** Bundled map data for `map` charts in the browser, where the Node fs
|
|
92
|
+
* `loadMapData()` seam can't run. CLI/SSR omit this and fall back to fs. */
|
|
93
|
+
mapData?: import('./map/resolved-types').MapData;
|
|
91
94
|
}
|
|
92
95
|
): Promise<{ svg: string; diagnostics: DgmoError[] }> {
|
|
93
96
|
const theme = options?.theme ?? 'light';
|
|
@@ -133,6 +136,7 @@ export async function render(
|
|
|
133
136
|
c4Container: options.c4Container,
|
|
134
137
|
}),
|
|
135
138
|
...(options?.tagGroup !== undefined && { tagGroup: options.tagGroup }),
|
|
139
|
+
...(options?.mapData !== undefined && { mapData: options.mapData }),
|
|
136
140
|
});
|
|
137
141
|
|
|
138
142
|
// The map pipeline resolves names AFTER parsing (gazetteer/ISO lookup), so its
|
|
@@ -149,7 +153,10 @@ export async function render(
|
|
|
149
153
|
import('./map/load-data'),
|
|
150
154
|
]
|
|
151
155
|
);
|
|
152
|
-
|
|
156
|
+
// Prefer injected data (browser); fall back to the fs loader (CLI/SSR).
|
|
157
|
+
const data = options?.mapData ?? (await loadMapData());
|
|
158
|
+
// resolveMap seeds its diagnostics with the parser's, so this is a superset.
|
|
159
|
+
// (The layout stage has no diagnostics producer, so there is nothing to merge.)
|
|
153
160
|
diagnostics = [...resolveMap(parseMap(content), data).diagnostics];
|
|
154
161
|
} catch {
|
|
155
162
|
/* asset load failed — keep the parser diagnostics */
|
package/src/tech-radar/types.ts
CHANGED
|
@@ -80,4 +80,7 @@ export interface TechRadarRenderOptions {
|
|
|
80
80
|
activeLine?: number | null;
|
|
81
81
|
/** True when rendering for export (PNG/SVG/PDF) — controls whether collapsed legend pills and cog are stripped. */
|
|
82
82
|
exportMode?: boolean;
|
|
83
|
+
/** When 'app', the Blip Legend toggle is hosted by the app overlay strip
|
|
84
|
+
* (inline gear suppressed, controls row + anchor reserved). */
|
|
85
|
+
controlsHost?: 'app' | 'inline';
|
|
83
86
|
}
|
package/src/utils/d3-types.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
export interface D3ExportDimensions {
|
|
2
2
|
width?: number;
|
|
3
3
|
height?: number;
|
|
4
|
+
/** Map-only: when true, the map renderer suppresses its global stretch-fill and
|
|
5
|
+
* contain-fits (letterbox) instead. Set by `mapExportDimensions` when the export
|
|
6
|
+
* canvas was clamped/floored away from the map's content aspect, so the
|
|
7
|
+
* off-aspect canvas doesn't re-distort. Ignored by all non-map renderers. */
|
|
8
|
+
preferContain?: boolean;
|
|
4
9
|
}
|
|
@@ -248,6 +248,18 @@ export function controlsGroupCapsuleWidth(
|
|
|
248
248
|
return w;
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
+
/** True when the controlsGroup should be hosted by the app overlay strip
|
|
252
|
+
* (gear suppressed, controls row + anchor reserved) rather than drawn inline.
|
|
253
|
+
* Never gates on the export path. */
|
|
254
|
+
function isAppHostedControls(config: LegendConfig, isExport: boolean): boolean {
|
|
255
|
+
return (
|
|
256
|
+
!isExport &&
|
|
257
|
+
config.controlsHost === 'app' &&
|
|
258
|
+
!!config.controlsGroup &&
|
|
259
|
+
config.controlsGroup.toggles.length > 0
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
251
263
|
function buildControlsGroupLayout(
|
|
252
264
|
config: LegendConfig,
|
|
253
265
|
state: LegendState
|
|
@@ -325,6 +337,9 @@ export function computeLegendLayout(
|
|
|
325
337
|
const { groups, controls: configControls, mode } = config;
|
|
326
338
|
const isExport = mode === 'export';
|
|
327
339
|
|
|
340
|
+
// App-hosted controls: suppress the inline gear, reserve a header row + anchor.
|
|
341
|
+
const gated = isAppHostedControls(config, isExport);
|
|
342
|
+
|
|
328
343
|
// Filter groups for export: only active group shown
|
|
329
344
|
const activeGroupName = state.activeGroup?.toLowerCase() ?? null;
|
|
330
345
|
|
|
@@ -339,10 +354,9 @@ export function computeLegendLayout(
|
|
|
339
354
|
};
|
|
340
355
|
}
|
|
341
356
|
|
|
342
|
-
// Controls group (
|
|
343
|
-
const controlsGroupLayout =
|
|
344
|
-
? undefined
|
|
345
|
-
: buildControlsGroupLayout(config, state);
|
|
357
|
+
// Controls group (gear): suppressed in export and when app-hosted.
|
|
358
|
+
const controlsGroupLayout =
|
|
359
|
+
isExport || gated ? undefined : buildControlsGroupLayout(config, state);
|
|
346
360
|
|
|
347
361
|
const visibleGroups = config.showEmptyGroups
|
|
348
362
|
? groups
|
|
@@ -469,6 +483,9 @@ export function computeLegendLayout(
|
|
|
469
483
|
controlsGroupLayout
|
|
470
484
|
);
|
|
471
485
|
|
|
486
|
+
// App-hosted controls: the controlsGroup was dropped above (no gear), and the
|
|
487
|
+
// app overlay strip pins itself to the top edge of the preview — dgmo reserves
|
|
488
|
+
// no row and emits no anchor, so the chart reclaims that space.
|
|
472
489
|
const height = rows.length * LEGEND_HEIGHT;
|
|
473
490
|
const width = containerWidth;
|
|
474
491
|
|
|
@@ -112,6 +112,13 @@ export interface LegendConfig {
|
|
|
112
112
|
* group). Lets the user click a sibling to switch the active group. Default
|
|
113
113
|
* false (legacy: when one group is active the others are hidden). */
|
|
114
114
|
showInactivePills?: boolean;
|
|
115
|
+
/** Where the controlsGroup is hosted. Default (undefined / 'inline') renders
|
|
116
|
+
* the in-SVG gear exactly as before — every non-app consumer (Obsidian,
|
|
117
|
+
* site, remark-family, CLI) is unaffected. When 'app', the controlsGroup is
|
|
118
|
+
* dropped entirely (no gear, no reserved row): the app overlay strip owns the
|
|
119
|
+
* controls, pinned to the top edge of the preview. App preview only; never
|
|
120
|
+
* set on the export path. */
|
|
121
|
+
controlsHost?: 'app' | 'inline';
|
|
115
122
|
}
|
|
116
123
|
|
|
117
124
|
export interface LegendPalette {
|
|
@@ -85,6 +85,9 @@ export const MAP_REGISTRY: ReservedKeyRegistry = staticRegistry([
|
|
|
85
85
|
'value',
|
|
86
86
|
'label',
|
|
87
87
|
'style',
|
|
88
|
+
// `surface:` was removed in the 2026-06-02 defaults-on review — it is no longer
|
|
89
|
+
// a recognized metadata key (the route/edge surface feature was cut; §24B.7).
|
|
90
|
+
// A stray `surface: water` is no longer captured as a reserved key.
|
|
88
91
|
]);
|
|
89
92
|
|
|
90
93
|
export const ORG_REGISTRY: ReservedKeyRegistry = staticRegistry([
|
package/src/palettes/bold.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import type { PaletteConfig } from './types';
|
|
2
|
-
import { registerPalette } from './registry';
|
|
3
|
-
|
|
4
|
-
// ============================================================
|
|
5
|
-
// Bold Palette Definition
|
|
6
|
-
// ============================================================
|
|
7
|
-
|
|
8
|
-
export const boldPalette: PaletteConfig = {
|
|
9
|
-
id: 'bold',
|
|
10
|
-
name: 'Bold',
|
|
11
|
-
light: {
|
|
12
|
-
bg: '#ffffff',
|
|
13
|
-
surface: '#f0f0f0',
|
|
14
|
-
overlay: '#f0f0f0',
|
|
15
|
-
border: '#cccccc',
|
|
16
|
-
text: '#000000',
|
|
17
|
-
textMuted: '#666666',
|
|
18
|
-
textOnFillLight: '#ffffff',
|
|
19
|
-
textOnFillDark: '#000000',
|
|
20
|
-
primary: '#0000ff',
|
|
21
|
-
secondary: '#ff00ff',
|
|
22
|
-
accent: '#00cccc',
|
|
23
|
-
destructive: '#ff0000',
|
|
24
|
-
colors: {
|
|
25
|
-
red: '#ff0000',
|
|
26
|
-
orange: '#ff8000',
|
|
27
|
-
yellow: '#ffcc00',
|
|
28
|
-
green: '#00cc00',
|
|
29
|
-
blue: '#0000ff',
|
|
30
|
-
purple: '#cc00cc',
|
|
31
|
-
teal: '#008080',
|
|
32
|
-
cyan: '#00cccc',
|
|
33
|
-
gray: '#808080',
|
|
34
|
-
black: '#000000',
|
|
35
|
-
white: '#f0f0f0',
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
dark: {
|
|
39
|
-
bg: '#000000',
|
|
40
|
-
surface: '#111111',
|
|
41
|
-
overlay: '#1a1a1a',
|
|
42
|
-
border: '#333333',
|
|
43
|
-
text: '#ffffff',
|
|
44
|
-
textMuted: '#aaaaaa',
|
|
45
|
-
textOnFillLight: '#ffffff',
|
|
46
|
-
textOnFillDark: '#000000',
|
|
47
|
-
primary: '#00ccff',
|
|
48
|
-
secondary: '#ff00ff',
|
|
49
|
-
accent: '#ffff00',
|
|
50
|
-
destructive: '#ff0000',
|
|
51
|
-
colors: {
|
|
52
|
-
red: '#ff0000',
|
|
53
|
-
orange: '#ff8000',
|
|
54
|
-
yellow: '#ffff00',
|
|
55
|
-
green: '#00ff00',
|
|
56
|
-
blue: '#0066ff',
|
|
57
|
-
purple: '#ff00ff',
|
|
58
|
-
teal: '#00cccc',
|
|
59
|
-
cyan: '#00ffff',
|
|
60
|
-
gray: '#808080',
|
|
61
|
-
black: '#111111',
|
|
62
|
-
white: '#ffffff',
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
registerPalette(boldPalette);
|