@rokkit/graph 1.8.0 → 1.8.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 (119) hide show
  1. package/README.md +59 -0
  2. package/dist/Graph.svelte +108 -134
  3. package/dist/Graph.svelte.d.ts +1 -1
  4. package/dist/GraphLegend.svelte +81 -10
  5. package/dist/GraphLegend.svelte.d.ts +15 -0
  6. package/dist/GraphState.svelte.d.ts +161 -52
  7. package/dist/GraphState.svelte.js +380 -304
  8. package/dist/actions/canvas.d.ts +18 -0
  9. package/dist/actions/canvas.js +59 -0
  10. package/dist/actions/choices.d.ts +12 -0
  11. package/dist/actions/choices.js +23 -0
  12. package/dist/actions/interactions.d.ts +20 -0
  13. package/dist/actions/interactions.js +57 -0
  14. package/dist/actions/listen.d.ts +2 -0
  15. package/dist/actions/listen.js +10 -0
  16. package/dist/canvas/frame.d.ts +41 -0
  17. package/dist/canvas/frame.js +34 -0
  18. package/dist/controls/BundleControl.svelte +11 -10
  19. package/dist/controls/BundleControl.svelte.d.ts +0 -7
  20. package/dist/controls/DensityControl.svelte +17 -9
  21. package/dist/controls/DensityControl.svelte.d.ts +0 -8
  22. package/dist/controls/DepthControl.svelte +11 -4
  23. package/dist/controls/DepthControl.svelte.d.ts +0 -9
  24. package/dist/controls/DrillBar.svelte +63 -0
  25. package/dist/controls/DrillBar.svelte.d.ts +9 -0
  26. package/dist/controls/EdgeStyleControl.svelte +10 -10
  27. package/dist/controls/EdgeStyleControl.svelte.d.ts +0 -6
  28. package/dist/controls/HiddenControl.svelte +27 -0
  29. package/dist/controls/HiddenControl.svelte.d.ts +7 -0
  30. package/dist/controls/MeasureControl.svelte +39 -0
  31. package/dist/controls/MeasureControl.svelte.d.ts +12 -0
  32. package/dist/controls/ToggleControl.svelte +33 -0
  33. package/dist/controls/ToggleControl.svelte.d.ts +13 -0
  34. package/dist/controls/ViolationsControl.svelte +27 -0
  35. package/dist/controls/ViolationsControl.svelte.d.ts +7 -0
  36. package/dist/controls/ZoomControl.svelte +21 -18
  37. package/dist/controls/zoom.d.ts +3 -0
  38. package/dist/controls/zoom.js +6 -0
  39. package/dist/diagrams/ArcDiagram.svelte +116 -0
  40. package/dist/diagrams/ArcDiagram.svelte.d.ts +31 -0
  41. package/dist/diagrams/CallTree.svelte +17 -5
  42. package/dist/diagrams/CallTree.svelte.d.ts +5 -1
  43. package/dist/diagrams/DependencyDiagram.svelte +18 -6
  44. package/dist/diagrams/DependencyDiagram.svelte.d.ts +5 -1
  45. package/dist/diagrams/DependencyMatrix.svelte +11 -32
  46. package/dist/diagrams/ErDiagram.svelte +18 -6
  47. package/dist/diagrams/ErDiagram.svelte.d.ts +5 -1
  48. package/dist/diagrams/LayersDiagram.svelte +124 -0
  49. package/dist/diagrams/LayersDiagram.svelte.d.ts +30 -0
  50. package/dist/diagrams/Neighborhood.svelte +26 -6
  51. package/dist/diagrams/Neighborhood.svelte.d.ts +11 -1
  52. package/dist/diagrams/PolymetricTree.svelte +116 -0
  53. package/dist/diagrams/PolymetricTree.svelte.d.ts +28 -0
  54. package/dist/diagrams/StructureDiagram.svelte +38 -8
  55. package/dist/diagrams/StructureDiagram.svelte.d.ts +9 -1
  56. package/dist/diagrams/Sunburst.svelte +44 -8
  57. package/dist/diagrams/Sunburst.svelte.d.ts +12 -2
  58. package/dist/diagrams/Treemap.svelte +44 -8
  59. package/dist/diagrams/Treemap.svelte.d.ts +12 -2
  60. package/dist/index.d.ts +10 -3
  61. package/dist/index.js +9 -2
  62. package/dist/layout/arcs.d.ts +6 -0
  63. package/dist/layout/arcs.js +141 -0
  64. package/dist/layout/cards.js +9 -2
  65. package/dist/layout/edges.d.ts +13 -1
  66. package/dist/layout/edges.js +26 -2
  67. package/dist/layout/extent.d.ts +17 -0
  68. package/dist/layout/extent.js +27 -0
  69. package/dist/layout/flow.js +3 -1
  70. package/dist/layout/index.d.ts +4 -1
  71. package/dist/layout/index.js +17 -2
  72. package/dist/layout/layers.d.ts +6 -0
  73. package/dist/layout/layers.js +180 -0
  74. package/dist/layout/matrix.d.ts +12 -0
  75. package/dist/layout/matrix.js +20 -0
  76. package/dist/layout/neighborhood.js +16 -7
  77. package/dist/layout/options.d.ts +1 -1
  78. package/dist/layout/options.js +16 -3
  79. package/dist/layout/percentile.d.ts +8 -0
  80. package/dist/layout/percentile.js +13 -0
  81. package/dist/layout/polymetric.d.ts +3 -0
  82. package/dist/layout/polymetric.js +221 -0
  83. package/dist/layout/radial.js +3 -1
  84. package/dist/layout/structure.js +7 -1
  85. package/dist/layout/sunburst.js +11 -4
  86. package/dist/layout/types.d.ts +79 -0
  87. package/dist/layout/world.js +11 -4
  88. package/dist/messages.d.ts +14 -0
  89. package/dist/messages.js +17 -0
  90. package/dist/model/condense.d.ts +8 -0
  91. package/dist/model/condense.js +114 -0
  92. package/dist/model/entities.d.ts +12 -0
  93. package/dist/model/entities.js +12 -0
  94. package/dist/model/normalize.d.ts +2 -6
  95. package/dist/model/normalize.js +64 -2
  96. package/dist/model/relationships.d.ts +30 -0
  97. package/dist/model/relationships.js +51 -0
  98. package/dist/model/share.d.ts +9 -0
  99. package/dist/model/share.js +43 -0
  100. package/dist/model/tree.d.ts +7 -1
  101. package/dist/model/tree.js +11 -4
  102. package/dist/preset.d.ts +18 -0
  103. package/dist/preset.js +34 -3
  104. package/dist/schema/EntitiesView.svelte +8 -6
  105. package/dist/schema/EntityView.svelte +13 -10
  106. package/dist/state/GraphConfig.svelte.d.ts +124 -0
  107. package/dist/state/GraphConfig.svelte.js +253 -0
  108. package/dist/state/GraphDrill.svelte.d.ts +52 -0
  109. package/dist/state/GraphDrill.svelte.js +115 -0
  110. package/dist/state/GraphGroups.svelte.d.ts +35 -0
  111. package/dist/state/GraphGroups.svelte.js +73 -0
  112. package/dist/state/GraphSelection.svelte.d.ts +53 -0
  113. package/dist/state/GraphSelection.svelte.js +94 -0
  114. package/dist/state/intents.d.ts +33 -0
  115. package/dist/state/intents.js +30 -0
  116. package/dist/state/text.d.ts +28 -0
  117. package/dist/state/text.js +56 -0
  118. package/dist/types.d.ts +72 -1
  119. package/package.json +3 -2
