@rokkit/graph 1.6.0 → 1.7.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 (77) hide show
  1. package/README.md +59 -2
  2. package/dist/Graph.svelte +121 -72
  3. package/dist/GraphLegend.svelte +112 -0
  4. package/dist/GraphLegend.svelte.d.ts +33 -0
  5. package/dist/GraphState.svelte.d.ts +107 -15
  6. package/dist/GraphState.svelte.js +186 -3
  7. package/dist/controls/BundleControl.svelte +30 -0
  8. package/dist/controls/BundleControl.svelte.d.ts +16 -0
  9. package/dist/controls/DensityControl.svelte +39 -0
  10. package/dist/controls/DensityControl.svelte.d.ts +16 -0
  11. package/dist/controls/DepthControl.svelte +34 -0
  12. package/dist/controls/DepthControl.svelte.d.ts +17 -0
  13. package/dist/controls/EdgeStyleControl.svelte +31 -0
  14. package/dist/controls/EdgeStyleControl.svelte.d.ts +14 -0
  15. package/dist/controls/ZoomControl.svelte +47 -0
  16. package/dist/controls/ZoomControl.svelte.d.ts +7 -0
  17. package/dist/controls/zoom.d.ts +6 -0
  18. package/dist/controls/zoom.js +12 -0
  19. package/dist/diagrams/CallTree.svelte +135 -0
  20. package/dist/diagrams/CallTree.svelte.d.ts +37 -0
  21. package/dist/diagrams/DependencyDiagram.svelte +124 -0
  22. package/dist/diagrams/DependencyDiagram.svelte.d.ts +30 -0
  23. package/dist/diagrams/DiagramFrame.svelte +36 -0
  24. package/dist/diagrams/DiagramFrame.svelte.d.ts +20 -0
  25. package/dist/diagrams/ErDiagram.svelte +128 -0
  26. package/dist/diagrams/ErDiagram.svelte.d.ts +33 -0
  27. package/dist/diagrams/Neighborhood.svelte +127 -0
  28. package/dist/diagrams/Neighborhood.svelte.d.ts +33 -0
  29. package/dist/diagrams/StructureDiagram.svelte +131 -0
  30. package/dist/diagrams/StructureDiagram.svelte.d.ts +31 -0
  31. package/dist/diagrams/Sunburst.svelte +124 -0
  32. package/dist/diagrams/Sunburst.svelte.d.ts +32 -0
  33. package/dist/diagrams/Treemap.svelte +124 -0
  34. package/dist/diagrams/Treemap.svelte.d.ts +32 -0
  35. package/dist/icons.d.ts +5 -0
  36. package/dist/icons.js +5 -0
  37. package/dist/index.d.ts +18 -1
  38. package/dist/index.js +23 -1
  39. package/dist/layout/arc.d.ts +13 -0
  40. package/dist/layout/arc.js +58 -0
  41. package/dist/layout/bundle.d.ts +30 -0
  42. package/dist/layout/bundle.js +80 -0
  43. package/dist/layout/cluster.js +2 -0
  44. package/dist/layout/flow.d.ts +8 -0
  45. package/dist/layout/flow.js +141 -0
  46. package/dist/layout/hierarchy.d.ts +42 -0
  47. package/dist/layout/hierarchy.js +175 -0
  48. package/dist/layout/index.d.ts +7 -1
  49. package/dist/layout/index.js +8 -2
  50. package/dist/layout/neighborhood.js +164 -28
  51. package/dist/layout/options.d.ts +44 -0
  52. package/dist/layout/options.js +106 -0
  53. package/dist/layout/order.d.ts +11 -0
  54. package/dist/layout/order.js +153 -0
  55. package/dist/layout/points.js +27 -35
  56. package/dist/layout/radial.d.ts +16 -0
  57. package/dist/layout/radial.js +214 -0
  58. package/dist/layout/rank.d.ts +15 -0
  59. package/dist/layout/rank.js +105 -0
  60. package/dist/layout/rings.d.ts +20 -0
  61. package/dist/layout/rings.js +92 -0
  62. package/dist/layout/sizing.d.ts +37 -0
  63. package/dist/layout/sizing.js +79 -0
  64. package/dist/layout/squarify.d.ts +14 -0
  65. package/dist/layout/squarify.js +114 -0
  66. package/dist/layout/structure.d.ts +9 -0
  67. package/dist/layout/structure.js +367 -0
  68. package/dist/layout/sunburst.d.ts +8 -0
  69. package/dist/layout/sunburst.js +126 -0
  70. package/dist/layout/types.d.ts +141 -0
  71. package/dist/layout/world.d.ts +9 -0
  72. package/dist/layout/world.js +144 -0
  73. package/dist/model/normalize.js +47 -1
  74. package/dist/model/tree.d.ts +27 -0
  75. package/dist/model/tree.js +182 -0
  76. package/dist/types.d.ts +55 -3
  77. package/package.json +9 -4
