@nodius/layouting 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +280 -126
  3. package/dist/algorithms/component-packing.d.ts +9 -0
  4. package/dist/algorithms/component-packing.d.ts.map +1 -0
  5. package/dist/algorithms/coordinate-assignment.d.ts +7 -0
  6. package/dist/algorithms/coordinate-assignment.d.ts.map +1 -0
  7. package/dist/algorithms/crossing-minimization.d.ts +7 -0
  8. package/dist/algorithms/crossing-minimization.d.ts.map +1 -0
  9. package/dist/algorithms/cycle-breaking.d.ts +8 -0
  10. package/dist/algorithms/cycle-breaking.d.ts.map +1 -0
  11. package/dist/algorithms/edge-routing.d.ts +17 -0
  12. package/dist/algorithms/edge-routing.d.ts.map +1 -0
  13. package/dist/algorithms/layer-assignment.d.ts +20 -0
  14. package/dist/algorithms/layer-assignment.d.ts.map +1 -0
  15. package/dist/algorithms/value-cluster.d.ts +15 -0
  16. package/dist/algorithms/value-cluster.d.ts.map +1 -0
  17. package/dist/algorithms/value-placement.d.ts +25 -0
  18. package/dist/algorithms/value-placement.d.ts.map +1 -0
  19. package/dist/debug.d.ts +20 -0
  20. package/dist/debug.d.ts.map +1 -0
  21. package/dist/graph.d.ts +50 -0
  22. package/dist/graph.d.ts.map +1 -0
  23. package/dist/incremental.d.ts +33 -0
  24. package/dist/incremental.d.ts.map +1 -0
  25. package/dist/index.d.ts +7 -176
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +904 -149
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +901 -148
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/layout.d.ts +10 -0
  32. package/dist/layout.d.ts.map +1 -0
  33. package/dist/proposals.d.ts +31 -0
  34. package/dist/proposals.d.ts.map +1 -0
  35. package/dist/types.d.ts +155 -0
  36. package/dist/types.d.ts.map +1 -0
  37. package/package.json +5 -4
  38. package/dist/index.d.mts +0 -176
