Skip to content

Commit 55823fb

Browse files
committed
Merge remote-tracking branch 'origin/feat/graph-explorer-overhead-structure' into fix/simultaneous-incongruences-complexity
2 parents ccad796 + 25ac127 commit 55823fb

14 files changed

Lines changed: 278 additions & 137 deletions

‎docs/website/graph.html‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,13 @@
88
<title>Reduction Paths — Problem Reductions</title>
99
<link rel="icon" href="./assets/favicon.svg" type="image/svg+xml">
1010
<link rel="preload" href="./assets/graph-scene.json.gz" as="fetch" type="application/gzip" crossorigin>
11-
<link rel="preload" href="./assets/path-graph.json.gz" as="fetch" type="application/gzip" crossorigin>
12-
<link rel="preload" href="./assets/path-selection_bg.wasm.gz" as="fetch" type="application/gzip" crossorigin>
11+
<script>
12+
if (location.hash === '#directions') for (const name of ['path-graph.json.gz', 'path-selection_bg.wasm.gz']) {
13+
const link = document.createElement('link');
14+
Object.assign(link, {rel: 'preload', href: './assets/' + name, as: 'fetch', type: 'application/gzip', crossOrigin: ''});
15+
document.head.append(link);
16+
}
17+
</script>
1318
<link rel="preload" href="./assets/fonts/dm-sans-variable.woff2" as="font" type="font/woff2" crossorigin>
1419
<link rel="stylesheet" href="./src/styles/site.css">
1520
<link rel="stylesheet" href="./src/styles/details.css">

‎docs/website/src/lib/force-layout.mts‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,14 @@ export function forceLayout(input: LayoutInput): Map<string, Point> {
8484
return sim.positions();
8585
}
8686
export const settled = (sim: Simulation) => sim.alpha <= ALPHA_MIN && sim.alphaTarget === 0;
87+
88+
// Let input and painting run between short batches; canceled views must not apply stale positions.
89+
export async function settleSimulation(sim: Simulation, signal: AbortSignal): Promise<boolean> {
90+
while (!settled(sim)) {
91+
await new Promise<void>(resolve => setTimeout(resolve, 0));
92+
if (signal.aborted) return false;
93+
const until = performance.now() + 4;
94+
do { sim.tick(); } while (!settled(sim) && performance.now() < until);
95+
}
96+
return !signal.aborted;
97+
}

‎docs/website/src/lib/graph-layout.js‎

Lines changed: 0 additions & 13 deletions
This file was deleted.

