@steffolino/diagram-kit-core 0.1.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/LICENSE +21 -0
- package/README.md +22 -0
- package/dist/cssPalette.d.ts +15 -0
- package/dist/cssPalette.d.ts.map +1 -0
- package/dist/cssPalette.js +37 -0
- package/dist/cssPalette.js.map +1 -0
- package/dist/cycleLayout.d.ts +13 -0
- package/dist/cycleLayout.d.ts.map +1 -0
- package/dist/cycleLayout.js +174 -0
- package/dist/cycleLayout.js.map +1 -0
- package/dist/detailText.d.ts +5 -0
- package/dist/detailText.d.ts.map +1 -0
- package/dist/detailText.js +34 -0
- package/dist/detailText.js.map +1 -0
- package/dist/graph.d.ts +52 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +30 -0
- package/dist/graph.js.map +1 -0
- package/dist/graph.test.d.ts +2 -0
- package/dist/graph.test.d.ts.map +1 -0
- package/dist/graph.test.js +33 -0
- package/dist/graph.test.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +46 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +57 -0
- package/dist/layout.js.map +1 -0
- package/dist/layout.test.d.ts +2 -0
- package/dist/layout.test.d.ts.map +1 -0
- package/dist/layout.test.js +72 -0
- package/dist/layout.test.js.map +1 -0
- package/dist/path.d.ts +25 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +60 -0
- package/dist/path.js.map +1 -0
- package/dist/presets.d.ts +15 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +211 -0
- package/dist/presets.js.map +1 -0
- package/dist/stackLayout.d.ts +22 -0
- package/dist/stackLayout.d.ts.map +1 -0
- package/dist/stackLayout.js +47 -0
- package/dist/stackLayout.js.map +1 -0
- package/dist/stackLayout.test.d.ts +2 -0
- package/dist/stackLayout.test.d.ts.map +1 -0
- package/dist/stackLayout.test.js +48 -0
- package/dist/stackLayout.test.js.map +1 -0
- package/dist/structuralLayout.d.ts +30 -0
- package/dist/structuralLayout.d.ts.map +1 -0
- package/dist/structuralLayout.js +117 -0
- package/dist/structuralLayout.js.map +1 -0
- package/dist/structuralLayout.test.d.ts +2 -0
- package/dist/structuralLayout.test.d.ts.map +1 -0
- package/dist/structuralLayout.test.js +74 -0
- package/dist/structuralLayout.test.js.map +1 -0
- package/dist/textWidth.d.ts +18 -0
- package/dist/textWidth.d.ts.map +1 -0
- package/dist/textWidth.js +50 -0
- package/dist/textWidth.js.map +1 -0
- package/dist/theme.d.ts +68 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +94 -0
- package/dist/theme.js.map +1 -0
- package/package.json +51 -0
package/dist/layout.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import dagre from '@dagrejs/dagre';
|
|
2
|
+
import { estimateNodeWidth } from './textWidth.js';
|
|
3
|
+
import { detailHeight } from './detailText.js';
|
|
4
|
+
const DEFAULTS = {
|
|
5
|
+
showDetails: false,
|
|
6
|
+
direction: 'TB',
|
|
7
|
+
nodeWidth: 160,
|
|
8
|
+
maxNodeWidth: 420,
|
|
9
|
+
nodeSizing: 'responsive',
|
|
10
|
+
nodeHeight: 48,
|
|
11
|
+
nodeSpacing: 40,
|
|
12
|
+
rankSpacing: 80,
|
|
13
|
+
};
|
|
14
|
+
/** Runs dagre's layered/DAG layout over a normalized graph and returns absolute pixel positions. */
|
|
15
|
+
export function layoutGraph(graph, options = {}) {
|
|
16
|
+
const opts = { ...DEFAULTS, ...options };
|
|
17
|
+
const g = new dagre.graphlib.Graph({ multigraph: true });
|
|
18
|
+
g.setGraph({
|
|
19
|
+
rankdir: opts.direction,
|
|
20
|
+
nodesep: opts.nodeSpacing,
|
|
21
|
+
ranksep: opts.rankSpacing,
|
|
22
|
+
});
|
|
23
|
+
g.setDefaultEdgeLabel(() => ({}));
|
|
24
|
+
for (const node of graph.nodes) {
|
|
25
|
+
const width = estimateNodeWidth(node.label, node.badge, {
|
|
26
|
+
minWidth: opts.nodeWidth,
|
|
27
|
+
maxWidth: opts.nodeSizing === 'fixed' ? opts.nodeWidth : opts.maxNodeWidth,
|
|
28
|
+
});
|
|
29
|
+
g.setNode(node.id, { width, height: opts.nodeHeight + detailHeight(node, width, opts.showDetails) });
|
|
30
|
+
}
|
|
31
|
+
for (const edge of graph.edges) {
|
|
32
|
+
g.setEdge(edge.source, edge.target, {}, edge.id);
|
|
33
|
+
}
|
|
34
|
+
dagre.layout(g);
|
|
35
|
+
const nodes = graph.nodes.map((node) => {
|
|
36
|
+
const positioned = g.node(node.id);
|
|
37
|
+
return {
|
|
38
|
+
id: node.id,
|
|
39
|
+
x: positioned.x,
|
|
40
|
+
y: positioned.y,
|
|
41
|
+
width: positioned.width,
|
|
42
|
+
height: positioned.height,
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
const edges = graph.edges.map((edge) => {
|
|
46
|
+
const edgeData = g.edge({ v: edge.source, w: edge.target, name: edge.id });
|
|
47
|
+
return { id: edge.id, points: edgeData.points };
|
|
48
|
+
});
|
|
49
|
+
const graphLabel = g.graph();
|
|
50
|
+
return {
|
|
51
|
+
nodes,
|
|
52
|
+
edges,
|
|
53
|
+
width: graphLabel.width ?? 0,
|
|
54
|
+
height: graphLabel.height ?? 0,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.test.d.ts","sourceRoot":"","sources":["../src/layout.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { createGraph } from './graph.js';
|
|
3
|
+
import { layoutGraph } from './layout.js';
|
|
4
|
+
describe('layoutGraph', () => {
|
|
5
|
+
it('positions every node and preserves edge count', () => {
|
|
6
|
+
const graph = createGraph([
|
|
7
|
+
{ id: 'a', label: 'A' },
|
|
8
|
+
{ id: 'b', label: 'B' },
|
|
9
|
+
{ id: 'c', label: 'C' },
|
|
10
|
+
], [
|
|
11
|
+
{ id: 'a->b', source: 'a', target: 'b' },
|
|
12
|
+
{ id: 'b->c', source: 'b', target: 'c' },
|
|
13
|
+
]);
|
|
14
|
+
const positioned = layoutGraph(graph);
|
|
15
|
+
expect(positioned.nodes).toHaveLength(3);
|
|
16
|
+
expect(positioned.edges).toHaveLength(2);
|
|
17
|
+
for (const node of positioned.nodes) {
|
|
18
|
+
expect(Number.isFinite(node.x)).toBe(true);
|
|
19
|
+
expect(Number.isFinite(node.y)).toBe(true);
|
|
20
|
+
expect(node.width).toBeGreaterThan(0);
|
|
21
|
+
expect(node.height).toBeGreaterThan(0);
|
|
22
|
+
}
|
|
23
|
+
expect(positioned.width).toBeGreaterThan(0);
|
|
24
|
+
expect(positioned.height).toBeGreaterThan(0);
|
|
25
|
+
});
|
|
26
|
+
it('routes a top-to-bottom layout with later ranks below earlier ones', () => {
|
|
27
|
+
const graph = createGraph([
|
|
28
|
+
{ id: 'a', label: 'A' },
|
|
29
|
+
{ id: 'b', label: 'B' },
|
|
30
|
+
], [{ id: 'a->b', source: 'a', target: 'b' }]);
|
|
31
|
+
const positioned = layoutGraph(graph, { direction: 'TB' });
|
|
32
|
+
const a = positioned.nodes.find((n) => n.id === 'a');
|
|
33
|
+
const b = positioned.nodes.find((n) => n.id === 'b');
|
|
34
|
+
expect(b.y).toBeGreaterThan(a.y);
|
|
35
|
+
});
|
|
36
|
+
it('handles a graph with no edges', () => {
|
|
37
|
+
const graph = createGraph([{ id: 'solo', label: 'Solo' }]);
|
|
38
|
+
const positioned = layoutGraph(graph);
|
|
39
|
+
expect(positioned.nodes).toHaveLength(1);
|
|
40
|
+
expect(positioned.edges).toHaveLength(0);
|
|
41
|
+
});
|
|
42
|
+
it('grows node width to fit a long label beyond the default minimum', () => {
|
|
43
|
+
const graph = createGraph([
|
|
44
|
+
{ id: 'short', label: 'A' },
|
|
45
|
+
{ id: 'long', label: 'A Much Much Longer Node Label Than The Default Width' },
|
|
46
|
+
]);
|
|
47
|
+
const positioned = layoutGraph(graph);
|
|
48
|
+
const short = positioned.nodes.find((n) => n.id === 'short');
|
|
49
|
+
const long = positioned.nodes.find((n) => n.id === 'long');
|
|
50
|
+
expect(long.width).toBeGreaterThan(short.width);
|
|
51
|
+
});
|
|
52
|
+
it('clamps node width to nodeWidth in "fixed" sizing mode regardless of label length', () => {
|
|
53
|
+
const graph = createGraph([
|
|
54
|
+
{ id: 'long', label: 'A Much Much Longer Node Label Than The Default Width' },
|
|
55
|
+
]);
|
|
56
|
+
const positioned = layoutGraph(graph, { nodeSizing: 'fixed', nodeWidth: 160 });
|
|
57
|
+
expect(positioned.nodes[0].width).toBe(160);
|
|
58
|
+
});
|
|
59
|
+
it('supports multiple parallel edges between the same two nodes (multigraph)', () => {
|
|
60
|
+
const graph = createGraph([
|
|
61
|
+
{ id: 'a', label: 'A' },
|
|
62
|
+
{ id: 'b', label: 'B' },
|
|
63
|
+
], [
|
|
64
|
+
{ id: 'edge1', source: 'a', target: 'b' },
|
|
65
|
+
{ id: 'edge2', source: 'a', target: 'b' },
|
|
66
|
+
]);
|
|
67
|
+
expect(() => layoutGraph(graph)).not.toThrow();
|
|
68
|
+
const positioned = layoutGraph(graph);
|
|
69
|
+
expect(positioned.edges).toHaveLength(2);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=layout.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.test.js","sourceRoot":"","sources":["../src/layout.test.ts"],"names":[],"mappings":"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"}
|
package/dist/path.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface Point {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
}
|
|
5
|
+
/** Smooths a dagre bend-point list into a single SVG path via quadratic curves through segment midpoints. */
|
|
6
|
+
export declare function pointsToSvgPath(points: Point[]): string;
|
|
7
|
+
export interface BlockArrowOptions {
|
|
8
|
+
/** Half-width of the arrow's shaft. Default 10. */
|
|
9
|
+
shaftWidth?: number;
|
|
10
|
+
/** Half-width of the arrowhead's base. Default 20. */
|
|
11
|
+
headWidth?: number;
|
|
12
|
+
/** Length of the triangular head. Default 24. */
|
|
13
|
+
headLength?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Builds a filled block-arrow polygon (thick shaft + triangular head)
|
|
17
|
+
* between an edge's first and last routed point — the "chunky flow arrow"
|
|
18
|
+
* look of a process/pipeline diagram, as opposed to a thin stroked line
|
|
19
|
+
* with a marker. Ignores intermediate bend points; block arrows read as a
|
|
20
|
+
* straight directional beat between two steps, not a routed path.
|
|
21
|
+
*/
|
|
22
|
+
export declare function blockArrowPoints(points: Point[], options?: BlockArrowOptions): Point[];
|
|
23
|
+
/** Formats a point list as an SVG `points` attribute value, e.g. for `<polygon>`. */
|
|
24
|
+
export declare function pointsToPolygon(points: Point[]): string;
|
|
25
|
+
//# sourceMappingURL=path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,6GAA6G;AAC7G,wBAAgB,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAiBvD;AAED,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,GAAE,iBAAsB,GAAG,KAAK,EAAE,CA2B1F;AAED,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAEvD"}
|
package/dist/path.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** Smooths a dagre bend-point list into a single SVG path via quadratic curves through segment midpoints. */
|
|
2
|
+
export function pointsToSvgPath(points) {
|
|
3
|
+
if (points.length === 0)
|
|
4
|
+
return '';
|
|
5
|
+
if (points.length === 1)
|
|
6
|
+
return `M ${points[0].x} ${points[0].y}`;
|
|
7
|
+
let path = `M ${points[0].x} ${points[0].y}`;
|
|
8
|
+
for (let i = 1; i < points.length; i++) {
|
|
9
|
+
const point = points[i];
|
|
10
|
+
if (i === points.length - 1) {
|
|
11
|
+
path += ` L ${point.x} ${point.y}`;
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
const next = points[i + 1];
|
|
15
|
+
const midX = (point.x + next.x) / 2;
|
|
16
|
+
const midY = (point.y + next.y) / 2;
|
|
17
|
+
path += ` Q ${point.x} ${point.y}, ${midX} ${midY}`;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return path;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Builds a filled block-arrow polygon (thick shaft + triangular head)
|
|
24
|
+
* between an edge's first and last routed point — the "chunky flow arrow"
|
|
25
|
+
* look of a process/pipeline diagram, as opposed to a thin stroked line
|
|
26
|
+
* with a marker. Ignores intermediate bend points; block arrows read as a
|
|
27
|
+
* straight directional beat between two steps, not a routed path.
|
|
28
|
+
*/
|
|
29
|
+
export function blockArrowPoints(points, options = {}) {
|
|
30
|
+
const { shaftWidth = 10, headWidth = 20, headLength = 24 } = options;
|
|
31
|
+
if (points.length < 2)
|
|
32
|
+
return [];
|
|
33
|
+
const start = points[0];
|
|
34
|
+
const end = points[points.length - 1];
|
|
35
|
+
const dx = end.x - start.x;
|
|
36
|
+
const dy = end.y - start.y;
|
|
37
|
+
const len = Math.hypot(dx, dy);
|
|
38
|
+
if (len === 0)
|
|
39
|
+
return [];
|
|
40
|
+
const ux = dx / len;
|
|
41
|
+
const uy = dy / len;
|
|
42
|
+
const px = -uy;
|
|
43
|
+
const py = ux;
|
|
44
|
+
const effectiveHeadLength = Math.min(headLength, len);
|
|
45
|
+
const shaftEnd = { x: end.x - ux * effectiveHeadLength, y: end.y - uy * effectiveHeadLength };
|
|
46
|
+
return [
|
|
47
|
+
{ x: start.x + px * shaftWidth, y: start.y + py * shaftWidth },
|
|
48
|
+
{ x: shaftEnd.x + px * shaftWidth, y: shaftEnd.y + py * shaftWidth },
|
|
49
|
+
{ x: shaftEnd.x + px * headWidth, y: shaftEnd.y + py * headWidth },
|
|
50
|
+
end,
|
|
51
|
+
{ x: shaftEnd.x - px * headWidth, y: shaftEnd.y - py * headWidth },
|
|
52
|
+
{ x: shaftEnd.x - px * shaftWidth, y: shaftEnd.y - py * shaftWidth },
|
|
53
|
+
{ x: start.x - px * shaftWidth, y: start.y - py * shaftWidth },
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
/** Formats a point list as an SVG `points` attribute value, e.g. for `<polygon>`. */
|
|
57
|
+
export function pointsToPolygon(points) {
|
|
58
|
+
return points.map((p) => `${p.x},${p.y}`).join(' ');
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=path.js.map
|
package/dist/path.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DiagramTheme } from './theme.js';
|
|
2
|
+
export declare const themePresets: {
|
|
3
|
+
default: DiagramTheme;
|
|
4
|
+
slate: DiagramTheme;
|
|
5
|
+
rose: DiagramTheme;
|
|
6
|
+
violet: DiagramTheme;
|
|
7
|
+
dracula: DiagramTheme;
|
|
8
|
+
greyscale: DiagramTheme;
|
|
9
|
+
synthwave: DiagramTheme;
|
|
10
|
+
cyberpunk: DiagramTheme;
|
|
11
|
+
forest: DiagramTheme;
|
|
12
|
+
retro: DiagramTheme;
|
|
13
|
+
};
|
|
14
|
+
export type ThemePresetName = keyof typeof themePresets;
|
|
15
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AA0O9C,eAAO,MAAM,YAAY;;;;;;;;;;;CAWe,CAAA;AAExC,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,YAAY,CAAA"}
|
package/dist/presets.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { generateTheme } from './theme.js';
|
|
2
|
+
/**
|
|
3
|
+
* Named category -> color, for the category vocabulary diagram-kit's own
|
|
4
|
+
* adapters/examples use: "presentation/application/infrastructure/core/external"
|
|
5
|
+
* (typical layered architecture), "context" (fromArchitectureLandscape), and
|
|
6
|
+
* "directory/file" (fromDirectory). Any other category string still falls
|
|
7
|
+
* back to the generated palette via categoryColor()'s hashing — these are a
|
|
8
|
+
* curated top-up, not an exhaustive list.
|
|
9
|
+
*/
|
|
10
|
+
function withConventionalCategories(categoryColors, options) {
|
|
11
|
+
return generateTheme({ ...options, categoryColors });
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Real Tailwind CSS palette values (the same ones shadcn/ui themes are
|
|
15
|
+
* typically built on top of) as named category accents, over a tinted
|
|
16
|
+
* neutral scale generated to match.
|
|
17
|
+
*/
|
|
18
|
+
const slate = withConventionalCategories({
|
|
19
|
+
presentation: '#0ea5e9', // sky-500
|
|
20
|
+
application: '#8b5cf6', // violet-500
|
|
21
|
+
infrastructure: '#64748b', // slate-500
|
|
22
|
+
core: '#10b981', // emerald-500
|
|
23
|
+
external: '#f59e0b', // amber-500
|
|
24
|
+
context: '#8b5cf6',
|
|
25
|
+
directory: '#64748b',
|
|
26
|
+
file: '#94a3b8', // slate-400
|
|
27
|
+
}, { seedHue: 222, tintNeutrals: true });
|
|
28
|
+
const rose = withConventionalCategories({
|
|
29
|
+
presentation: '#f43f5e', // rose-500
|
|
30
|
+
application: '#fb7185', // rose-400
|
|
31
|
+
infrastructure: '#71717a', // zinc-500
|
|
32
|
+
core: '#e11d48', // rose-600
|
|
33
|
+
external: '#f59e0b', // amber-500
|
|
34
|
+
context: '#f43f5e',
|
|
35
|
+
directory: '#71717a',
|
|
36
|
+
file: '#a1a1aa', // zinc-400
|
|
37
|
+
}, { seedHue: 350, tintNeutrals: true });
|
|
38
|
+
const violet = withConventionalCategories({
|
|
39
|
+
presentation: '#8b5cf6', // violet-500
|
|
40
|
+
application: '#a78bfa', // violet-400
|
|
41
|
+
infrastructure: '#71717a', // zinc-500
|
|
42
|
+
core: '#7c3aed', // violet-600
|
|
43
|
+
external: '#14b8a6', // teal-500
|
|
44
|
+
context: '#8b5cf6',
|
|
45
|
+
directory: '#71717a',
|
|
46
|
+
file: '#a1a1aa',
|
|
47
|
+
}, { seedHue: 265, tintNeutrals: true });
|
|
48
|
+
/**
|
|
49
|
+
* The Dracula theme's actual published palette (draculatheme.com) —
|
|
50
|
+
* reproduced as-is rather than generated, since its specific hex values are
|
|
51
|
+
* the point.
|
|
52
|
+
*/
|
|
53
|
+
const dracula = {
|
|
54
|
+
dark: {
|
|
55
|
+
background: '#282a36',
|
|
56
|
+
surface: '#2b2d3a',
|
|
57
|
+
border: '#44475a',
|
|
58
|
+
text: '#f8f8f2',
|
|
59
|
+
textMuted: '#6272a4',
|
|
60
|
+
edge: '#6272a4',
|
|
61
|
+
edgeProjected: '#44475a',
|
|
62
|
+
categories: ['#8be9fd', '#50fa7b', '#ffb86c', '#ff79c6', '#bd93f9', '#ff5555', '#f1fa8c'],
|
|
63
|
+
categoryColors: {
|
|
64
|
+
presentation: '#ff79c6',
|
|
65
|
+
application: '#bd93f9',
|
|
66
|
+
infrastructure: '#6272a4',
|
|
67
|
+
core: '#50fa7b',
|
|
68
|
+
external: '#ffb86c',
|
|
69
|
+
context: '#bd93f9',
|
|
70
|
+
directory: '#6272a4',
|
|
71
|
+
file: '#8be9fd',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
light: {
|
|
75
|
+
background: '#f8f8f2',
|
|
76
|
+
surface: '#ffffff',
|
|
77
|
+
border: '#e2e2e9',
|
|
78
|
+
text: '#282a36',
|
|
79
|
+
textMuted: '#6272a4',
|
|
80
|
+
edge: '#9aa1ac',
|
|
81
|
+
edgeProjected: '#c7cbd3',
|
|
82
|
+
categories: ['#0891a3', '#1a9850', '#c2740a', '#c2277c', '#8250c4', '#d6273a', '#a68a00'],
|
|
83
|
+
categoryColors: {
|
|
84
|
+
presentation: '#c2277c',
|
|
85
|
+
application: '#8250c4',
|
|
86
|
+
infrastructure: '#6272a4',
|
|
87
|
+
core: '#1a9850',
|
|
88
|
+
external: '#c2740a',
|
|
89
|
+
context: '#8250c4',
|
|
90
|
+
directory: '#6272a4',
|
|
91
|
+
file: '#0891a3',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Pure grayscale (chroma 0) — hand-tuned rather than run through
|
|
97
|
+
* `generateTheme`'s hue-rotation generator, since hue is meaningless at
|
|
98
|
+
* zero chroma: every category would come out the same gray. Categories are
|
|
99
|
+
* differentiated by lightness step instead, each with a distinct light and
|
|
100
|
+
* dark counterpart so contrast against the background holds in both modes.
|
|
101
|
+
*/
|
|
102
|
+
const greyscale = {
|
|
103
|
+
light: {
|
|
104
|
+
background: '#FFFFFF',
|
|
105
|
+
surface: '#F5F5F5',
|
|
106
|
+
border: '#D4D4D4',
|
|
107
|
+
text: '#171717',
|
|
108
|
+
textMuted: '#737373',
|
|
109
|
+
edge: '#A3A3A3',
|
|
110
|
+
edgeProjected: '#D4D4D4',
|
|
111
|
+
categories: ['#171717', '#404040', '#525252', '#737373', '#8A8A8A', '#A3A3A3', '#BFBFBF'],
|
|
112
|
+
categoryColors: {
|
|
113
|
+
presentation: '#171717',
|
|
114
|
+
application: '#404040',
|
|
115
|
+
infrastructure: '#737373',
|
|
116
|
+
core: '#525252',
|
|
117
|
+
external: '#8A8A8A',
|
|
118
|
+
context: '#404040',
|
|
119
|
+
directory: '#737373',
|
|
120
|
+
file: '#A3A3A3',
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
dark: {
|
|
124
|
+
background: '#171717',
|
|
125
|
+
surface: '#212121',
|
|
126
|
+
border: '#3F3F3F',
|
|
127
|
+
text: '#F5F5F5',
|
|
128
|
+
textMuted: '#A3A3A3',
|
|
129
|
+
edge: '#5C5C5C',
|
|
130
|
+
edgeProjected: '#3F3F3F',
|
|
131
|
+
categories: ['#F5F5F5', '#D4D4D4', '#BFBFBF', '#A3A3A3', '#8A8A8A', '#737373', '#5C5C5C'],
|
|
132
|
+
categoryColors: {
|
|
133
|
+
presentation: '#F5F5F5',
|
|
134
|
+
application: '#D4D4D4',
|
|
135
|
+
infrastructure: '#8A8A8A',
|
|
136
|
+
core: '#BFBFBF',
|
|
137
|
+
external: '#737373',
|
|
138
|
+
context: '#D4D4D4',
|
|
139
|
+
directory: '#8A8A8A',
|
|
140
|
+
file: '#A3A3A3',
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Generated with parameters tuned to evoke the mood of the equivalent
|
|
146
|
+
* daisyUI theme name — not a reproduction of its literal (and, as of
|
|
147
|
+
* daisyUI 5, OKLCH-native) design tokens.
|
|
148
|
+
*/
|
|
149
|
+
const synthwave = withConventionalCategories({
|
|
150
|
+
presentation: '#ff5fd8',
|
|
151
|
+
application: '#a15fff',
|
|
152
|
+
infrastructure: '#5f8dff',
|
|
153
|
+
core: '#5fffe0',
|
|
154
|
+
external: '#ffd65f',
|
|
155
|
+
context: '#a15fff',
|
|
156
|
+
directory: '#5f8dff',
|
|
157
|
+
file: '#8888aa',
|
|
158
|
+
}, { seedHue: 300, chroma: 0.2, tintNeutrals: true });
|
|
159
|
+
const cyberpunk = withConventionalCategories({
|
|
160
|
+
presentation: '#ffe94f',
|
|
161
|
+
application: '#ff5fa2',
|
|
162
|
+
infrastructure: '#5fd0ff',
|
|
163
|
+
core: '#8bff5f',
|
|
164
|
+
external: '#ff8f5f',
|
|
165
|
+
context: '#ff5fa2',
|
|
166
|
+
directory: '#5fd0ff',
|
|
167
|
+
file: '#a8a8a8',
|
|
168
|
+
}, { seedHue: 55, chroma: 0.22, tintNeutrals: true });
|
|
169
|
+
const forest = withConventionalCategories({
|
|
170
|
+
presentation: '#4fae6a',
|
|
171
|
+
application: '#7cc98f',
|
|
172
|
+
infrastructure: '#6b8f78',
|
|
173
|
+
core: '#2f8f5a',
|
|
174
|
+
external: '#a3b869',
|
|
175
|
+
context: '#7cc98f',
|
|
176
|
+
directory: '#6b8f78',
|
|
177
|
+
file: '#8fa896',
|
|
178
|
+
}, { seedHue: 145, chroma: 0.13, tintNeutrals: true });
|
|
179
|
+
const retro = withConventionalCategories({
|
|
180
|
+
presentation: '#c2703c',
|
|
181
|
+
application: '#3c9a8f',
|
|
182
|
+
infrastructure: '#a89078',
|
|
183
|
+
core: '#c2903c',
|
|
184
|
+
external: '#8f6b3c',
|
|
185
|
+
context: '#3c9a8f',
|
|
186
|
+
directory: '#a89078',
|
|
187
|
+
file: '#bfae98',
|
|
188
|
+
}, { seedHue: 30, chroma: 0.1, tintNeutrals: true });
|
|
189
|
+
const defaultPreset = withConventionalCategories({
|
|
190
|
+
presentation: '#3B6EA5',
|
|
191
|
+
application: '#5F8D6B',
|
|
192
|
+
infrastructure: '#A5763B',
|
|
193
|
+
core: '#7A5FA5',
|
|
194
|
+
external: '#3F8A8C',
|
|
195
|
+
context: '#5F8D6B',
|
|
196
|
+
directory: '#A5763B',
|
|
197
|
+
file: '#8f97a3',
|
|
198
|
+
}, {});
|
|
199
|
+
export const themePresets = {
|
|
200
|
+
default: defaultPreset,
|
|
201
|
+
slate,
|
|
202
|
+
rose,
|
|
203
|
+
violet,
|
|
204
|
+
dracula,
|
|
205
|
+
greyscale,
|
|
206
|
+
synthwave,
|
|
207
|
+
cyberpunk,
|
|
208
|
+
forest,
|
|
209
|
+
retro,
|
|
210
|
+
};
|
|
211
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DiagramGraph } from './graph.js';
|
|
2
|
+
import type { PositionedGraph } from './layout.js';
|
|
3
|
+
export interface StackLayoutOptions {
|
|
4
|
+
showDetails?: boolean;
|
|
5
|
+
direction?: 'vertical' | 'horizontal';
|
|
6
|
+
gap?: number;
|
|
7
|
+
/** Minimum node width — nodes with longer labels grow wider to fit, up to `maxNodeWidth`, when `nodeSizing` is "responsive". Default 200. */
|
|
8
|
+
nodeWidth?: number;
|
|
9
|
+
/** Cap on how wide a single node can grow to fit its label. Default 420. */
|
|
10
|
+
maxNodeWidth?: number;
|
|
11
|
+
/** "responsive" (default): nodes grow to fit their label, up to `maxNodeWidth`. "fixed": every node is exactly `nodeWidth` wide, and a label too long to fit gets truncated with an ellipsis instead. */
|
|
12
|
+
nodeSizing?: 'responsive' | 'fixed';
|
|
13
|
+
nodeHeight?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Flat sequential list — every node in graph order, evenly spaced, no
|
|
17
|
+
* hierarchy and no connectors. For data with no real structure to show
|
|
18
|
+
* (or where showing it would be noise), like a single context's internal
|
|
19
|
+
* layers listed one after another.
|
|
20
|
+
*/
|
|
21
|
+
export declare function layoutStack(graph: DiagramGraph, options?: StackLayoutOptions): PositionedGraph;
|
|
22
|
+
//# sourceMappingURL=stackLayout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stackLayout.d.ts","sourceRoot":"","sources":["../src/stackLayout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,aAAa,CAAA;AAIlE,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,SAAS,CAAC,EAAE,UAAU,GAAG,YAAY,CAAA;IACrC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,6IAA6I;IAC7I,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,yMAAyM;IACzM,UAAU,CAAC,EAAE,YAAY,GAAG,OAAO,CAAA;IACnC,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAYD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,GAAE,kBAAuB,GAAG,eAAe,CAkClG"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { estimateNodeWidth } from './textWidth.js';
|
|
2
|
+
import { detailHeight } from './detailText.js';
|
|
3
|
+
const DEFAULTS = {
|
|
4
|
+
showDetails: false,
|
|
5
|
+
direction: 'vertical',
|
|
6
|
+
gap: 10,
|
|
7
|
+
nodeWidth: 200,
|
|
8
|
+
maxNodeWidth: 420,
|
|
9
|
+
nodeSizing: 'responsive',
|
|
10
|
+
nodeHeight: 44,
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Flat sequential list — every node in graph order, evenly spaced, no
|
|
14
|
+
* hierarchy and no connectors. For data with no real structure to show
|
|
15
|
+
* (or where showing it would be noise), like a single context's internal
|
|
16
|
+
* layers listed one after another.
|
|
17
|
+
*/
|
|
18
|
+
export function layoutStack(graph, options = {}) {
|
|
19
|
+
const opts = { ...DEFAULTS, ...options };
|
|
20
|
+
const widths = graph.nodes.map((node) => estimateNodeWidth(node.label, node.badge, {
|
|
21
|
+
minWidth: opts.nodeWidth,
|
|
22
|
+
maxWidth: opts.nodeSizing === 'fixed' ? opts.nodeWidth : opts.maxNodeWidth,
|
|
23
|
+
}));
|
|
24
|
+
const nodes = [];
|
|
25
|
+
let cursor = 0;
|
|
26
|
+
if (opts.direction === 'vertical') {
|
|
27
|
+
const overallWidth = Math.max(0, ...widths);
|
|
28
|
+
graph.nodes.forEach((node, i) => {
|
|
29
|
+
const width = widths[i];
|
|
30
|
+
const height = opts.nodeHeight + detailHeight(node, width, opts.showDetails);
|
|
31
|
+
nodes.push({ id: node.id, x: overallWidth / 2, y: cursor + height / 2, width, height });
|
|
32
|
+
cursor += height + opts.gap;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
graph.nodes.forEach((node, i) => {
|
|
37
|
+
const width = widths[i];
|
|
38
|
+
const height = opts.nodeHeight + detailHeight(node, width, opts.showDetails);
|
|
39
|
+
nodes.push({ id: node.id, x: cursor + width / 2, y: height / 2, width, height });
|
|
40
|
+
cursor += width + opts.gap;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const width = opts.direction === 'vertical' ? Math.max(0, ...widths) : Math.max(0, cursor - opts.gap);
|
|
44
|
+
const height = opts.direction === 'vertical' ? Math.max(0, cursor - opts.gap) : Math.max(0, ...nodes.map((node) => node.height));
|
|
45
|
+
return { nodes, edges: [], width, height };
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=stackLayout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stackLayout.js","sourceRoot":"","sources":["../src/stackLayout.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAe9C,MAAM,QAAQ,GAAiC;IAC7C,WAAW,EAAE,KAAK;IAClB,SAAS,EAAE,UAAU;IACrB,GAAG,EAAE,EAAE;IACP,SAAS,EAAE,GAAG;IACd,YAAY,EAAE,GAAG;IACjB,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,EAAE;CACf,CAAA;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,KAAmB,EAAE,UAA8B,EAAE;IAC/E,MAAM,IAAI,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,EAAE,CAAA;IAExC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACtC,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;QACxC,QAAQ,EAAE,IAAI,CAAC,SAAS;QACxB,QAAQ,EAAE,IAAI,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY;KAC3E,CAAC,CACH,CAAA;IAED,MAAM,KAAK,GAAqB,EAAE,CAAA;IAClC,IAAI,MAAM,GAAG,CAAC,CAAA;IAEd,IAAI,IAAI,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;QAClC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,CAAA;QAC3C,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;YAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAE,CAAA;YACxB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;YAC5E,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,YAAY,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;YACvF,MAAM,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAA;QAC7B,CAAC,CAAC,CAAA;IACJ,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;YAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAE,CAAA;YACxB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;YAC5E,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;YAChF,MAAM,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,CAAA;QAC5B,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;IACrG,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;IAEhI,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;AAC5C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stackLayout.test.d.ts","sourceRoot":"","sources":["../src/stackLayout.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { createGraph } from './graph.js';
|
|
3
|
+
import { layoutStack } from './stackLayout.js';
|
|
4
|
+
describe('layoutStack', () => {
|
|
5
|
+
it('produces no edges', () => {
|
|
6
|
+
const graph = createGraph([
|
|
7
|
+
{ id: 'a', label: 'A' },
|
|
8
|
+
{ id: 'b', label: 'B' },
|
|
9
|
+
], [{ id: 'x', source: 'a', target: 'b' }]);
|
|
10
|
+
expect(layoutStack(graph).edges).toEqual([]);
|
|
11
|
+
});
|
|
12
|
+
it('stacks nodes vertically in graph order with increasing y', () => {
|
|
13
|
+
const graph = createGraph([
|
|
14
|
+
{ id: 'a', label: 'A' },
|
|
15
|
+
{ id: 'b', label: 'B' },
|
|
16
|
+
{ id: 'c', label: 'C' },
|
|
17
|
+
]);
|
|
18
|
+
const positioned = layoutStack(graph, { direction: 'vertical' });
|
|
19
|
+
const [a, b, c] = graph.nodes.map((n) => positioned.nodes.find((p) => p.id === n.id));
|
|
20
|
+
expect(b.y).toBeGreaterThan(a.y);
|
|
21
|
+
expect(c.y).toBeGreaterThan(b.y);
|
|
22
|
+
});
|
|
23
|
+
it('lays out nodes horizontally with increasing x in horizontal direction', () => {
|
|
24
|
+
const graph = createGraph([
|
|
25
|
+
{ id: 'a', label: 'A' },
|
|
26
|
+
{ id: 'b', label: 'B' },
|
|
27
|
+
]);
|
|
28
|
+
const positioned = layoutStack(graph, { direction: 'horizontal' });
|
|
29
|
+
const a = positioned.nodes.find((n) => n.id === 'a');
|
|
30
|
+
const b = positioned.nodes.find((n) => n.id === 'b');
|
|
31
|
+
expect(b.x).toBeGreaterThan(a.x);
|
|
32
|
+
});
|
|
33
|
+
it('grows node width to fit a long label in responsive mode', () => {
|
|
34
|
+
const graph = createGraph([{ id: 'long', label: 'A Much Much Longer Node Label Than Default' }]);
|
|
35
|
+
const positioned = layoutStack(graph);
|
|
36
|
+
expect(positioned.nodes[0].width).toBeGreaterThan(200);
|
|
37
|
+
});
|
|
38
|
+
it('clamps node width in fixed sizing mode', () => {
|
|
39
|
+
const graph = createGraph([{ id: 'long', label: 'A Much Much Longer Node Label Than Default' }]);
|
|
40
|
+
const positioned = layoutStack(graph, { nodeSizing: 'fixed', nodeWidth: 200 });
|
|
41
|
+
expect(positioned.nodes[0].width).toBe(200);
|
|
42
|
+
});
|
|
43
|
+
it('handles an empty graph without throwing', () => {
|
|
44
|
+
const graph = createGraph([]);
|
|
45
|
+
expect(() => layoutStack(graph)).not.toThrow();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=stackLayout.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stackLayout.test.js","sourceRoot":"","sources":["../src/stackLayout.test.ts"],"names":[],"mappings":"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"}
|