@@ -0,0 +1,155 @@
1
+ /** Position on a node where a handle can be placed */
2
+ export type HandleSide = 'top' | 'right' | 'bottom' | 'left';
3
+ /** Handle type - input receives connections, output sends connections */
4
+ export type HandleType = 'input' | 'output';
5
+ /** Layout direction. 'TB' or 'LR' are the supported strict reading axes. */
6
+ export type LayoutDirection = 'TB' | 'LR' | 'BT' | 'RL';
7
+ /**
8
+ * Edge kind drives the layout weight:
9
+ * - `control`: full strength; defines the execution rail (layer count).
10
+ * - `data`: light weight; values are pulled onto the same layer as their consumer
11
+ * instead of extending the rail.
12
+ */
13
+ export type EdgeKind = 'control' | 'data';
14
+ /** A 2D point */
15
+ export interface Point {
16
+ x: number;
17
+ y: number;
18
+ }
19
+ /** Handle definition on a node */
20
+ export interface HandleInput {
21
+ id: string;
22
+ type: HandleType;
23
+ position: HandleSide;
24
+ /** Position along the side (0 = start, 1 = end). Default: 0.5 */
25
+ offset?: number;
26
+ }
27
+ /** Node input definition */
28
+ export interface NodeInput {
29
+ id: string;
30
+ width: number;
31
+ height: number;
32
+ handles: HandleInput[];
33
+ /** Parent node id for compound (nested) layouts. */
34
+ parentId?: string;
35
+ }
36
+ /** Edge input definition */
37
+ export interface EdgeInput {
38
+ id: string;
39
+ from: string;
40
+ to: string;
41
+ fromHandle: string;
42
+ toHandle: string;
43
+ /** Default: 'control' */
44
+ kind?: EdgeKind;
45
+ /** Explicit weight override. Defaults: 1 (control), 0.25 (data). */
46
+ weight?: number;
47
+ }
48
+ /** Complete layout input */
49
+ export interface LayoutInput {
50
+ nodes: NodeInput[];
51
+ edges: EdgeInput[];
52
+ }
53
+ /** Per-kind default weight overrides. */
54
+ export interface EdgeWeights {
55
+ control?: number;
56
+ data?: number;
57
+ }
58
+ /**
59
+ * A proposal the layout engine emits to the calling application during a pass.
60
+ * The app inspects it and decides whether to accept it, modify it, or reject it
61
+ * by returning either the (possibly tweaked) proposed node or `null`/`undefined`
62
+ * to keep the original.
63
+ */
64
+ export interface RotateProposal {
65
+ type: 'rotate';
66
+ /** The node being analyzed. */
67
+ nodeId: string;
68
+ /** Same node as provided in the input. */
69
+ current: NodeInput;
70
+ /** The engine's proposed version after rotating handles. */
71
+ proposed: NodeInput;
72
+ /** Rotation in degrees (CW = positive). */
73
+ rotation: 90 | -90 | 180;
74
+ /** Reason this proposal was emitted (handle layout mismatches direction, etc.). */
75
+ reason: string;
76
+ }
77
+ export type LayoutProposal = RotateProposal;
78
+ export type ProposalCallback = (proposal: LayoutProposal) => NodeInput | null | undefined | void;
79
+ /** Layout configuration options */
80
+ export interface LayoutOptions {
81
+ /** Layout direction. Default: 'TB' */
82
+ direction?: LayoutDirection;
83
+ /** Minimum spacing between nodes in the same layer. Default: 40 */
84
+ nodeSpacing?: number;
85
+ /** Minimum spacing between layers. Default: 60 */
86
+ layerSpacing?: number;
87
+ /** Number of iterations for crossing minimization. Default: 24 */
88
+ crossingMinimizationIterations?: number;
89
+ /** Number of iterations for coordinate optimization. Default: 8 */
90
+ coordinateOptimizationIterations?: number;
91
+ /** Margin for edge routing (distance from node before turning). Default: 20 */
92
+ edgeMargin?: number;
93
+ /** Override default per-kind weights. */
94
+ edgeWeights?: EdgeWeights;
95
+ /** When true, disjoint components are packed side-by-side. Default: true */
96
+ packComponents?: boolean;
97
+ /** Padding around compound (parent) bounding boxes. Default: 24 */
98
+ compoundPadding?: number;
99
+ /**
100
+ * Called once per node when the engine thinks a rotation of the node's
101
+ * handles would suit the chosen direction better. Return the (possibly
102
+ * tweaked) proposed node to accept, or `null`/nothing to keep the original.
103
+ */
104
+ onProposal?: ProposalCallback;
105
+ }
106
+ /** Resolved options with all defaults applied */
107
+ export interface ResolvedOptions {
108
+ direction: LayoutDirection;
109
+ nodeSpacing: number;
110
+ layerSpacing: number;
111
+ crossingMinimizationIterations: number;
112
+ coordinateOptimizationIterations: number;
113
+ edgeMargin: number;
114
+ controlWeight: number;
115
+ dataWeight: number;
116
+ packComponents: boolean;
117
+ compoundPadding: number;
118
+ onProposal?: ProposalCallback;
119
+ }
120
+ export declare function resolveOptions(options?: LayoutOptions): ResolvedOptions;
121
+ /** Positioned handle in the output */
122
+ export interface HandleOutput {
123
+ id: string;
124
+ type: HandleType;
125
+ position: HandleSide;
126
+ x: number;
127
+ y: number;
128
+ }
129
+ /** Positioned node in the output */
130
+ export interface NodeOutput {
131
+ id: string;
132
+ x: number;
133
+ y: number;
134
+ width: number;
135
+ height: number;
136
+ handles: HandleOutput[];
137
+ /** Echoed back so consumers can reconstruct the hierarchy. */
138
+ parentId?: string;
139
+ }
140
+ /** Routed edge in the output */
141
+ export interface EdgeOutput {
142
+ id: string;
143
+ from: string;
144
+ to: string;
145
+ fromHandle: string;
146
+ toHandle: string;
147
+ points: Point[];
148
+ kind: EdgeKind;
149
+ }
150
+ /** Complete layout result */
151
+ export interface LayoutResult {
152
+ nodes: NodeOutput[];
153
+ edges: EdgeOutput[];
154
+ }
155
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE7D,yEAAyE;AACzE,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5C,4EAA4E;AAC5E,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAExD;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAE1C,iBAAiB;AACjB,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,kCAAkC;AAClC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,UAAU,CAAC;IACrB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,4BAA4B;AAC5B,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,4BAA4B;AAC5B,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,4BAA4B;AAC5B,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,yCAAyC;AACzC,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,OAAO,EAAE,SAAS,CAAC;IACnB,4DAA4D;IAC5D,QAAQ,EAAE,SAAS,CAAC;IACpB,2CAA2C;IAC3C,QAAQ,EAAE,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC;IACzB,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,cAAc,GAAG,cAAc,CAAC;AAE5C,MAAM,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,cAAc,KAAK,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;AAEjG,mCAAmC;AACnC,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mEAAmE;IACnE,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,4EAA4E;IAC5E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAED,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,eAAe,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,8BAA8B,EAAE,MAAM,CAAC;IACvC,gCAAgC,EAAE,MAAM,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAED,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,eAAe,CAcvE;AAED,sCAAsC;AACtC,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,UAAU,CAAC;IACrB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,oCAAoC;AACpC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,gCAAgC;AAChC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,6BAA6B;AAC7B,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodius/layouting",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Zero-dependency, optimized graph layouting algorithm for node-based technical diagrams with incremental layout support",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -19,8 +19,9 @@
19
19
  "dist"
