@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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +22 -0
  3. package/dist/cssPalette.d.ts +15 -0
  4. package/dist/cssPalette.d.ts.map +1 -0
  5. package/dist/cssPalette.js +37 -0
  6. package/dist/cssPalette.js.map +1 -0
  7. package/dist/cycleLayout.d.ts +13 -0
  8. package/dist/cycleLayout.d.ts.map +1 -0
  9. package/dist/cycleLayout.js +174 -0
  10. package/dist/cycleLayout.js.map +1 -0
  11. package/dist/detailText.d.ts +5 -0
  12. package/dist/detailText.d.ts.map +1 -0
  13. package/dist/detailText.js +34 -0
  14. package/dist/detailText.js.map +1 -0
  15. package/dist/graph.d.ts +52 -0
  16. package/dist/graph.d.ts.map +1 -0
  17. package/dist/graph.js +30 -0
  18. package/dist/graph.js.map +1 -0
  19. package/dist/graph.test.d.ts +2 -0
  20. package/dist/graph.test.d.ts.map +1 -0
  21. package/dist/graph.test.js +33 -0
  22. package/dist/graph.test.js.map +1 -0
  23. package/dist/index.d.ts +21 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +12 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/layout.d.ts +46 -0
  28. package/dist/layout.d.ts.map +1 -0
  29. package/dist/layout.js +57 -0
  30. package/dist/layout.js.map +1 -0
  31. package/dist/layout.test.d.ts +2 -0
  32. package/dist/layout.test.d.ts.map +1 -0
  33. package/dist/layout.test.js +72 -0
  34. package/dist/layout.test.js.map +1 -0
  35. package/dist/path.d.ts +25 -0
  36. package/dist/path.d.ts.map +1 -0
  37. package/dist/path.js +60 -0
  38. package/dist/path.js.map +1 -0
  39. package/dist/presets.d.ts +15 -0
  40. package/dist/presets.d.ts.map +1 -0
  41. package/dist/presets.js +211 -0
  42. package/dist/presets.js.map +1 -0
  43. package/dist/stackLayout.d.ts +22 -0
  44. package/dist/stackLayout.d.ts.map +1 -0
  45. package/dist/stackLayout.js +47 -0
  46. package/dist/stackLayout.js.map +1 -0
  47. package/dist/stackLayout.test.d.ts +2 -0
  48. package/dist/stackLayout.test.d.ts.map +1 -0
  49. package/dist/stackLayout.test.js +48 -0
  50. package/dist/stackLayout.test.js.map +1 -0
  51. package/dist/structuralLayout.d.ts +30 -0
  52. package/dist/structuralLayout.d.ts.map +1 -0
  53. package/dist/structuralLayout.js +117 -0
  54. package/dist/structuralLayout.js.map +1 -0
  55. package/dist/structuralLayout.test.d.ts +2 -0
  56. package/dist/structuralLayout.test.d.ts.map +1 -0
  57. package/dist/structuralLayout.test.js +74 -0
  58. package/dist/structuralLayout.test.js.map +1 -0
  59. package/dist/textWidth.d.ts +18 -0
  60. package/dist/textWidth.d.ts.map +1 -0
  61. package/dist/textWidth.js +50 -0
  62. package/dist/textWidth.js.map +1 -0
  63. package/dist/theme.d.ts +68 -0
  64. package/dist/theme.d.ts.map +1 -0
  65. package/dist/theme.js +94 -0
  66. package/dist/theme.js.map +1 -0
  67. 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":"AAAA,OAAO,KAAK,MAAM,gBAAgB,CAAA;AAElC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AA0C9C,MAAM,QAAQ,GAA4B;IACxC,WAAW,EAAE,KAAK;IAClB,SAAS,EAAE,IAAI;IACf,SAAS,EAAE,GAAG;IACd,YAAY,EAAE,GAAG;IACjB,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,EAAE;IACd,WAAW,EAAE,EAAE;IACf,WAAW,EAAE,EAAE;CAChB,CAAA;AAED,oGAAoG;AACpG,MAAM,UAAU,WAAW,CAAC,KAAmB,EAAE,UAAyB,EAAE;IAC1E,MAAM,IAAI,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,EAAE,CAAA;IAExC,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAA;IACxD,CAAC,CAAC,QAAQ,CAAC;QACT,OAAO,EAAE,IAAI,CAAC,SAAS;QACvB,OAAO,EAAE,IAAI,CAAC,WAAW;QACzB,OAAO,EAAE,IAAI,CAAC,WAAW;KAC1B,CAAC,CAAA;IACF,CAAC,CAAC,mBAAmB,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAEjC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;YACtD,QAAQ,EAAE,IAAI,CAAC,SAAS;YACxB,QAAQ,EAAE,IAAI,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY;SAC3E,CAAC,CAAA;QACF,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;IACtG,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAA;IAClD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAEf,MAAM,KAAK,GAAqB,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACvD,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAA4D,CAAA;QAC7F,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,CAAC,EAAE,UAAU,CAAC,CAAC;YACf,CAAC,EAAE,UAAU,CAAC,CAAC;YACf,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,MAAM,KAAK,GAAqB,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACvD,MAAM,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAExE,CAAA;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAA;IACjD,CAAC,CAAC,CAAA;IAEF,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,EAAE,CAAA;IAC5B,OAAO;QACL,KAAK;QACL,KAAK;QACL,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI,CAAC;QAC5B,MAAM,EAAE,UAAU,CAAC,MAAM,IAAI,CAAC;KAC/B,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=layout.test.d.ts.map
@@ -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
@@ -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"}
@@ -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":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stackLayout.test.d.ts.map
@@ -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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"}