diff --git a/AGENTS.md b/AGENTS.md
index efb686f..023867c 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -148,6 +148,7 @@ Imports point one way only:
- One shared worker keeps tables loaded by key across navigations. Don't `new ArrowProcessingWorkerManager()` per page or `terminate()` the shared instance.
- Avoid blocking the main thread with large Arrow transforms.
- Preserve guards like `isLoading` / `firstLoad` around query execution.
+- A canvas path holds about 150,000 arcs. Above that the browser drops the fill and reports no error, so the plot draws blank. `fillPointChunks` in `plots/uplot-render.ts` flushes the path every 10,000 arcs, and it also draws faster than one large path. Draw every point set through it. A palette bucket needs the same flush: the buckets divide the Z range, not the row count, so one bucket can hold every row.
- `QueryWorkspace.blocks` gets a new array, with new block objects, on every write to the block collection — including `markBlockRun`/`markBlockRunning` and any draft update. Do not read `workspace.activeBlock` (or a query object derived from it) directly inside an `$effect`. That makes the effect re-fire after its own write, in a loop that never stops. Track primitive values instead (block id, a stringified compiled query) and read the live block/query with `untrack`. See `src/routes/visualisations/table-explorer/+page.svelte` for the pattern.
## Editing Guidance for Agents
diff --git a/src/lib/beacon-api/client.ts b/src/lib/beacon-api/client.ts
index 1eec434..e040d70 100644
--- a/src/lib/beacon-api/client.ts
+++ b/src/lib/beacon-api/client.ts
@@ -5,6 +5,7 @@ import { Utils } from '@/utils';
import { addToast } from '@/stores/toasts';
import { BeaconClient as BeaconSdkClient } from '@beacon/client';
import { normalizeUrl, splitNodeUrl } from '@/services/beacon-node-url';
+import { PUBLIC_NODE_TABLES } from '@/services/open-nodes';
import {
isAbortError,
@@ -300,6 +301,13 @@ export class BeaconClient {
async getTables(): Promise> {
const url = this.buildUrl('/api/tables');
const response: Array = await this.fetch(url);
+
+ // Temporary fix: a public demo node shows only its curated tables.
+ const allowedTables = PUBLIC_NODE_TABLES[this.baseUrl];
+ if (allowedTables) {
+ return response.filter((table) => allowedTables.includes(table));
+ }
+
return response;
}
diff --git a/src/lib/components/home/HowItWorks.svelte b/src/lib/components/home/HowItWorks.svelte
index 85cd120..7613eff 100644
--- a/src/lib/components/home/HowItWorks.svelte
+++ b/src/lib/components/home/HowItWorks.svelte
@@ -55,7 +55,7 @@
How it works
-
Three steps from an empty query to a downloaded file
Three real queries. Open one to review the query in the query builder and plot it on the map.
-
+
@@ -68,12 +68,12 @@
Check query
-
+
diff --git a/src/lib/components/palette/PalettePicker.svelte b/src/lib/components/palette/PalettePicker.svelte
index d8f0d8e..c0090d5 100644
--- a/src/lib/components/palette/PalettePicker.svelte
+++ b/src/lib/components/palette/PalettePicker.svelte
@@ -25,6 +25,7 @@
onSelect,
reverse = false,
showSolids = true,
+ showGradients = true,
id = undefined
}: {
/** The id of the palette now in use. */
@@ -33,6 +34,8 @@
/** Preview the palette the way it is drawn, turned around or not. */
reverse?: boolean;
showSolids?: boolean;
+ /** False offers the single colours alone, for a plot that paints no value. */
+ showGradients?: boolean;
/** DOM id of the trigger, so a `
{/if}
- {:else}
- Bind a column to the colour axis in step 2 to pick a palette.
+ {:else}
+ patchStyle({ palette: id })}
+ />
+
+
+ Every point takes this colour. Bind a column to the colour axis in step 2 to paint
+ the points by value.