@@ -1,26 +1,18 @@
1
1
  import { SvelteSet } from 'svelte/reactivity';
2
2
  import type { GraphPreset } from './preset.js';
3
- import type { Arrange, Cards, Cluster, Column, Density, EdgeStyle, LayoutFn, NodeAxis, RoutedEdge, Size } from './layout/types.js';
3
+ import type { Arrange, Cards, Cluster, Column, Density, EdgeStyle, LayoutFn, NodeAxis, RoutedEdge, ShowEdges, Size, LayoutResult } from './layout/types.js';
4
4
  import type { GraphEdge, GraphFields, GraphModel, GraphNode } from './types.js';
5
- export type EntityRow = {
6
- id: string;
7
- label: string;
8
- group?: string;
9
- kind?: string;
10
- rowCount: number;
11
- refCount: number;
12
- note?: string;
13
- };
14
- export type Relationship = {
15
- direction: 'in' | 'out';
16
- id: string;
17
- label: string;
18
- group?: string;
19
- /** The canonical edge — always present. A relationship is a fact about the model. */
20
- edge: GraphEdge;
21
- /** Routed geometry, present only when the ACTIVE layout placed this edge. */
22
- routed?: RoutedEdge;
23
- };
5
+ import type { Relationship } from './model/relationships.js';
6
+ import type { EntityRow } from './model/entities.js';
7
+ import { GraphConfig } from './state/GraphConfig.svelte.js';
8
+ import { GraphSelection } from './state/GraphSelection.svelte.js';
9
+ import { GraphDrill } from './state/GraphDrill.svelte.js';
10
+ import { GraphGroups } from './state/GraphGroups.svelte.js';
11
+ import type { GroupAction } from './state/GraphGroups.svelte.js';
12
+ import type { Intent } from './state/intents.js';
13
+ import type { ChannelRow } from './state/text.js';
14
+ import type { Breadcrumb } from './state/GraphDrill.svelte.js';
15
+ export type { Relationship, EntityRow, Breadcrumb, GroupAction };
24
16
  export type GraphStateConfig = {
25
17
  nodes?: unknown[];
26
18
  edges?: unknown[];
@@ -66,9 +58,66 @@ export type GraphStateConfig = {
66
58
  mode?: 'light' | 'dark';
67
59
  label?: string;
68
60
  onselect?: (id: string | null) => void;
61
+ /**
62
+ * The reader drilled INTO a box: `path` is the new `focusPath`, `node` the declared node at
63
+ * it (null for a container nothing declared). Return a promise to show a pending state
64
+ * until the level's data arrives; a rejection restores the previous level. Distinct from
65
+ * `onselect` — drilling changes scope, it does not select.
66
+ */
67
+ ondrill?: (path: string[], node: GraphNode | null) => void | Promise<void>;
68
+ /** The reader drilled OUT; `path` is the new, shorter `focusPath`. Same promise contract. */
69
+ ondrillup?: (path: string[]) => void | Promise<void>;
70
+ /**
71
+ * Every internal change of `focusPath` — drill in, out, or a rollback after a failed load.
72
+ * For a component that owns a bindable `focusPath` prop, so its next `update()` agrees.
73
+ */
74
+ onfocuspath?: (path: string[]) => void;
75
+ /**
76
+ * The reader expanded a group (#166). With its members already in `nodes` they appear at
77
+ * once; a host that sends only the group can load them in answer.
78
+ */
79
+ onexpand?: (id: string, node: GraphNode) => void;
80
+ /** The reader collapsed a group back into one node. */
81
+ oncollapse?: (id: string, node: GraphNode) => void;
82
+ /**
83
+ * Every edge (the default), or only the ones the view is about: `violations` in `layers`
84
+ * (#167), `hidden` in `arcs` (#169).
85
+ */
86
+ showEdges?: ShowEdges;
87
+ /** `layers` only — band names by layer index. */
88
+ layerLabels?: string[];
89
+ /** `polymetric` only — the measures box width, height and shade encode (#168). */
90
+ widthBy?: string;
91
+ heightBy?: string;
92
+ colorBy?: string;
93
+ /** `arcs` only — the relation drawn on the right of the axis (#169). */
94
+ above?: string;
95
+ /** `world` / `sunburst` — the measure (a 0..1 share) each box is shaded by (#164). */
96
+ shadeBy?: string;
69
97
  };
98
+ /**
99
+ * The store. Turns raw `nodes`/`edges`/`fields` into the reactive shape the visuals
100
+ * render, and owns every transition.
101
+ *
102
+ * Components read from this and call its methods — they never compute. That is what
103
+ * lets the geometry, badge derivation and selection logic be covered exhaustively
104
+ * with no DOM, and lets the component specs assert only attributes.
105
+ *
106
+ * A composition: `config` (every input, `state/GraphConfig`) feeds the layout pipeline
107
+ * derived here; the selection and the view queries read both. `update()` FULLY re-applies
108
+ * config rather than merging deltas — so a prop reverting to undefined actually reverts;
109
+ * `apply()` merges.
110
+ */
70
111
  export declare class GraphState {
71
112
  #private;
113
+ /** Every input — see `CONFIG_FIELDS` for what each omitted key falls back to. */
114
+ readonly config: GraphConfig;
115
+ /** Which subtree is the canvas, and the host events for moving it (#165). */
116
+ readonly drill: GraphDrill;
117
+ /** What the reader picked and opened. */
118
+ readonly selection: GraphSelection;
119
+ /** Which groups are collapsed (#166). */
120
+ readonly groups: GraphGroups;
72
121
  constructor(config?: GraphStateConfig);
73
122
  /**
74
123
  * Fully re-applies config. Safe to call on every prop change.
@@ -88,27 +137,41 @@ export declare class GraphState {
88
137
  */
89
138
  apply(config: Partial<GraphStateConfig>): void;
90
139
  select(id: string): void;
140
+ /** Drop the selection and report `null` — see `GraphSelection.clear`. */
141
+ clear(): void;
142
+ /** Show one node's rows in full, whatever the density says — see `GraphSelection`. */
143
+ toggleExpanded(id: string): void;
144
+ isExpanded(id: string): boolean;
145
+ isGroup(id: string): boolean;
146
+ isCollapsed(id: string): boolean;
147
+ memberCount(id: string): number;
148
+ groupOf(id: string): string | null;
91
149
  /**
92
- * Drop the selection, and SAY SO.
93
- *
94
- * Found by dbd consuming the package: it owns `selected` in its route and branches on it
95
- * to show the entity panel, so a silent clear left that panel open over nothing. A
96
- * controlled consumer cannot observe an internal `#value` — the callback is the only
97
- * channel, which is why it carries `null` rather than being skipped.
98
- *
99
- * Guarded on an actual change, or a background click on an already-empty canvas
100
- * round-trips through the consumer's setter on every stray click.
150
+ * Expand or collapse a group. Collapsing one whose member is selected moves the selection to
151
+ * the group: the thing being looked at is now inside it, and a selection naming a hidden node
152
+ * would leave the entity panel empty for no visible reason.
101
153
  */
102
- clear(): void;
154
+ toggleGroup(id: string): boolean;
155
+ /** The selection's group action — what a drill bar offers. */
156
+ get groupAction(): GroupAction | null;
157
+ get drillPath(): string[];
158
+ get breadcrumbs(): Breadcrumb[];
159
+ /** A drill's handler returned a promise that has not settled. */
160
+ get pending(): boolean;
161
+ get drillError(): unknown;
162
+ canDrill(box: Cluster): boolean;
163
+ drillInto(box: Cluster): boolean;
164
+ drillOut(levels?: number): boolean;
165
+ drillTo(path: string[]): boolean;
103
166
  /**
104
- * Show one node's rows in full, whatever the density says.
105
- *
106
- * Per NODE rather than a global density change: a reader who clicks "+3 more" on one
107
- * card is asking about that card, and expanding all of them answers a question they did
108
- * not ask — on a large diagram it also relayouts everything under them.
167
+ * The selected box, when it can be opened — what a drill bar's "Open" acts on. The keyboard
168
+ * route into a leaf: Enter selects it, and this is the next step.
109
169
  */
110
- toggleExpanded(id: string): void;
111
- isExpanded(id: string): boolean;
170
+ /** The failed drill, worded for the reader; null when the last drill did not fail. */
171
+ get drillErrorText(): string | null;
172
+ get drillTarget(): Cluster | null;
173
+ /** Whether a drill bar has anything to show: a trail, a load, a failure, or a box to open. */
174
+ get showsDrillBar(): boolean;
112
175
  /**
113
176
  * The more-row's text, or null when the card is hiding nothing and needs no control.
114
177
  *
@@ -130,17 +193,24 @@ export declare class GraphState {
130
193
  * prop would render, click, and change nothing.
131
194
  */
132
195
  setDensity(density: Density): void;
196
+ /** Every edge or only the climbing ones — what `ViolationsControl` drives (#167). */
197
+ setShowEdges(value: ShowEdges): void;
198
+ get showEdges(): ShowEdges;
133
199
  nodeState(id: string): 'selected' | 'related' | 'dim' | null;
134
200
  edgeState(edge: RoutedEdge): 'highlight' | 'dim' | null;
135
201
  edgePath(edge: RoutedEdge): string;
136
202
  groupStyle(group: string | undefined): Record<string, string>;
137
203
  /**
138
- * The same style as a `style=` attribute string.
139
- *
140
- * A template cannot spread an object into `style`, so something has to serialise it.
141
- * Doing that inline put the same map/join in two places in `Graph.svelte` — a derivation
142
- * living in a component, which is the one thing this layer exists to prevent.
204
+ * A box's paint as a style attribute: the shade ramp's step for its share when shading
205
+ * (#164), else its group's colour. Custom properties, so a theme still has the last word.
143
206
  */
207
+ boxStyleAttr(cluster: Cluster): string;
208
+ /** What a legend says about the shade: the measure and the ramp's two ends, or null. */
209
+ get shadeLegend(): {
210
+ measure: string;
211
+ low: string;
212
+ high: string;
213
+ } | null;
144
214
  groupStyleAttr(group: string | undefined): string;
145
215
  get model(): GraphModel;
146
216
  /**
@@ -160,7 +230,8 @@ export declare class GraphState {
160
230
  get overlayEdges(): GraphEdge[];
161
231
  /**
162
232
  * An edge's weight as 0..1 of the heaviest weighted edge, for stroke width — or undefined
163
- * for an edge with no weight, which draws at the theme's normal width.
233
+ * for an edge with no weight, which draws at the theme's normal width. A layout's own
234
+ * per-set `strength` wins.
164
235
  */
165
236
  edgeWeight(edge: RoutedEdge): number | undefined;
166
237
  get size(): Size;
@@ -190,14 +261,6 @@ export declare class GraphState {
190
261
  get unplacedEdges(): GraphEdge[];
191
262
  get density(): Density;
192
263
  get arrange(): Arrange;
193
- /**
194
- * A cluster's unique render key.
195
- *
196
- * NOT the name: nesting puts a `table` box under `public` AND under `billing`, and keying
197
- * an `{#each}` by name alone is a duplicate key — Svelte throws `each_key_duplicate`, the
198
- * render aborts, and no inner box appears at all, which reads as nesting silently not
199
- * working rather than as an error.
200
- */
201
264
  /**
202
265
  * The SVG path for a wedge-shaped box, centred on the canvas.
203
266
  *
@@ -212,7 +275,53 @@ export declare class GraphState {
212
275
  * differ only in the element and its role, which is exactly the difference that matters.
213
276
  */
214
277
  boxAttrs(cluster: Cluster): Record<string, string | null | undefined>;
278
+ /** Whether a box takes the pointer and the keyboard: it has an intent. */
279
+ interactive(cluster: Cluster): boolean;
280
+ /** A box's visible caption: its name, and the layout's caption or its count. */
281
+ caption(cluster: Cluster): string;
282
+ /**
283
+ * A node card's hooks and intents: it selects on press, and folds or opens its group on open
284
+ * (#166). A card with nothing below its head — no rows shown, none to reveal, not a group —
285
+ * is marked head-only so the theme can drop the empty body.
286
+ */
287
+ cardAttrs(key: string): Record<string, string | undefined>;
288
+ /** What a card's head counts: a group, the members it stands for; anything else, its rows. */
289
+ cardCount(key: string): number;
290
+ /** The "more rows" control's hooks: it expands the card, and says when a filter emptied it. */
291
+ moreAttrs(key: string): Record<string, string | undefined>;
292
+ /**
293
+ * The box a `data-graph-key` names, if it is on the canvas: a container by its render key,
294
+ * a leaf by its node id — the one key a leaf carries for both its press and its open.
295
+ */
296
+ boxFor(key: string): Cluster | undefined;
297
+ /**
298
+ * Perform an intent read off the DOM (see `state/intents`). An unknown intent, or a key
299
+ * that names nothing, does nothing — the DOM is not a trusted source.
300
+ */
301
+ act(intent: Intent, key: string | null): void;
302
+ /**
303
+ * A cluster's unique render key.
304
+ *
305
+ * NOT the name: nesting puts a `table` box under `public` AND under `billing`, and keying
306
+ * an `{#each}` by name alone is a duplicate key — Svelte throws `each_key_duplicate`, the
307
+ * render aborts, and no inner box appears at all, which reads as nesting silently not
308
+ * working rather than as an error.
309
+ */
215
310
  clusterKey(cluster: Cluster): string;
311
+ /** `polymetric` — which measure is on which channel, and each one's cap; for the legend. */
312
+ get channels(): LayoutResult['channels'];
313
+ /** The polymetric legend's rows, labelled from the locale (#168). */
314
+ get channelRows(): ChannelRow[];
315
+ /** What each side of an arc diagram shows, named from the data or the locale (#169). */
316
+ get sideNames(): {
317
+ below: string;
318
+ above: string;
319
+ };
320
+ /**
321
+ * Every measure a channel could bind: the keys in the nodes' `measures`, plus `weight` and
322
+ * `degree`, which every node has an answer for. Sorted, so a picker does not reshuffle.
323
+ */
324
+ get measureKeys(): string[];
216
325
  get groupBy(): NodeAxis;
217
326
  /**
218
327
  * The node kinds actually present, sorted.
@@ -231,9 +340,9 @@ export declare class GraphState {
231
340
  get relationsPresent(): string[];
232
341
  /** The group names present, sorted. Same reasoning as `kindsPresent`. */
233
342
  get groupsPresent(): string[];
234
- /** Whether cards carry the group ramp themselves. See `GraphStateConfig.groupTint`. */
235
343
  /** `dot` or `card` — what the active layout draws a node as. */
236
344
  get nodeShape(): 'dot' | 'card';
345
+ /** Whether cards carry the group ramp themselves. See `GraphStateConfig.groupTint`. */
237
346
  get groupTint(): boolean;
238
347
  get nestBy(): NodeAxis | null;
239
348
  get sizeBy(): string;