feat(ui): implement Map grouping, dependents, and weight bars; symbol tab address
Adds a new grouping system for the Map with a new grouping depth control, exposes per-module dependents (files and modules) to drive a weight bar, and renders it on each module. Introduces a MapKey to explain visuals, collapses lone root-file buckets for clearer labeling, and supports a nullable depth value to let the provider pick grouping. The Symbol tab now has its own address (#/s) when nothing is selected, and routing/top-bar logic is updated accordingly. Also updates export SVG rendering to include weight-based bars, and extends tests and docs to cover the new visuals and behavior.
This commit is contained in:
@@ -139,6 +139,7 @@ function mod(id: string, over: Partial<WireMapModule> = {}): WireMapModule {
|
||||
test: over.test ?? false,
|
||||
facade: over.facade ?? false,
|
||||
fileList: over.fileList ?? { total: 3, shown: 3, truncated: false, items: [] },
|
||||
dependents: over.dependents ?? { files: 0, modules: 0 },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -449,6 +450,37 @@ describe('mapSvg', () => {
|
||||
expect(svg).not.toContain('>__tests__</text>');
|
||||
});
|
||||
|
||||
it('exports the weight bar the canvas draws, scaled the same way', () => {
|
||||
const weighted = buildMapLayout(
|
||||
{
|
||||
modules: [
|
||||
mod('src/types', { dependents: { files: 80, modules: 4 } }),
|
||||
mod('src/db', { dependents: { files: 20, modules: 2 } }),
|
||||
mod('src/bin'),
|
||||
],
|
||||
links: [link('src/db', 'src/types', 30), link('src/bin', 'src/db', 30)],
|
||||
},
|
||||
{ includeTests: false }
|
||||
);
|
||||
const svg = mapSvg(weighted);
|
||||
const nodeOf = (id: string) => weighted.nodes.find((n) => n.id === id)!;
|
||||
// Full bar for the heaviest, a quarter for the module a quarter as leaned
|
||||
// on, and NO rect at all for the one nothing depends on.
|
||||
// The export rounds to a tenth, as every coordinate in this file does.
|
||||
const tenth = (n: number) => Math.round(n * 10) / 10;
|
||||
const full = nodeOf('src/types');
|
||||
const quarter = nodeOf('src/db');
|
||||
expect(quarter.weight).toBeCloseTo(0.25, 5);
|
||||
expect(svg).toContain(`width="${tenth(full.width)}" height="4" fill="${EXPORT_COLORS.ink}"`);
|
||||
expect(svg).toContain(
|
||||
`width="${tenth(quarter.width * 0.25)}" height="4" fill="${EXPORT_COLORS.ink}"`
|
||||
);
|
||||
expect(nodeOf('src/bin').weight).toBe(0);
|
||||
expect(svg.match(/height="4" fill=/g)?.length).toBe(2);
|
||||
// …and the count rides in the meta line, as on screen.
|
||||
expect(svg).toContain('· 80 depend on it</text>');
|
||||
});
|
||||
|
||||
it('names the top and bottom bands', () => {
|
||||
const svg = mapSvg(layout);
|
||||
expect(svg).toContain('>entry points</text>');
|
||||
|
||||
Reference in New Issue
Block a user