@data-navigator/inspector 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/package.json +1 -1
- package/src/tree-graph.js +45 -16
package/README.md
CHANGED
|
@@ -26,6 +26,29 @@ Data Navigator is organized into 3 composable modules:
|
|
|
26
26
|
|
|
27
27
|
These modules can be used together or independently. Visit [the docs](https://dig.cmu.edu/data-navigator/getting-started/) for a step-by-step guide to building your first navigable chart.
|
|
28
28
|
|
|
29
|
+
## Inspector
|
|
30
|
+
|
|
31
|
+
The optional **[@data-navigator/inspector](https://www.npmjs.com/package/@data-navigator/inspector)** package provides a visual graph of your data-navigator structure, useful for debugging and understanding navigation paths.
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
npm install @data-navigator/inspector data-navigator d3-array d3-drag d3-force d3-scale d3-scale-chromatic d3-selection
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
import dataNavigator from 'data-navigator';
|
|
39
|
+
import { Inspector } from '@data-navigator/inspector';
|
|
40
|
+
|
|
41
|
+
const inspector = Inspector({
|
|
42
|
+
structure: myStructure, // made using data navigator
|
|
43
|
+
container: 'inspector-container' // render to DOM
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Sync with navigation events
|
|
47
|
+
inspector.highlight(nodeId);
|
|
48
|
+
inspector.clear();
|
|
49
|
+
inspector.destroy();
|
|
50
|
+
```
|
|
51
|
+
|
|
29
52
|
## Contributing
|
|
30
53
|
|
|
31
54
|
See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup instructions and development workflow.
|
package/package.json
CHANGED
package/src/tree-graph.js
CHANGED
|
@@ -131,17 +131,20 @@ export function TreeGraph(
|
|
|
131
131
|
});
|
|
132
132
|
|
|
133
133
|
// Compute layout positions.
|
|
134
|
+
// Upper levels (dimensions, divisions) are compressed; leaves get more room.
|
|
134
135
|
const padding = { top: 30, bottom: 20, left: 30, right: 30 };
|
|
135
136
|
const usableWidth = width - padding.left - padding.right;
|
|
136
137
|
const usableHeight = height - padding.top - padding.bottom;
|
|
137
138
|
|
|
138
|
-
// Determine rows: level0 (optional), level1, level2, leaves
|
|
139
139
|
const hasLevel0 = level0.length > 0;
|
|
140
|
-
const
|
|
141
|
-
|
|
140
|
+
const upperRows = (hasLevel0 ? 1 : 0) + 1 + 1; // l0?, l1, l2
|
|
141
|
+
// Upper hierarchy gets 40% of height, leaves get 60%
|
|
142
|
+
const upperHeight = usableHeight * 0.4;
|
|
143
|
+
const upperSpacing = upperRows > 1 ? upperHeight / (upperRows - 1) : upperHeight;
|
|
144
|
+
const leafYPos = padding.top + usableHeight * 0.85;
|
|
142
145
|
|
|
143
146
|
let currentRow = 0;
|
|
144
|
-
const yFor = (row) => padding.top + row *
|
|
147
|
+
const yFor = (row) => padding.top + row * upperSpacing;
|
|
145
148
|
|
|
146
149
|
// Level 0
|
|
147
150
|
if (hasLevel0) {
|
|
@@ -192,7 +195,7 @@ export function TreeGraph(
|
|
|
192
195
|
currentRow++;
|
|
193
196
|
|
|
194
197
|
// Leaf nodes
|
|
195
|
-
const leafY =
|
|
198
|
+
const leafY = leafYPos;
|
|
196
199
|
if (dimOrder.length === 0 || !dimensions) {
|
|
197
200
|
// No dimensions — flat row
|
|
198
201
|
leafNodes.forEach((n, i) => {
|
|
@@ -232,7 +235,7 @@ export function TreeGraph(
|
|
|
232
235
|
const rows = div2Ids.length || 1;
|
|
233
236
|
|
|
234
237
|
// Grid occupies the leaf area but may expand vertically
|
|
235
|
-
const gridTop = leafY -
|
|
238
|
+
const gridTop = leafY - (leafY - yFor(currentRow - 1)) * 0.15;
|
|
236
239
|
const gridBottom = height - padding.bottom;
|
|
237
240
|
const gridHeight = gridBottom - gridTop;
|
|
238
241
|
const colSpacing = usableWidth / (cols + 1);
|
|
@@ -270,20 +273,46 @@ export function TreeGraph(
|
|
|
270
273
|
.attr('aria-label', hide ? null : description)
|
|
271
274
|
.attr('style', 'max-width: 100%; height: auto; height: intrinsic;');
|
|
272
275
|
|
|
273
|
-
// Draw sibling links (dashed, behind parent-child links).
|
|
276
|
+
// Draw sibling links as arced paths (dashed, behind parent-child links).
|
|
277
|
+
// Regular siblings arc above (horizontal) or left (vertical).
|
|
278
|
+
// Wrap-around (circular) siblings arc below/right with a larger curve.
|
|
279
|
+
const siblingArc = (d) => {
|
|
280
|
+
const s = nodeObjById[d.source];
|
|
281
|
+
const t = nodeObjById[d.target];
|
|
282
|
+
if (!s || !t) return '';
|
|
283
|
+
const sx = s.x, sy = s.y, tx = t.x, ty = t.y;
|
|
284
|
+
const dx = tx - sx, dy = ty - sy;
|
|
285
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
286
|
+
const isHorizontal = Math.abs(dx) > Math.abs(dy);
|
|
287
|
+
// Detect wrap-around: source is to the right of target (horizontal)
|
|
288
|
+
// or below target (vertical) — these are circular edges.
|
|
289
|
+
const isWrap = isHorizontal ? (sx > tx) : (sy > ty);
|
|
290
|
+
// Arc offset scales with distance but stays subtle
|
|
291
|
+
const arcAmount = Math.min(dist * 0.3, 40);
|
|
292
|
+
const midX = (sx + tx) / 2;
|
|
293
|
+
const midY = (sy + ty) / 2;
|
|
294
|
+
let cx, cy;
|
|
295
|
+
if (isHorizontal) {
|
|
296
|
+
cx = midX;
|
|
297
|
+
cy = isWrap ? midY + arcAmount : midY - arcAmount;
|
|
298
|
+
} else {
|
|
299
|
+
cx = isWrap ? midX + arcAmount : midX - arcAmount;
|
|
300
|
+
cy = midY;
|
|
301
|
+
}
|
|
302
|
+
return `M ${sx} ${sy} Q ${cx} ${cy} ${tx} ${ty}`;
|
|
303
|
+
};
|
|
304
|
+
|
|
274
305
|
svg.append('g')
|
|
275
306
|
.attr('class', 'tree-sibling-links')
|
|
276
|
-
.selectAll('
|
|
307
|
+
.selectAll('path')
|
|
277
308
|
.data(siblingLinks)
|
|
278
|
-
.join('
|
|
279
|
-
.attr('
|
|
280
|
-
.attr('
|
|
281
|
-
.attr('
|
|
282
|
-
.attr('
|
|
283
|
-
.attr('stroke', '#bbb')
|
|
284
|
-
.attr('stroke-opacity', 0.25)
|
|
309
|
+
.join('path')
|
|
310
|
+
.attr('d', siblingArc)
|
|
311
|
+
.attr('fill', 'none')
|
|
312
|
+
.attr('stroke', '#888')
|
|
313
|
+
.attr('stroke-opacity', 0.6)
|
|
285
314
|
.attr('stroke-width', 1)
|
|
286
|
-
.attr('stroke-dasharray', '3
|
|
315
|
+
.attr('stroke-dasharray', '4,3');
|
|
287
316
|
|
|
288
317
|
// Draw parent-child links (solid).
|
|
289
318
|
svg.append('g')
|