20
20
  ],
21
21
  "scripts": {
22
- "build": "tsup",
22
+ "build": "tsup && tsc --emitDeclarationOnly",
23
23
  "dev": "tsup --watch",
24
+ "dev:types": "tsc --emitDeclarationOnly --watch",
24
25
  "test": "vitest run",
25
26
  "test:watch": "vitest",
26
27
  "test:coverage": "vitest run --coverage",
@@ -42,7 +43,7 @@
42
43
  "license": "ISC",
43
44
  "devDependencies": {
44
45
  "tsup": "^8.5.1",
45
- "typescript": "^5.9.3",
46
- "vitest": "^4.0.18"
46
+ "typescript": "^6.0.3",
47
+ "vitest": "^4.1.6"
47
48
  }
48
49
  }
package/dist/index.d.mts DELETED
@@ -1,176 +0,0 @@
1
- /** Position on a node where a handle can be placed */
2
- type HandleSide = 'top' | 'right' | 'bottom' | 'left';
3
- /** Handle type - input receives connections, output sends connections */
4
- type HandleType = 'input' | 'output';
5
- /** Layout direction */
6
- type LayoutDirection = 'TB' | 'LR' | 'BT' | 'RL';
7
- /** A 2D point */
8
- interface Point {
9
- x: number;
10
- y: number;
11
- }
12
- /** Handle definition on a node */
13
- interface HandleInput {
14
- id: string;
15
- type: HandleType;
16
- position: HandleSide;
17
- /** Position along the side (0 = start, 1 = end). Default: 0.5 */
18
- offset?: number;
19
- }
20
- /** Node input definition */
21
- interface NodeInput {
22
- id: string;
23
- width: number;
24
- height: number;
25
- handles: HandleInput[];
26
- }
27
- /** Edge input definition */
28
- interface EdgeInput {
29
- id: string;
30
- from: string;
31
- to: string;
32
- fromHandle: string;
33
- toHandle: string;
34
- }
35
- /** Complete layout input */
36
- interface LayoutInput {
37
- nodes: NodeInput[];
38
- edges: EdgeInput[];
39
- }
40
- /** Layout configuration options */
41
- interface LayoutOptions {
42
- /** Layout direction. Default: 'TB' */
43
- direction?: LayoutDirection;
44
- /** Minimum spacing between nodes in the same layer. Default: 40 */
45
- nodeSpacing?: number;
46
- /** Minimum spacing between layers. Default: 60 */
47
- layerSpacing?: number;
48
- /** Number of iterations for crossing minimization. Default: 24 */
49
- crossingMinimizationIterations?: number;
50
- /** Number of iterations for coordinate optimization. Default: 8 */
51
- coordinateOptimizationIterations?: number;
52
- /** Margin for edge routing (distance from node before turning). Default: 20 */
53
- edgeMargin?: number;
54
- }
55
- /** Positioned handle in the output */
56
- interface HandleOutput {
57
- id: string;
58
- type: HandleType;
59
- position: HandleSide;
60
- x: number;
61
- y: number;
62
- }
63
- /** Positioned node in the output */
64
- interface NodeOutput {
65
- id: string;
66
- x: number;
67
- y: number;
68
- width: number;
69
- height: number;
70
- handles: HandleOutput[];
71
- }
72
- /** Routed edge in the output */
73
- interface EdgeOutput {
74
- id: string;
75
- from: string;
76
- to: string;
77
- fromHandle: string;
78
- toHandle: string;
79
- points: Point[];
80
- }
81
- /** Complete layout result */
82
- interface LayoutResult {
83
- nodes: NodeOutput[];
84
- edges: EdgeOutput[];
85
- }
86
-
87
- interface InternalNode {
88
- id: string;
89
- width: number;
90
- height: number;
91
- handles: HandleInput[];
92
- isDummy: boolean;
93
- layer: number;
94
- order: number;
95
- x: number;
96
- y: number;
97
- }
98
- interface InternalEdge {
99
- id: string;
100
- from: string;
101
- to: string;
102
- fromHandle: string;
103
- toHandle: string;
104
- reversed: boolean;
105
- originalId: string;
106
- }
107
- declare class Graph {
108
- nodes: Map<string, InternalNode>;
109
- edges: Map<string, InternalEdge>;
110
- outEdges: Map<string, Set<string>>;
111
- inEdges: Map<string, Set<string>>;
112
- addNode(node: InternalNode): void;
113
- addEdge(edge: InternalEdge): void;
114
- removeEdge(edgeId: string): void;
115
- removeNode(nodeId: string): void;
116
- predecessors(nodeId: string): string[];
117
- successors(nodeId: string): string[];
118
- }
119
-
120
- /**
121
- * Compute a complete layout for the given graph.
122
- * This is the main entry point for one-shot layout computation.
123
- */
124
- declare function layout(input: LayoutInput, options?: LayoutOptions): LayoutResult;
125
-
126
- /**
127
- * Incremental layout engine.
128
- * Maintains layout state and supports adding/removing nodes
129
- * without full recomputation.
130
- */
131
- declare class IncrementalLayout {
132
- private options;
133
- private inputNodes;
134
- private inputEdges;
135
- private lastResult;
136
- private nodePositions;
137
- constructor(options?: LayoutOptions);
138
- /**
139
- * Set the full graph and compute a complete layout.
140
- */
141
- setGraph(input: LayoutInput): LayoutResult;
142
- /**
143
- * Add nodes and edges incrementally.
144
- * Attempts to minimize layout changes for existing nodes.
145
- */
146
- addNodes(nodes: NodeInput[], edges?: EdgeInput[]): LayoutResult;
147
- /**
148
- * Remove nodes (and their connected edges) from the layout.
149
- */
150
- removeNodes(nodeIds: string[]): LayoutResult;
151
- /**
152
- * Add edges between existing nodes.
153
- */
154
- addEdges(edges: EdgeInput[]): LayoutResult;
155
- /**
156
- * Remove edges from the layout.
157
- */
158
- removeEdges(edgeIds: string[]): LayoutResult;
159
- /**
160
- * Get the current layout result.
161
- */
162
- getResult(): LayoutResult | null;
163
- private recompute;
164
- private recomputeIncremental;
165
- /**
166
- * Apply stability: blend new positions with old positions for existing nodes.
167
- * This reduces visual disruption when adding new nodes.
168
- */
169
- private applyStability;
170
- private cachePositions;
171
- private buildResult;
172
- }
173
-
174
- declare function countAllCrossings(graph: Graph, layers: string[][]): number;
175
-
176
- export { type EdgeInput, type EdgeOutput, type HandleInput, type HandleOutput, type HandleSide, type HandleType, IncrementalLayout, type LayoutDirection, type LayoutInput, type LayoutOptions, type LayoutResult, type NodeInput, type NodeOutput, type Point, countAllCrossings, layout };