‎docs/website/src/pages/graph-startup.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const graphStartup: {scene: Promise<GraphSceneData>; worker: Worker | nul
1313
worker: null,
1414
};
1515
graphStartup.scene.catch(() => {});
16-
try {
16+
if (location.hash === '#directions') try {
1717
const worker = graphStartup.worker = new Worker(new URL('../workers/path-worker.ts', import.meta.url), {type: 'module'});
1818
performance.mark('graph:worker-started');
1919
worker.addEventListener('error', (event) => {

‎docs/website/src/pages/graph.ts‎

Lines changed: 120 additions & 38 deletions
Large diffs are not rendered by default.

‎docs/website/src/pages/hero-graph.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export function mountHeroGraph(container: HTMLElement, graph: HeroGraph) {
6363
const byId = new Map(nodes.map(n => [n.id, n]));
6464
const links: SimLink[] = graph.links.map(([a, b]) => {
6565
const s = byId.get(a)!, t = byId.get(b)!, hub = !!(s.anchor || t.anchor), featured = s.focus && t.focus;
66-
const el = make("line", { class: `network-edge${featured ? " featured-edge" : ""}` });
66+
const el = make("line", { class: "network-edge" });
6767
edgeLayer.append(el);
6868
return { s, t, hub, length: hub ? 80 : featured ? 64 : 24, el };
6969
});

‎docs/website/src/styles/graph.css‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ button { cursor: pointer; background: none; border: 0; padding: 0; }
5858
.scene-edge { stroke: var(--ink); stroke-width: .7; opacity: .09; pointer-events: none; }
5959
.scene-edge.dim { opacity: .025; }
6060
.scene-edge.nbr { stroke: var(--ink-2); opacity: .45; }
61-
.scene-edge.ghost { stroke: var(--accent); stroke-width: 1.5; opacity: .22; }
6261
.scene-edge.route { stroke: var(--accent); stroke-width: 1.8; opacity: 1; marker-end: url(#route-arrow); pointer-events: stroke; cursor: pointer; }
6362
.scene-node { cursor: pointer; }
6463
.node-disc { stroke: var(--bg); stroke-width: 2; }
@@ -67,7 +66,6 @@ button { cursor: pointer; background: none; border: 0; padding: 0; }
6766
paint-order: stroke; stroke-linejoin: round; visibility: hidden; pointer-events: none; }
6867
.scene-node.named .node-label, .scene-node:is(.route,.start,.end,.hover,.focused,.reach) .node-label { visibility: visible; }
6968
.scene-node.dim { opacity: .16; }
70-
.scene-node.ghost { opacity: .75; }
7169
.scene-node:is(.route,.start,.end,.hover,.focused) { opacity: 1; }
7270
.scene-node:is(.route,.start,.end,.hover,.focused,.reach) .node-label { fill: var(--ink); }
7371
.scene-node.route .node-disc { stroke: var(--accent); }
@@ -77,6 +75,8 @@ button { cursor: pointer; background: none; border: 0; padding: 0; }
7775
.scene-node.start .node-halo { fill: var(--start); opacity: .22; }
7876
.scene-node.end .node-halo { fill: var(--end); opacity: .22; }
7977
.scene-node.pulse .node-halo { fill: var(--accent); opacity: .4; r: 20; }
78+
.scene-node:focus { outline: none; }
79+
.scene-node:focus-visible .node-halo { fill: none; stroke: var(--accent); stroke-width: 2; opacity: 1; vector-effect: non-scaling-stroke; }
8080

8181
/* Panel */
8282
.site-header { z-index: 4; }
@@ -125,7 +125,8 @@ button { cursor: pointer; background: none; border: 0; padding: 0; }
125125

126126
.detail { padding: 2px 12px 14px; background: color-mix(in oklab, var(--accent) 8%, transparent); border-radius: 0 0 12px 12px; }
127127
.steps { list-style: none; margin: 0 0 12px; padding: 0; }
128-
.steps li { position: relative; display: grid; grid-template-columns: 18px 1fr auto; gap: 6px; padding: 5px 0; }
128+
.steps li { position: relative; display: grid; grid-template-columns: 18px 1fr auto; gap: 2px 6px; padding: 5px 0; }
129+
.steps li > button:not(.rule-link) { grid-column: 2; }
129130
.steps li::before { content: ""; position: absolute; left: 4px; top: 19px; bottom: -7px; width: 2px; background: rgba(237,242,232,.18); }
130131
.steps li:last-child::before { display: none; }
131132
.steps .dot { margin-top: 6px; width: 9px; height: 9px; border-radius: 50%; border: 1.5px solid var(--ink-3); background: var(--bg); }
@@ -136,7 +137,8 @@ button { cursor: pointer; background: none; border: 0; padding: 0; }
136137
.steps button:hover .name { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--ink-3); }
137138
.kv { display: block; position: relative; font: 12px var(--mono); color: var(--ink); }
138139
.kv i { font-style: normal; color: var(--ink-2); }
139-
.kv + .kv::before { content: "↓ "; position: absolute; left: -14px; color: var(--ink-3); }
140+
.steps .variant-line ~ .variant-line .kv::before { content: "↓ "; position: absolute; left: -14px; color: var(--ink-3); }
141+
.steps .variant-line:hover .kv { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--ink-3); }
140142
.growth-title { margin: 0 0 6px; font-size: 12px; color: var(--ink-3); }
141143
.growth { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; margin: 0 0 12px; font-size: 13px; }
142144
.growth dt { color: var(--ink-2); }
@@ -181,8 +183,8 @@ button { cursor: pointer; background: none; border: 0; padding: 0; }
181183
.pop-details { display: block; width: 100%; margin-top: 6px; padding: 7px 0; color: var(--ink-2); font-size: 13px; }
182184
.pop-details:hover { color: var(--ink); }
183185
.size.pending { width: 34px; height: 21px; background: linear-gradient(90deg, rgba(237,242,232,.04), rgba(237,242,232,.12), rgba(237,242,232,.04)) 0 0 / 200% 100%; animation: shimmer 1.4s linear infinite; }
184-
.steps .rule-link { grid-column: 3; grid-row: 1; align-self: start; padding: 2px 0; background: none; color: var(--ink-3); font: 12px var(--mono); }
185-
.steps .rule-link:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
186+
.steps .rule-link { grid-column: 3; align-self: start; padding: 0; background: none; border-radius: 999px; }
187+
.steps .rule-link:hover .oh { background: color-mix(in oklab, currentColor 26%, transparent); }
186188
#details-drawer { position: fixed; z-index: 5; top: calc(var(--header-height) + 16px); right: 16px; bottom: 16px; width: 440px; display: flex; flex-direction: column; background: var(--panel); border: 1px solid var(--line); border-radius: 18px; box-shadow: 0 24px 60px rgba(0,0,0,.45); backdrop-filter: blur(16px) saturate(1.1); -webkit-backdrop-filter: blur(16px) saturate(1.1); }
187189
.drawer-head { display: flex; justify-content: space-between; gap: 12px; padding: 18px 20px 14px; border-bottom: 1px solid var(--line); }
188190
.drawer-head > div { min-width: 0; }
@@ -248,6 +250,8 @@ button { cursor: pointer; background: none; border: 0; padding: 0; }
248250
.scene-edge.e-higher { stroke: var(--g-higher); stroke-width: 2.3; stroke-dasharray: 6 3; marker-end: url(#arrow-higher); }
249251
.scene-edge.e-unknown { stroke: var(--g-unknown); stroke-dasharray: 2 3; marker-end: url(#arrow-unknown); }
250252
.scene-edge.turing { stroke-dasharray: 9 3 2 3; }
253+
/* A route edge keeps its growth colour but stays heavier than any class width. */
254+
.scene-edge.route { stroke-width: 2.4; }
251255
.explore .scene-node.reach { opacity: 1; }
252256
.scene-node.sel .node-disc { stroke: var(--accent); stroke-width: 3; }
253257
.scene-node.sel .node-halo { fill: var(--accent); opacity: .25; }

‎docs/website/src/styles/site.css‎

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -289,11 +289,6 @@ p {
289289
stroke-width: 0.85;
290290
opacity: 0.47;
291291
}
292-
.network-edge.featured-edge {
293-
stroke: #c2de9b;
294-
stroke-width: 2.4;
295-
opacity: 1;
296-
}
297292
.network-node {
298293
transition: opacity 0.2s;
299294
}
@@ -324,19 +319,11 @@ p {
324319
.network-node.major circle {
325320
fill: #b3d191;
326321
}
327-
.network-node.major text {
328-
font-size: 13px;
329-
fill: var(--diagram-label);
330-
}
331322
.network-node.focus circle {
332323
fill: #d4eab6;
333324
stroke: #446239;
334325
stroke-width: 7;
335326
}
336-
.network-node.focus text {
337-
font-weight: 600;
338-
fill: #d4eab6;
339-
}
340327
.network-node.hub circle {
341328
filter: drop-shadow(0 0 6px rgba(207, 232, 160, 0.45));
342329
}

‎package-lock.json‎

Lines changed: 0 additions & 42 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
"@typescript-eslint/parser": "8.71.2",
1717
"ajv": "8.20.0",
1818
"axe-core": "4.14.0",
19-
"cytoscape": "3.33.1",
20-
"cytoscape-fcose": "2.2.0",
2119
"elkjs": "0.9.3",
2220
"eslint": "10.12.0",
2321
"json-schema-to-typescript": "16.0.0",

0 commit comments

Comments
 (0)