@@ -0,0 +1,33 @@
1
+ import { GraphState } from '../GraphState.svelte.js';
2
+ import type { EdgeStyle } from '../layout/types.js';
3
+ import type { GraphFields } from '../types.js';
4
+ import type { GraphPreset } from '../preset.js';
5
+ type Props = {
6
+ /**
7
+ * Share one state across this diagram and, say, an entity table beside it. Given one,
8
+ * the caller owns it: this component reads it and never calls `update`, exactly as
9
+ * `Graph` does — two owners writing one state fight on every render.
10
+ */
11
+ state?: GraphState;
12
+ nodes?: unknown[];
13
+ edges?: unknown[];
14
+ fields?: GraphFields;
15
+ /** The node to centre. Defaults to the selection. */
16
+ focus?: string | null;
17
+ /** How many hops out. One answers "what touches this"; two, "what does this reach". */
18
+ depth?: number;
19
+ edgeStyle?: EdgeStyle;
20
+ controls?: boolean;
21
+ maxDepth?: number;
22
+ legend?: boolean;
23
+ value?: string | null;
24
+ preset?: GraphPreset;
25
+ mode?: 'light' | 'dark';
26
+ arrows?: boolean;
27
+ label?: string;
28
+ onselect?: (id: string | null) => void;
29
+ class?: string;
30
+ };
31
+ declare const Neighborhood: import("svelte").Component<Props, {}, "focus" | "value" | "edgeStyle" | "depth">;
32
+ type Neighborhood = ReturnType<typeof Neighborhood>;
33
+ export default Neighborhood;
@@ -0,0 +1,131 @@
1
+ <script lang="ts">
2
+ /**
3
+ * A codebase as a radial dendrogram, with its calls bundled through the structure.
4
+ *
5
+ * What `CallTree` cannot be over a real repo. A call graph's own spanning tree has hundreds
6
+ * of roots, so capping its depth prunes almost nothing and the rim comes out a grey smear.
7
+ * Containment — crate, module, file — is a real tree with one root, which is what makes
8
+ * "show two levels, then drill" mean something.
9
+ *
10
+ * The calls are drawn ON that tree rather than defining it, bundled so edges travelling the
11
+ * same way through the hierarchy pull together. `bundleTension` is the Straight/Bundled
12
+ * toggle: 0 is a plain chord, 0.85 the full route.
13
+ */
14
+ import Graph from '../Graph.svelte'
15
+ import GraphLegend from '../GraphLegend.svelte'
16
+ import DiagramFrame from './DiagramFrame.svelte'
17
+ import DepthControl from '../controls/DepthControl.svelte'
18
+ import BundleControl from '../controls/BundleControl.svelte'
19
+ import ZoomControl from '../controls/ZoomControl.svelte'
20
+ import { GraphState } from '../GraphState.svelte.js'
21
+ import type { GraphFields } from '../types.js'
22
+ import type { GraphPreset } from '../preset.js'
23
+
24
+ type Props = {
25
+ /** Share one state with views beside this one. See `ErDiagram` for the contract. */
26
+ state?: GraphState
27
+ nodes?: unknown[]
28
+ edges?: unknown[]
29
+ fields?: GraphFields
30
+ /** How many ancestor bands to draw, counting from the focus. */
31
+ levels?: number
32
+ /** The subtree to render as the whole canvas. `[]` is the root. Drilling, not zooming. */
33
+ focusPath?: string[]
34
+ /** How hard edges are pulled onto the tree, 0..1. 0 is a straight chord. */
35
+ bundleTension?: number
36
+ /** What a leaf's dot is sized by. */
37
+ sizeBy?: string
38
+ sizeScale?: 'linear' | 'log'
39
+ controls?: boolean
40
+ maxLevels?: number
41
+ legend?: boolean
42
+ value?: string | null
43
+ preset?: GraphPreset
44
+ mode?: 'light' | 'dark'
45
+ label?: string
46
+ onselect?: (id: string | null) => void
47
+ class?: string
48
+ }
49
+
50
+ let {
51
+ state: provided,
52
+ nodes = [],
53
+ edges = [],
54
+ fields = {},
55
+ levels = $bindable(2),
56
+ focusPath = $bindable([]),
57
+ bundleTension = $bindable(0.85),
58
+ sizeBy = 'degree',
59
+ sizeScale = 'linear',
60
+ controls = false,
61
+ maxLevels = 4,
62
+ legend = false,
63
+ value = $bindable(undefined),
64
+ preset = undefined,
65
+ mode = 'light',
66
+ label = undefined,
67
+ onselect = undefined,
68
+ class: className = ''
69
+ }: Props = $props()
70
+
71
+ let zoom = $state(1)
72
+
73
+ const config = () => ({
74
+ nodes,
75
+ edges,
76
+ fields,
77
+ layout: 'structure',
78
+ levels,
79
+ focusPath,
80
+ bundleTension,
81
+ sizeBy,
82
+ sizeScale,
83
+ value,
84
+ preset,
85
+ mode,
86
+ label,
87
+ onselect
88
+ })
89
+
90
+ // svelte-ignore state_referenced_locally
91
+ const graph = provided ?? new GraphState(config())
92
+
93
+ $effect(() => {
94
+ if (!provided) {
95
+ graph.update(config())
96
+
97
+ return
98
+ }
99
+
100
+ // A supplied state is the caller's: their data, preset, mode and selection stay theirs
101
+ // and are never reset here. What this component DOES own is the options its own
102
+ // controls drive — the layout above all, since choosing this component is choosing it.
103
+ // `apply` merges; `update` would revert everything it does not name.
104
+ const { nodes: _n, edges: _e, fields: _f, preset: _p, mode: _m, value: _v, ...mine } =
105
+ config()
106
+ graph.apply(mine)
107
+ })
108
+ </script>
109
+
110
+ <!-- Snippets are declared OUTSIDE the frame and passed conditionally: one declared
111
+ inside is always defined, so the frame would render an empty control bar over
112
+ every diagram that asked for none. -->
113
+ {#snippet controlBar()}
114
+ <DepthControl {levels} max={maxLevels} onchange={(v) => (levels = v)} />
115
+ <BundleControl {bundleTension} onchange={(v) => (bundleTension = v)} />
116
+ <ZoomControl {zoom} onchange={(v) => (zoom = v)} />
117
+ {/snippet}
118
+
119
+ {#snippet legendBar()}
120
+ <GraphLegend state={graph} relations groups />
121
+ {/snippet}
122
+
123
+ <DiagramFrame
124
+ class={className}
125
+ overlay={controls ? controlBar : undefined}
126
+ footer={legend ? legendBar : undefined}
127
+ >
128
+ {#snippet canvas()}
129
+ <Graph state={graph} bind:zoom arrows={false} />
130
+ {/snippet}
131
+ </DiagramFrame>
@@ -0,0 +1,31 @@
1
+ import { GraphState } from '../GraphState.svelte.js';
2
+ import type { GraphFields } from '../types.js';
3
+ import type { GraphPreset } from '../preset.js';
4
+ type Props = {
5
+ /** Share one state with views beside this one. See `ErDiagram` for the contract. */
6
+ state?: GraphState;
7
+ nodes?: unknown[];
8
+ edges?: unknown[];
9
+ fields?: GraphFields;
10
+ /** How many ancestor bands to draw, counting from the focus. */
11
+ levels?: number;
12
+ /** The subtree to render as the whole canvas. `[]` is the root. Drilling, not zooming. */
13
+ focusPath?: string[];
14
+ /** How hard edges are pulled onto the tree, 0..1. 0 is a straight chord. */
15
+ bundleTension?: number;
16
+ /** What a leaf's dot is sized by. */
17
+ sizeBy?: string;
18
+ sizeScale?: 'linear' | 'log';
19
+ controls?: boolean;
20
+ maxLevels?: number;
21
+ legend?: boolean;
22
+ value?: string | null;
23
+ preset?: GraphPreset;
24
+ mode?: 'light' | 'dark';
25
+ label?: string;
26
+ onselect?: (id: string | null) => void;
27
+ class?: string;
28
+ };
29
+ declare const StructureDiagram: import("svelte").Component<Props, {}, "value" | "focusPath" | "levels" | "bundleTension">;
30
+ type StructureDiagram = ReturnType<typeof StructureDiagram>;
31
+ export default StructureDiagram;
@@ -0,0 +1,124 @@
1
+ <script lang="ts">
2
+ /**
3
+ * The same containment as a treemap, drawn as nested wedges.
4
+ *
5
+ * Angle carries the measure and RADIUS carries the depth, so how deep the tree goes is the
6
+ * first thing you read — which is exactly what a treemap makes you hunt for. A treemap
7
+ * spends its pixels better; neither is the right one, which is why both exist.
8
+ *
9
+ * Same tree, same measure, same captions as `Treemap`, so switching between them keeps
10
+ * your place.
11
+ */
12
+ import Graph from '../Graph.svelte'
13
+ import GraphLegend from '../GraphLegend.svelte'
14
+ import DiagramFrame from './DiagramFrame.svelte'
15
+ import DepthControl from '../controls/DepthControl.svelte'
16
+ import ZoomControl from '../controls/ZoomControl.svelte'
17
+ import { GraphState } from '../GraphState.svelte.js'
18
+ import type { GraphFields } from '../types.js'
19
+ import type { GraphPreset } from '../preset.js'
20
+
21
+ type Props = {
22
+ /**
23
+ * Share one state across this diagram and, say, an entity table beside it. Given one,
24
+ * the caller owns it: this component reads it and never calls `update`, exactly as
25
+ * `Graph` does — two owners writing one state fight on every render.
26
+ */
27
+ state?: GraphState
28
+ nodes?: unknown[]
29
+ edges?: unknown[]
30
+ fields?: GraphFields
31
+ /** What area encodes. A `measures` key, or `weight`, or `degree`. */
32
+ sizeBy?: string
33
+ /** How many levels below the focus to materialise. */
34
+ levels?: number
35
+ /** The subtree to render as the whole canvas. `[]` is the root. Drilling, not zooming. */
36
+ focusPath?: string[]
37
+ controls?: boolean
38
+ maxLevels?: number
39
+ legend?: boolean
40
+ value?: string | null
41
+ preset?: GraphPreset
42
+ mode?: 'light' | 'dark'
43
+ label?: string
44
+ onselect?: (id: string | null) => void
45
+ class?: string
46
+ }
47
+
48
+ let {
49
+ state: provided,
50
+ nodes = [],
51
+ edges = [],
52
+ fields = {},
53
+ sizeBy = 'weight',
54
+ levels = $bindable(2),
55
+ focusPath = $bindable([]),
56
+ controls = false,
57
+ maxLevels = 4,
58
+ legend = false,
59
+ value = $bindable(undefined),
60
+ preset = undefined,
61
+ mode = 'light',
62
+ label = undefined,
63
+ onselect = undefined,
64
+ class: className = ''
65
+ }: Props = $props()
66
+
67
+ let zoom = $state(1)
68
+
69
+ const config = () => ({
70
+ nodes,
71
+ edges,
72
+ fields,
73
+ layout: 'sunburst',
74
+ sizeBy,
75
+ levels,
76
+ focusPath,
77
+ value,
78
+ preset,
79
+ mode,
80
+ label,
81
+ onselect
82
+ })
83
+
84
+ // svelte-ignore state_referenced_locally
85
+ const graph = provided ?? new GraphState(config())
86
+
87
+ $effect(() => {
88
+ if (!provided) {
89
+ graph.update(config())
90
+
91
+ return
92
+ }
93
+
94
+ // A supplied state is the caller's: their data, preset, mode and selection stay theirs
95
+ // and are never reset here. What this component DOES own is the options its own
96
+ // controls drive — the layout above all, since choosing this component is choosing it.
97
+ // `apply` merges; `update` would revert everything it does not name.
98
+ const { nodes: _n, edges: _e, fields: _f, preset: _p, mode: _m, value: _v, ...mine } =
99
+ config()
100
+ graph.apply(mine)
101
+ })
102
+ </script>
103
+
104
+ <!-- Snippets are declared OUTSIDE the frame and passed conditionally: one declared
105
+ inside is always defined, so the frame would render an empty control bar over
106
+ every diagram that asked for none. -->
107
+ {#snippet controlBar()}
108
+ <DepthControl {levels} max={maxLevels} onchange={(v) => (levels = v)} />
109
+ <ZoomControl {zoom} onchange={(v) => (zoom = v)} />
110
+ {/snippet}
111
+
112
+ {#snippet legendBar()}
113
+ <GraphLegend state={graph} groups />
114
+ {/snippet}
115
+
116
+ <DiagramFrame
117
+ class={className}
118
+ overlay={controls ? controlBar : undefined}
119
+ footer={legend ? legendBar : undefined}
120
+ >
121
+ {#snippet canvas()}
122
+ <Graph state={graph} bind:zoom arrows={false} />
123
+ {/snippet}
124
+ </DiagramFrame>
@@ -0,0 +1,32 @@
1
+ import { GraphState } from '../GraphState.svelte.js';
2
+ import type { GraphFields } from '../types.js';
3
+ import type { GraphPreset } from '../preset.js';
4
+ type Props = {
5
+ /**
6
+ * Share one state across this diagram and, say, an entity table beside it. Given one,
7
+ * the caller owns it: this component reads it and never calls `update`, exactly as
8
+ * `Graph` does — two owners writing one state fight on every render.
9
+ */
10
+ state?: GraphState;
11
+ nodes?: unknown[];
12
+ edges?: unknown[];
13
+ fields?: GraphFields;
14
+ /** What area encodes. A `measures` key, or `weight`, or `degree`. */
15
+ sizeBy?: string;
16
+ /** How many levels below the focus to materialise. */
17
+ levels?: number;
18
+ /** The subtree to render as the whole canvas. `[]` is the root. Drilling, not zooming. */
19
+ focusPath?: string[];
20
+ controls?: boolean;
21
+ maxLevels?: number;
22
+ legend?: boolean;
23
+ value?: string | null;
24
+ preset?: GraphPreset;
25
+ mode?: 'light' | 'dark';
26
+ label?: string;
27
+ onselect?: (id: string | null) => void;
28
+ class?: string;
29
+ };
30
+ declare const Sunburst: import("svelte").Component<Props, {}, "value" | "focusPath" | "levels">;
31
+ type Sunburst = ReturnType<typeof Sunburst>;
32
+ export default Sunburst;
@@ -0,0 +1,124 @@
1
+ <script lang="ts">
2
+ /**
3
+ * Containment as nested rectangles, area proportional to a measure.
4
+ *
5
+ * Answers "where is the mass" — a box's area is what it CONTAINS, so the tree sums
6
+ * subtrees rather than counting nodes. Every box is the same shape at every depth,
7
+ * including a leaf: a treemap nests one thing.
8
+ *
9
+ * No edges. Containment IS the relationship here, and at this scale an adjacency graph
10
+ * cannot be drawn.
11
+ */
12
+ import Graph from '../Graph.svelte'
13
+ import GraphLegend from '../GraphLegend.svelte'
14
+ import DiagramFrame from './DiagramFrame.svelte'
15
+ import DepthControl from '../controls/DepthControl.svelte'
16
+ import ZoomControl from '../controls/ZoomControl.svelte'
17
+ import { GraphState } from '../GraphState.svelte.js'
18
+ import type { GraphFields } from '../types.js'
19
+ import type { GraphPreset } from '../preset.js'
20
+
21
+ type Props = {
22
+ /**
23
+ * Share one state across this diagram and, say, an entity table beside it. Given one,
24
+ * the caller owns it: this component reads it and never calls `update`, exactly as
25
+ * `Graph` does — two owners writing one state fight on every render.
26
+ */
27
+ state?: GraphState
28
+ nodes?: unknown[]
29
+ edges?: unknown[]
30
+ fields?: GraphFields
31
+ /** What area encodes. A `measures` key, or `weight`, or `degree`. */
32
+ sizeBy?: string
33
+ /** How many levels below the focus to materialise. */
34
+ levels?: number
35
+ /** The subtree to render as the whole canvas. `[]` is the root. Drilling, not zooming. */
36
+ focusPath?: string[]
37
+ controls?: boolean
38
+ maxLevels?: number
39
+ legend?: boolean
40
+ value?: string | null
41
+ preset?: GraphPreset
42
+ mode?: 'light' | 'dark'
43
+ label?: string
44
+ onselect?: (id: string | null) => void
45
+ class?: string
46
+ }
47
+
48
+ let {
49
+ state: provided,
50
+ nodes = [],
51
+ edges = [],
52
+ fields = {},
53
+ sizeBy = 'weight',
54
+ levels = $bindable(2),
55
+ focusPath = $bindable([]),
56
+ controls = false,
57
+ maxLevels = 4,
58
+ legend = false,
59
+ value = $bindable(undefined),
60
+ preset = undefined,
61
+ mode = 'light',
62
+ label = undefined,
63
+ onselect = undefined,
64
+ class: className = ''
65
+ }: Props = $props()
66
+
67
+ let zoom = $state(1)
68
+
69
+ const config = () => ({
70
+ nodes,
71
+ edges,
72
+ fields,
73
+ layout: 'world',
74
+ sizeBy,
75
+ levels,
76
+ focusPath,
77
+ value,
78
+ preset,
79
+ mode,
80
+ label,
81
+ onselect
82
+ })
83
+
84
+ // svelte-ignore state_referenced_locally
85
+ const graph = provided ?? new GraphState(config())
86
+
87
+ $effect(() => {
88
+ if (!provided) {
89
+ graph.update(config())
90
+
91
+ return
92
+ }
93
+
94
+ // A supplied state is the caller's: their data, preset, mode and selection stay theirs
95
+ // and are never reset here. What this component DOES own is the options its own
96
+ // controls drive — the layout above all, since choosing this component is choosing it.
97
+ // `apply` merges; `update` would revert everything it does not name.
98
+ const { nodes: _n, edges: _e, fields: _f, preset: _p, mode: _m, value: _v, ...mine } =
99
+ config()
100
+ graph.apply(mine)
101
+ })
102
+ </script>
103
+
104
+ <!-- Snippets are declared OUTSIDE the frame and passed conditionally: one declared
105
+ inside is always defined, so the frame would render an empty control bar over
106
+ every diagram that asked for none. -->
107
+ {#snippet controlBar()}
108
+ <DepthControl {levels} max={maxLevels} onchange={(v) => (levels = v)} />
109
+ <ZoomControl {zoom} onchange={(v) => (zoom = v)} />
110
+ {/snippet}
111
+
112
+ {#snippet legendBar()}
113
+ <GraphLegend state={graph} groups />
114
+ {/snippet}
115
+
116
+ <DiagramFrame
117
+ class={className}
118
+ overlay={controls ? controlBar : undefined}
119
+ footer={legend ? legendBar : undefined}
120
+ >
121
+ {#snippet canvas()}
122
+ <Graph state={graph} bind:zoom arrows={false} />
123
+ {/snippet}
124
+ </DiagramFrame>
@@ -0,0 +1,32 @@
1
+ import { GraphState } from '../GraphState.svelte.js';
2
+ import type { GraphFields } from '../types.js';
3
+ import type { GraphPreset } from '../preset.js';
4
+ type Props = {
5
+ /**
6
+ * Share one state across this diagram and, say, an entity table beside it. Given one,
7
+ * the caller owns it: this component reads it and never calls `update`, exactly as
8
+ * `Graph` does — two owners writing one state fight on every render.
9
+ */
10
+ state?: GraphState;
11
+ nodes?: unknown[];
12
+ edges?: unknown[];
13
+ fields?: GraphFields;
14
+ /** What area encodes. A `measures` key, or `weight`, or `degree`. */
15
+ sizeBy?: string;
16
+ /** How many levels below the focus to materialise. */
17
+ levels?: number;
18
+ /** The subtree to render as the whole canvas. `[]` is the root. Drilling, not zooming. */
19
+ focusPath?: string[];
20
+ controls?: boolean;
21
+ maxLevels?: number;
22
+ legend?: boolean;
23
+ value?: string | null;
24
+ preset?: GraphPreset;
25
+ mode?: 'light' | 'dark';
26
+ label?: string;
27
+ onselect?: (id: string | null) => void;
28
+ class?: string;
29
+ };
30
+ declare const Treemap: import("svelte").Component<Props, {}, "value" | "focusPath" | "levels">;
31
+ type Treemap = ReturnType<typeof Treemap>;
32
+ export default Treemap;
package/dist/icons.d.ts CHANGED
@@ -1,6 +1,11 @@
1
1
  /**
2
2
  * Default glyph per node kind and row badge.
3
3
  *
4
+ * Reachable as `@rokkit/graph/icons` — a subpath with NO Svelte imports, because the one
5
+ * place a consumer is REQUIRED to use it is a UnoCSS config, which Node loads directly and
6
+ * which therefore cannot import the main barrel (that re-exports `Graph.svelte`, and Node
7
+ * cannot parse `.svelte`). Found by dbd wiring its safelist.
8
+ *
4
9
  * `i-glyph:<name>` is the vocabulary this repo actually ships — `packages/icons/lib/glyph.json`,
5
10
  * 697 names, safelisted wholesale by the app's UnoCSS config. An earlier version of this map
6
11
  * used `i-graph-<kind>`, which is defined nowhere: UnoCSS emitted no rule, so every kind
package/dist/icons.js CHANGED
@@ -1,6 +1,11 @@
1
1
  /**
2
2
  * Default glyph per node kind and row badge.
3
3
  *
4
+ * Reachable as `@rokkit/graph/icons` — a subpath with NO Svelte imports, because the one
5
+ * place a consumer is REQUIRED to use it is a UnoCSS config, which Node loads directly and
6
+ * which therefore cannot import the main barrel (that re-exports `Graph.svelte`, and Node
7
+ * cannot parse `.svelte`). Found by dbd wiring its safelist.
8
+ *
4
9
  * `i-glyph:<name>` is the vocabulary this repo actually ships — `packages/icons/lib/glyph.json`,
5
10
  * 697 names, safelisted wholesale by the app's UnoCSS config. An earlier version of this map
6
11
  * used `i-graph-<kind>`, which is defined nowhere: UnoCSS emitted no rule, so every kind
package/dist/index.d.ts CHANGED
@@ -1,10 +1,27 @@
1
1
  export { default as Graph } from './Graph.svelte';
2
+ export { default as GraphLegend } from './GraphLegend.svelte';
3
+ export { default as ErDiagram } from './diagrams/ErDiagram.svelte';
4
+ export { default as DependencyDiagram } from './diagrams/DependencyDiagram.svelte';
5
+ export { default as CallTree } from './diagrams/CallTree.svelte';
6
+ export { default as Treemap } from './diagrams/Treemap.svelte';
7
+ export { default as Sunburst } from './diagrams/Sunburst.svelte';
8
+ export { default as StructureDiagram } from './diagrams/StructureDiagram.svelte';
9
+ export { default as Neighborhood } from './diagrams/Neighborhood.svelte';
10
+ export { default as DensityControl } from './controls/DensityControl.svelte';
11
+ export { default as EdgeStyleControl } from './controls/EdgeStyleControl.svelte';
12
+ export { default as ZoomControl } from './controls/ZoomControl.svelte';
13
+ export { default as DepthControl } from './controls/DepthControl.svelte';
14
+ export { default as BundleControl } from './controls/BundleControl.svelte';
15
+ export { ZOOM_MIN, ZOOM_MAX, ZOOM_STEP, clampZoom } from './controls/zoom.js';
2
16
  export { GraphState } from './GraphState.svelte.js';
3
17
  export { normalizeGraph } from './model/normalize.js';
18
+ export { buildTree, findNode } from './model/tree.js';
19
+ export type { TreeNode } from './model/tree.js';
4
20
  export { readPath } from './model/path.js';
5
21
  export { createGraphPreset, defaultGraphPreset, resolveGroupStyles } from './preset.js';
6
22
  export { DEFAULT_ICONS } from './icons.js';
7
- export { cluster, neighborhood, points, layouts } from './layout/index.js';
23
+ export { cluster, flow, neighborhood, points, radial, structure, sunburst, world, layouts } from './layout/index.js';
24
+ export { LAYOUT_OPTIONS, appliesTo } from './layout/options.js';
8
25
  export type { EntityRow, GraphStateConfig, Relationship } from './GraphState.svelte.js';
9
26
  export type { GraphChannel, GraphPreset, GraphShades } from './preset.js';
10
27
  export type * from './types.js';
package/dist/index.js CHANGED
@@ -1,8 +1,30 @@
1
1
  // Public surface for `@rokkit/graph`.
2
+ // The canvas. It draws what a layout hands it and ships no chrome — pair it with the
3
+ // controls below, or reach for a named diagram, which is the composition already made.
2
4
  export { default as Graph } from './Graph.svelte';
5
+ export { default as GraphLegend } from './GraphLegend.svelte';
6
+ // Named diagrams: one layout, the controls that mean something for that picture, an opt-in
7
+ // legend. `@rokkit/chart` has `BarChart` and `LineChart` over one `Plot`; these are the same
8
+ // idea over one `Graph`, and each is usable on its own.
9
+ export { default as ErDiagram } from './diagrams/ErDiagram.svelte';
10
+ export { default as DependencyDiagram } from './diagrams/DependencyDiagram.svelte';
11
+ export { default as CallTree } from './diagrams/CallTree.svelte';
12
+ export { default as Treemap } from './diagrams/Treemap.svelte';
13
+ export { default as Sunburst } from './diagrams/Sunburst.svelte';
14
+ export { default as StructureDiagram } from './diagrams/StructureDiagram.svelte';
15
+ export { default as Neighborhood } from './diagrams/Neighborhood.svelte';
16
+ // Controls, for composing your own arrangement over the bare canvas.
17
+ export { default as DensityControl } from './controls/DensityControl.svelte';
18
+ export { default as EdgeStyleControl } from './controls/EdgeStyleControl.svelte';
19
+ export { default as ZoomControl } from './controls/ZoomControl.svelte';
20
+ export { default as DepthControl } from './controls/DepthControl.svelte';
21
+ export { default as BundleControl } from './controls/BundleControl.svelte';
22
+ export { ZOOM_MIN, ZOOM_MAX, ZOOM_STEP, clampZoom } from './controls/zoom.js';
3
23
  export { GraphState } from './GraphState.svelte.js';
4
24
  export { normalizeGraph } from './model/normalize.js';
25
+ export { buildTree, findNode } from './model/tree.js';
5
26
  export { readPath } from './model/path.js';
6
27
  export { createGraphPreset, defaultGraphPreset, resolveGroupStyles } from './preset.js';
7
28
  export { DEFAULT_ICONS } from './icons.js';
8
- export { cluster, neighborhood, points, layouts } from './layout/index.js';
29
+ export { cluster, flow, neighborhood, points, radial, structure, sunburst, world, layouts } from './layout/index.js';
30
+ export { LAYOUT_OPTIONS, appliesTo } from './layout/options.js';
@@ -0,0 +1,13 @@
1
+ export type Wedge = {
2
+ r0: number;
3
+ r1: number;
4
+ a0: number;
5
+ a1: number;
6
+ };
7
+ /**
8
+ * The wedge as a path, centred on `(cx, cy)`.
9
+ *
10
+ * An innermost wedge has `r0 === 0`, where the two inner corners are the same point and an
11
+ * inner arc is undefined — that one is a pie slice, closing through the centre instead.
12
+ */
13
+ export declare function arcPath(cx: number, cy: number, wedge: Wedge): string;
@@ -0,0 +1,58 @@
1
+ /* An annulus sector as an SVG path.
2
+ *
3
+ * Kept out of the component because it is arithmetic, not rendering: the layout reports a
4
+ * wedge as four numbers, and turning those into a path is a pure function that can be tested
5
+ * to exact coordinates. The same split `edgePath` already makes.
6
+ */
7
+ const TAU = Math.PI * 2;
8
+ /** Point on a circle of radius `r` at angle `a`, relative to a centre at the origin. */
9
+ function at(cx, cy, r, a) {
10
+ return [cx + Math.cos(a) * r, cy + Math.sin(a) * r];
11
+ }
12
+ const fmt = (n) => Number(n.toFixed(3));
13
+ /**
14
+ * A full turn cannot be one arc.
15
+ *
16
+ * SVG's `A` command draws the arc BETWEEN two points, and for a complete circle those two
17
+ * points coincide — so the command is a no-op and the wedge vanishes. A single child covering
18
+ * its parent's whole span is the common case at the root, not an edge case, so the span is
19
+ * halved and drawn as two arcs.
20
+ */
21
+ function isFullTurn(wedge) {
22
+ return wedge.a1 - wedge.a0 >= TAU - 1e-9;
23
+ }
24
+ /** Ring path for a span that covers the whole circle: two half-arcs, outer then inner. */
25
+ function fullRing(cx, cy, wedge) {
26
+ const { r0, r1 } = wedge;
27
+ const ring = (r, sweep) => {
28
+ const [ax, ay] = at(cx, cy, r, 0);
29
+ const [bx, by] = at(cx, cy, r, Math.PI);
30
+ return (`M ${fmt(ax)} ${fmt(ay)} ` +
31
+ `A ${fmt(r)} ${fmt(r)} 0 0 ${sweep} ${fmt(bx)} ${fmt(by)} ` +
32
+ `A ${fmt(r)} ${fmt(r)} 0 0 ${sweep} ${fmt(ax)} ${fmt(ay)} Z`);
33
+ };
34
+ // The inner circle is drawn the opposite way round, so the even-odd/nonzero fill punches
35
+ // it out and the result is a ring rather than a disc.
36
+ return r0 > 0 ? `${ring(r1, 1)} ${ring(r0, 0)}` : ring(r1, 1);
37
+ }
38
+ /**
39
+ * The wedge as a path, centred on `(cx, cy)`.
40
+ *
41
+ * An innermost wedge has `r0 === 0`, where the two inner corners are the same point and an
42
+ * inner arc is undefined — that one is a pie slice, closing through the centre instead.
43
+ */
44
+ export function arcPath(cx, cy, wedge) {
45
+ if (isFullTurn(wedge))
46
+ return fullRing(cx, cy, wedge);
47
+ const { r0, r1, a0, a1 } = wedge;
48
+ const large = a1 - a0 > Math.PI ? 1 : 0;
49
+ const [ox0, oy0] = at(cx, cy, r1, a0);
50
+ const [ox1, oy1] = at(cx, cy, r1, a1);
51
+ const outer = `M ${fmt(ox0)} ${fmt(oy0)} A ${fmt(r1)} ${fmt(r1)} 0 ${large} 1 ${fmt(ox1)} ${fmt(oy1)}`;
52
+ if (r0 <= 0)
53
+ return `${outer} L ${fmt(cx)} ${fmt(cy)} Z`;
54
+ const [ix1, iy1] = at(cx, cy, r0, a1);
55
+ const [ix0, iy0] = at(cx, cy, r0, a0);
56
+ return (`${outer} L ${fmt(ix1)} ${fmt(iy1)} ` +
57
+ `A ${fmt(r0)} ${fmt(r0)} 0 ${large} 0 ${fmt(ix0)} ${fmt(iy0)} Z`);
58
+ }