From 8c4278ea634cdd808dc1c7561a717461c29d4d51 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 25 Aug 2026 15:50:59 -0400 Subject: [PATCH 1/9] Fix chart freeze on empty explicit series, and stranded tooltip on pointer leave MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `ChartState` gated implicit-series generation on `explicit && explicit.length > 0`, so an explicitly-provided but empty `series` array fell through to deriving series from registered marks — while the charts render their marks from the series. That cycle has no fixed point and spins the main thread, so a chart whose series emptied out while mounted (during a refetch, say) would lock the page rather than render as empty. A non-empty array cut the cycle via the early return; `[]` didn't. The test asserts at the `ChartState` level rather than by rendering, deliberately — a rendering test would hang CI instead of failing. `Tooltip` never re-armed the hide when `pointerEvents` is enabled: `TooltipContext` is the only thing that schedules one, and its timer had already fired and been blocked while the pointer was over the tooltip. Leaving it anywhere other than back over the hit area stranded it on screen. Co-Authored-By: Claude Opus 5 --- .changeset/chart-empty-explicit-series.md | 5 +++ .changeset/tooltip-pointer-events-hide.md | 5 +++ .../src/lib/components/tooltip/Tooltip.svelte | 6 +++- .../components/tooltip/Tooltip.svelte.test.ts | 35 +++++++++++++++++++ .../src/lib/states/chart.svelte.test.ts | 25 +++++++++++++ .../layerchart/src/lib/states/chart.svelte.ts | 5 ++- 6 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 .changeset/chart-empty-explicit-series.md create mode 100644 .changeset/tooltip-pointer-events-hide.md diff --git a/.changeset/chart-empty-explicit-series.md b/.changeset/chart-empty-explicit-series.md new file mode 100644 index 000000000..3d4868ebf --- /dev/null +++ b/.changeset/chart-empty-explicit-series.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +fix(Chart): Treat an explicit but empty `series` array as authoritative, rather than deriving implicit series from the marks it just rendered (the two never settled, locking the page) diff --git a/.changeset/tooltip-pointer-events-hide.md b/.changeset/tooltip-pointer-events-hide.md new file mode 100644 index 000000000..379a7d579 --- /dev/null +++ b/.changeset/tooltip-pointer-events-hide.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +fix(Tooltip): Hide after the pointer leaves the tooltip when `pointerEvents` is enabled (hovering it suppressed the pending hide, and leaving never re-armed it) diff --git a/packages/layerchart/src/lib/components/tooltip/Tooltip.svelte b/packages/layerchart/src/lib/components/tooltip/Tooltip.svelte index 06754e029..b5c27412d 100644 --- a/packages/layerchart/src/lib/components/tooltip/Tooltip.svelte +++ b/packages/layerchart/src/lib/components/tooltip/Tooltip.svelte @@ -538,8 +538,12 @@ onpointerenter={() => { ctx.tooltip.isHoveringTooltipContent = true; }} - onpointerleave={() => { + onpointerleave={(e) => { ctx.tooltip.isHoveringTooltipContent = false; + // `TooltipContext` is the only thing that schedules a hide, and its timer has already fired + // and been blocked by the flag above while the pointer was in here. Without re-arming it, + // leaving the tooltip anywhere other than back over the hit area strands it on screen. + ctx.tooltip.hide(e); }} >
{ ); }); }); + + describe('pointerEvents', () => { + /** + * With `pointerEvents` enabled the tooltip can be hovered, which sets + * `isHoveringTooltipContent` and makes the hide timer `TooltipContext` already scheduled a + * no-op. Nothing else re-arms that timer, so leaving the tooltip anywhere other than back + * over the hit area used to strand it on screen indefinitely. + */ + it('should hide after the pointer leaves an interactive tooltip', async () => { + const { container } = render(LineChart, { + props: { + ...baseProps, + props: { tooltip: { root: { pointerEvents: true } } }, + }, + }); + + const tooltipCtx = container.querySelector('.lc-tooltip-context') as HTMLElement; + await expect.element(tooltipCtx).toBeInTheDocument(); + await waitForTooltip(tooltipCtx, undefined, () => { + expect(getTooltipRoot()).not.toBeNull(); + }); + + const tooltipRoot = getTooltipRoot()!; + + // Move off the plot and onto the tooltip, which blocks the pending hide + tooltipCtx.dispatchEvent(new PointerEvent('pointerleave', { bubbles: true })); + tooltipRoot.dispatchEvent(new PointerEvent('pointerenter', { bubbles: true })); + await new Promise((resolve) => setTimeout(resolve, 50)); + expect(getTooltipRoot(), 'should stay visible while hovered').not.toBeNull(); + + // Leaving the tooltip has to re-arm it + tooltipRoot.dispatchEvent(new PointerEvent('pointerleave', { bubbles: true })); + await vi.waitFor(() => expect(getTooltipRoot()).toBeNull()); + }); + }); }); diff --git a/packages/layerchart/src/lib/states/chart.svelte.test.ts b/packages/layerchart/src/lib/states/chart.svelte.test.ts index 3592f4312..4a95512cc 100644 --- a/packages/layerchart/src/lib/states/chart.svelte.test.ts +++ b/packages/layerchart/src/lib/states/chart.svelte.test.ts @@ -378,6 +378,31 @@ describe('ChartState mark registration', () => { } }); + it('should treat an empty explicit series array as authoritative', () => { + // Charts render their marks from the series, so deriving the series back from those marks + // leaves the two oscillating with no fixed point — a chart whose data emptied out mid-flight + // (a refetch, say) would hang the tab rather than render as empty. + const data: MultiSeriesData[] = [{ date: '2024-01', apples: 10, bananas: 15 }]; + + const { state, cleanup } = createChartState({ + seriesLayout: 'overlap', + data, + x: 'date', + series: [], + }); + + try { + // Marks left over from the previous, non-empty series + state.registerMark({ y: 'apples', color: 'red' }); + state.registerMark({ y: 'bananas', color: 'yellow' }); + flushSync(); + + expect(state.seriesState.series).toHaveLength(0); + } finally { + cleanup(); + } + }); + it('should deduplicate implicit series with the same key', () => { const { state, cleanup } = createChartState({ data: [{ date: '2024-01', value: 10 }], diff --git a/packages/layerchart/src/lib/states/chart.svelte.ts b/packages/layerchart/src/lib/states/chart.svelte.ts index a9801a625..06e7fabc3 100644 --- a/packages/layerchart/src/lib/states/chart.svelte.ts +++ b/packages/layerchart/src/lib/states/chart.svelte.ts @@ -402,7 +402,10 @@ export class ChartState< this.seriesState = new SeriesState( () => { const explicit = this.props.series; - if (explicit && explicit.length > 0) return explicit; + // An explicitly-provided array is authoritative even when empty. Falling through to the + // implicit path on `[]` deadlocks: implicit series are derived from registered marks, but + // charts render their marks from the series, so the two oscillate and never settle. + if (explicit) return explicit; // Generate implicit series from registered marks. // Use the value axis accessor (y for horizontal charts, x for vertical). From ca502aa9536d701e17f9d7e2bd534466f8198f16 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 25 Aug 2026 15:51:09 -0400 Subject: [PATCH 2/9] Fail visual-regression runs loudly when the docs server is broken MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The readiness probe hit `/`, which a dev server answers before it can render an example, and `capture` recorded "nothing drawn" for every page without saying why. A broken server therefore produced a snapshot of ~1000 errored entries — worse than producing nothing, since `compare` has no baseline to diff an errored entry against and every one of them turns into a silent pass from then on. - probe a real example route, then smoke-test one capture before spending the ~40 minutes a full run takes - record the console error, page error, or HTTP status behind a failure, so a failure on a runner is diagnosable from the job log alone - treat "rendered on a later pass" as a flake rather than a failure - refuse to write a snapshot where more than 5% of examples failed, and report a baseline that far gone as unusable rather than as a check that passed Co-Authored-By: Claude Opus 5 --- .github/workflows/update-visual-baseline.yml | 8 +- .github/workflows/visual-regression.yml | 9 ++- docs/scripts/visual-snapshot.mjs | 80 +++++++++++++++++--- 3 files changed, 86 insertions(+), 11 deletions(-) diff --git a/.github/workflows/update-visual-baseline.yml b/.github/workflows/update-visual-baseline.yml index 5ff8dcdc1..a62bca30d 100644 --- a/.github/workflows/update-visual-baseline.yml +++ b/.github/workflows/update-visual-baseline.yml @@ -49,11 +49,17 @@ jobs: run: | pnpm --filter docs exec vite dev --port 3002 > /tmp/server.log 2>&1 & for i in $(seq 1 60); do - curl -sf -o /dev/null http://localhost:3002/ && exit 0 + curl -sf -o /dev/null "http://localhost:3002/docs/screenshot/AnnotationLine/horizontal" && exit 0 sleep 2 done echo "docs server did not start"; cat /tmp/server.log; exit 1 + # A full capture takes ~40 minutes, so prove the app renders at all before spending them. + # `capture` exits non-zero once more than a few examples draw nothing. + - name: Smoke test the docs server + working-directory: docs + run: node scripts/visual-snapshot.mjs capture /tmp/smoke.json --filter AnnotationLine --repeat 1 + # Two passes so examples that are still nondeterministic are recorded as such and skipped # by later comparisons rather than reported as regressions - name: Capture baseline diff --git a/.github/workflows/visual-regression.yml b/.github/workflows/visual-regression.yml index a862cfbbb..ebc38b85e 100644 --- a/.github/workflows/visual-regression.yml +++ b/.github/workflows/visual-regression.yml @@ -57,11 +57,18 @@ jobs: run: | pnpm --filter docs exec vite dev --port 3002 > /tmp/visual/server.log 2>&1 & for i in $(seq 1 60); do - curl -sf -o /dev/null http://localhost:3002/ && exit 0 + curl -sf -o /dev/null "http://localhost:3002/docs/screenshot/AnnotationLine/horizontal" && exit 0 sleep 2 done echo "docs server did not start"; cat /tmp/visual/server.log; exit 1 + # Fails in seconds if the app is not rendering, so a broken docs server reads as a broken + # job rather than as 978 examples that "have no baseline" and silently pass + - name: Smoke test the docs server + if: steps.baseline.outputs.found == 'true' + working-directory: docs + run: node scripts/visual-snapshot.mjs capture /tmp/visual/smoke.json --filter AnnotationLine --repeat 1 + - name: Capture this branch if: steps.baseline.outputs.found == 'true' working-directory: docs diff --git a/docs/scripts/visual-snapshot.mjs b/docs/scripts/visual-snapshot.mjs index 4ce200e21..156dcfd23 100644 --- a/docs/scripts/visual-snapshot.mjs +++ b/docs/scripts/visual-snapshot.mjs @@ -23,6 +23,9 @@ import { dirname, join } from 'node:path'; const CATALOG_DIR = 'src/examples/catalog'; const DEFAULT_URL = 'http://localhost:3002'; +// Above this share of examples failing, the run says more about the environment than the charts +const MAX_FAILURE_RATE = 0.05; + // Fixed so a chart built from `new Date()` lands on the same dates every run const FROZEN_NOW = Date.UTC(2026, 0, 15, 12, 0, 0); @@ -163,8 +166,28 @@ function listExamples(filter) { async function captureOne(page, baseUrl, item, attempt = 0) { const { component, example } = item; const url = `${baseUrl}/docs/screenshot/${component}/${example}`; + // A dev server 500, a module that failed to load and a chart that genuinely draws nothing are + // indistinguishable from the outside — all three end up as an empty page. Record what the + // browser reported so a failure on a runner can be diagnosed from the job log alone. + const problems = []; + const onConsole = (msg) => { + if (msg.type() === 'error') + problems.push(`console: ${msg.text().split('\n')[0].slice(0, 200)}`); + }; + const onPageError = (err) => { + problems.push( + `pageerror: ${String(err?.message ?? err) + .split('\n')[0] + .slice(0, 200)}` + ); + }; + page.on('console', onConsole); + page.on('pageerror', onPageError); + const why = (reason) => (problems.length ? `${reason} — ${problems[0]}` : reason); try { - await page.goto(url, { waitUntil: 'networkidle', timeout: 30000 }); + const response = await page.goto(url, { waitUntil: 'networkidle', timeout: 30000 }); + const status = response?.status() ?? 0; + if (status >= 400) problems.unshift(`http ${status}`); // Marks tween in; wait for the drawing to stop changing rather than guessing a delay let previous = null; for (let i = 0; i < (attempt ? 40 : 12); i++) { @@ -180,7 +203,7 @@ async function captureOne(page, baseUrl, item, attempt = 0) { } // An example fetching its data can outlast the settle window; give it one slower go if (attempt === 0) return captureOne(page, baseUrl, item, 1); - return { error: 'nothing drawn' }; + return { error: why('nothing drawn') }; } catch (e) { // A dev server under load aborts navigations — that says nothing about the chart if (attempt < 2) { @@ -188,10 +211,15 @@ async function captureOne(page, baseUrl, item, attempt = 0) { return captureOne(page, baseUrl, item, attempt + 1); } return { - error: String(e.message ?? e) - .split('\n')[0] - .slice(0, 120) + error: why( + String(e.message ?? e) + .split('\n')[0] + .slice(0, 120) + ) }; + } finally { + page.off('console', onConsole); + page.off('pageerror', onPageError); } } @@ -224,7 +252,11 @@ async function capture(outPath, { url, filter, concurrency, repeat, seed }) { const existing = results.get(key); if (pass === 0) { results.set(key, result); - } else if (existing && existing.hash !== result.hash) { + } else if (existing?.error && !result.error) { + // Rendering on a later pass means the first pass hit a flake, not a broken + // example — keep the drawing rather than recording the failure + results.set(key, result); + } else if (existing && !existing.error && existing.hash !== result.hash) { results.set(key, { ...existing, unstable: true }); } if (++done % 100 === 0) console.log(` pass ${pass + 1}: ${done}/${examples.length}`); @@ -238,13 +270,32 @@ async function capture(outPath, { url, filter, concurrency, repeat, seed }) { const entries = Object.fromEntries([...results].sort(([a], [b]) => a.localeCompare(b))); const unstable = Object.values(entries).filter((r) => r.unstable).length; const failed = Object.values(entries).filter((r) => r.error).length; + const seconds = Math.round((Date.now() - started) / 1000); + if (failed) { + console.log(`\n${failed} of ${Object.keys(entries).length} examples failed to render`); + for (const [key, r] of Object.entries(entries) + .filter(([, r]) => r.error) + .slice(0, 10)) { + console.log(` ${key} — ${r.error}`); + } + } + + // A run where most examples drew nothing says the docs server was broken, not that the charts + // changed. Recording it would be worse than recording nothing: `compare` has no baseline to + // diff an errored entry against, so every one of them would turn into a silent pass from then + // on. Bail before writing so a run this broken cannot be picked up as a baseline. + if (failed > Object.keys(entries).length * MAX_FAILURE_RATE) { + throw new Error( + `${failed}/${Object.keys(entries).length} examples failed to render — refusing to write a snapshot this broken. ` + + `Check that the docs server is serving /docs/screenshot//.` + ); + } + mkdirSync(dirname(outPath), { recursive: true }); writeFileSync(outPath, JSON.stringify({ seed, examples: entries }, null, 2) + '\n'); - const seconds = Math.round((Date.now() - started) / 1000); console.log(`\nwrote ${outPath} — ${Object.keys(entries).length} examples in ${seconds}s`); if (unstable) console.log(` ${unstable} unstable (excluded from comparison)`); - if (failed) console.log(` ${failed} failed to render`); } /** Screenshot one example from a running server. */ @@ -364,7 +415,18 @@ function compare(baselinePath, currentPath) { console.log( `\n${changed.length} changed, ${broke.length} broken, ${added.length} added, ${removed.length} removed, ${incomparable.length} without a baseline, ${skipped.length} skipped as unstable` ); - return { keys: [...changed, ...broke].map((line) => line.split(/\s+/)[0]), differences: broke.length + changed.length }; // prettier-ignore + + // Entries the baseline failed to capture are unreviewable, not unchanged. A handful is the + // cost of a flaky example; a large share means the baseline itself needs re-recording, and + // staying quiet about it would report a check that never actually ran as a pass. + const unusable = incomparable.length > Object.keys(baseline).length * MAX_FAILURE_RATE; + if (unusable) { + console.log( + `\n${incomparable.length} of ${Object.keys(baseline).length} baseline entries are errors — the baseline is unusable. ` + + `Re-record it with the Update Visual Baseline workflow.` + ); + } + return { keys: [...changed, ...broke].map((line) => line.split(/\s+/)[0]), differences: broke.length + changed.length + (unusable ? 1 : 0) }; // prettier-ignore } /** Re-render one example against two servers and print the drawing attributes that differ. */ From 3bbfef26439d1eb2e266ed5d6e52bb1cf1204a4f Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 25 Aug 2026 15:51:23 -0400 Subject: [PATCH 3/9] Document reading the facet panel on click, and pass `facet` to the `marks` snippet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The facets guide covered reading the panel while rendering but not while handling a click, which is the question that actually comes up. Adds a `Clicks` section with the three routes and two examples: - from a row — `context.facet.x?.(data)`, which survives `fx` being a function - from the panel — `facet` off the snippet, for a click on a panel's background, an annotation, or a panel with nothing in it - from a pixel — `context.facet.panelAt`, also added to the `context.facet` table `onTooltipClick` is what the first example uses, because the tooltip modes that draw hit targets (`bounds`, `band`, `facet`, `voronoi`) put them above the marks — a mark's own `onclick` and `Bars`' `onBarClick` never see the click there. `marks` is typed as receiving `{ context, facet }`, but `BarChart`, `LineChart`, `AreaChart` and `ScatterChart` each destructured only `context` and forwarded only `context`, leaving `facet` undefined on exactly the charts most people reach for while `aboveMarks` / `belowMarks` worked. No changeset — faceting is unreleased. Co-Authored-By: Claude Opus 5 --- docs/src/content/guides/facets.md | 59 +++++++++++++++ docs/src/examples/catalog/BarChart.json | 9 ++- docs/src/examples/catalog/Chart.json | 43 ++++++++++- docs/src/examples/catalog/Circle.json | 9 ++- docs/src/examples/catalog/Frame.json | 9 ++- .../components/Chart/facet-click-panel.svelte | 53 ++++++++++++++ .../components/Chart/facet-click.svelte | 68 ++++++++++++++++++ .../facet-stack-long-data-dark-240w.webp | Bin 0 -> 5932 bytes .../facet-stack-long-data-dark-400w.webp | Bin 0 -> 8958 bytes .../facet-stack-long-data-dark-800w.webp | Bin 0 -> 9920 bytes .../facet-stack-long-data-light-240w.webp | Bin 0 -> 5622 bytes .../facet-stack-long-data-light-400w.webp | Bin 0 -> 8702 bytes .../facet-stack-long-data-light-800w.webp | Bin 0 -> 9624 bytes .../Chart/facet-click-dark-240w.webp | Bin 0 -> 7680 bytes .../Chart/facet-click-dark-400w.webp | Bin 0 -> 11526 bytes .../Chart/facet-click-dark-800w.webp | Bin 0 -> 13996 bytes .../Chart/facet-click-light-240w.webp | Bin 0 -> 7020 bytes .../Chart/facet-click-light-400w.webp | Bin 0 -> 11150 bytes .../Chart/facet-click-light-800w.webp | Bin 0 -> 13648 bytes .../Chart/facet-click-panel-dark-240w.webp | Bin 0 -> 7244 bytes .../Chart/facet-click-panel-dark-400w.webp | Bin 0 -> 13660 bytes .../Chart/facet-click-panel-dark-800w.webp | Bin 0 -> 18816 bytes .../Chart/facet-click-panel-light-240w.webp | Bin 0 -> 6810 bytes .../Chart/facet-click-panel-light-400w.webp | Bin 0 -> 12518 bytes .../Chart/facet-click-panel-light-800w.webp | Bin 0 -> 18260 bytes docs/static/screenshots/index.json | 16 ++++- .../charts/AreaChart/AreaChart.base.svelte | 4 +- .../charts/BarChart/BarChart.base.svelte | 4 +- .../charts/LineChart/LineChart.base.svelte | 4 +- .../ScatterChart/ScatterChart.base.svelte | 4 +- 30 files changed, 267 insertions(+), 15 deletions(-) create mode 100644 docs/src/examples/components/Chart/facet-click-panel.svelte create mode 100644 docs/src/examples/components/Chart/facet-click.svelte create mode 100644 docs/static/screenshots/BarChart/facet-stack-long-data-dark-240w.webp create mode 100644 docs/static/screenshots/BarChart/facet-stack-long-data-dark-400w.webp create mode 100644 docs/static/screenshots/BarChart/facet-stack-long-data-dark-800w.webp create mode 100644 docs/static/screenshots/BarChart/facet-stack-long-data-light-240w.webp create mode 100644 docs/static/screenshots/BarChart/facet-stack-long-data-light-400w.webp create mode 100644 docs/static/screenshots/BarChart/facet-stack-long-data-light-800w.webp create mode 100644 docs/static/screenshots/Chart/facet-click-dark-240w.webp create mode 100644 docs/static/screenshots/Chart/facet-click-dark-400w.webp create mode 100644 docs/static/screenshots/Chart/facet-click-dark-800w.webp create mode 100644 docs/static/screenshots/Chart/facet-click-light-240w.webp create mode 100644 docs/static/screenshots/Chart/facet-click-light-400w.webp create mode 100644 docs/static/screenshots/Chart/facet-click-light-800w.webp create mode 100644 docs/static/screenshots/Chart/facet-click-panel-dark-240w.webp create mode 100644 docs/static/screenshots/Chart/facet-click-panel-dark-400w.webp create mode 100644 docs/static/screenshots/Chart/facet-click-panel-dark-800w.webp create mode 100644 docs/static/screenshots/Chart/facet-click-panel-light-240w.webp create mode 100644 docs/static/screenshots/Chart/facet-click-panel-light-400w.webp create mode 100644 docs/static/screenshots/Chart/facet-click-panel-light-800w.webp diff --git a/docs/src/content/guides/facets.md b/docs/src/content/guides/facets.md index b8d4f466d..ff20efe00 100644 --- a/docs/src/content/guides/facets.md +++ b/docs/src/content/guides/facets.md @@ -264,6 +264,64 @@ To build the rows yourself — a single tooltip listing every panel, say — `pa A faceted chart resolves tooltips against the rows the panels were partitioned from — the chart's `data`. Marks given their own `data` aren't part of that partition, so their points are not found by the pointer. :: +## Clicks + +The panel is a property of the row, so a click that resolves to one already carries it. Read it back with the chart's own `fx` / `fy` accessors rather than the key you passed, and it keeps working when `fx` is a function: + +```svelte + { + const party = context.facet.x?.(data); + }} +/> +``` + +:example{ component="Chart" name="facet-click" } + +`onTooltipClick` is what a chart with a tooltip wants. The modes that draw hit targets — `bounds`, `band`, `facet` and `voronoi` — put them above the marks, so a mark's own `onclick` (and `Bars`' `onBarClick`) never sees the click. A hand-composed chart passes the same handler as `tooltipContext={{ onclick }}`. + +The `bisect-*` and `quadtree*` modes draw nothing over the marks, so there the mark keeps its click — and the panel comes from the snippet it's drawn in: + +```svelte +{#snippet marks({ facet })} + select(facet.fx)} /> +{/snippet} +``` + +### Clicking the panel itself + +A click on something that _isn't_ a row — the panel's background, an annotation, a panel with nothing in it — has no row to read from, so take the panel from the snippet. A `Frame` fills the panel it's rendered in, which makes it the target: + +```svelte +{#snippet belowMarks({ facet })} + (selected = facet.fx)} + /> +{/snippet} +``` + +:example{ component="Chart" name="facet-click-panel" } + +Below the marks rather than above, so the rows stay clickable in their own right. A crossed grid keys on the pair — `[facet.fx, facet.fy]` — and `facet.empty` says whether the panel holds anything. + +### From a pixel + +Where the click is neither a row nor inside a panel's snippet — a handler on the container, a drop target — `panelAt` resolves plot-area coordinates to the panel covering them, and gives `undefined` in the gap between panels: + +```svelte +onclick={(e) => { + const rect = e.currentTarget.getBoundingClientRect(); + const panel = context.facet.panelAt( + e.clientX - rect.left - context.padding.left, + e.clientY - rect.top - context.padding.top + ); +}} +``` + ## Brushing A brush gesture belongs to the panel it starts in, so the range it produces is read from that panel's coordinates. What it produces is a range of the _shared_ scales, though — so the selection applies to every panel, and is drawn in each of them. @@ -379,6 +437,7 @@ The layout itself lives on the chart state as `context.facet`: | `context.facet.panels` | Every panel, with offsets, rows, and edge flags | | `context.facet.xScale` / `yScale` | Band scales laying the panels out | | `context.facet.width` / `height` | One panel's dimensions | +| `context.facet.panelAt(x, y)` | The panel covering a plot-area point | `context.width` / `height` are that same panel box — `context.box` stays the whole plot area. diff --git a/docs/src/examples/catalog/BarChart.json b/docs/src/examples/catalog/BarChart.json index ed287437e..d9691e492 100644 --- a/docs/src/examples/catalog/BarChart.json +++ b/docs/src/examples/catalog/BarChart.json @@ -2452,6 +2452,13 @@ "lineNumber": 84, "line": "" } ], - "updatedAt": "2026-08-20T12:48:38.692Z" + "updatedAt": "2026-08-23T18:52:25.346Z" } \ No newline at end of file diff --git a/docs/src/examples/catalog/Frame.json b/docs/src/examples/catalog/Frame.json index 5c2b6b94e..e93faef78 100644 --- a/docs/src/examples/catalog/Frame.json +++ b/docs/src/examples/catalog/Frame.json @@ -123,6 +123,13 @@ "lineNumber": 39, "line": "" }, + { + "example": "facet-click-panel", + "component": "Chart", + "path": "/docs/components/Chart/facet-click-panel", + "lineNumber": 36, + "line": "" } ], - "updatedAt": "2026-08-19T14:28:18.858Z" + "updatedAt": "2026-08-23T18:52:25.602Z" } \ No newline at end of file diff --git a/docs/src/examples/components/Chart/facet-click-panel.svelte b/docs/src/examples/components/Chart/facet-click-panel.svelte new file mode 100644 index 000000000..4fccb97d9 --- /dev/null +++ b/docs/src/examples/components/Chart/facet-click-panel.svelte @@ -0,0 +1,53 @@ + + + + +
+ {#if selected} + Selected {selected} — {data.filter((d) => d.species === selected).length} penguins + {:else} + Click a panel + {/if} +
+ + + + {#snippet belowMarks({ facet })} + (selected = selected === facet.fx ? null : facet.fx)} + /> + {/snippet} + + {#snippet marks({ facet })} + + {/snippet} + diff --git a/docs/src/examples/components/Chart/facet-click.svelte b/docs/src/examples/components/Chart/facet-click.svelte new file mode 100644 index 000000000..f77a308b8 --- /dev/null +++ b/docs/src/examples/components/Chart/facet-click.svelte @@ -0,0 +1,68 @@ + + +
+ {#if selected} + Clicked {selected.party} in {selected.row.year} — {(selected.row.percent * 100).toFixed( + 1 + )}% + {:else} + Click a bar + {/if} +
+ + { + // The panel is a property of the row, so the chart's own `fx` accessor reads it back out — + // which also works when `fx` is a function rather than a key + selected = { party: context.facet.x?.(data), row: data }; + }} + facet={{ + axis: { + placement: 'bottom', + tickLabelProps: { dy: 24, class: 'text-xs font-semibold fill-surface-content' } + } + }} + props={{ + xAxis: { format: 'none' }, + yAxis: { format: 'percentRound' }, + tooltip: { + header: { format: 'none' }, + item: { format: { type: 'percent', options: { fractionDigits: 1 } } }, + hideTotal: true + } + }} + padding={{ left: 44, bottom: 40, top: 8, right: 8 }} + height={300} +/> diff --git a/docs/static/screenshots/BarChart/facet-stack-long-data-dark-240w.webp b/docs/static/screenshots/BarChart/facet-stack-long-data-dark-240w.webp new file mode 100644 index 0000000000000000000000000000000000000000..c54b335fd20f8d429fb5aae8cdebbcbaafb4c079 GIT binary patch literal 5932 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 YluJW55~+-t*EsGK7qG!^6Sx2X0B93p%K!iX literal 0 HcmV?d00001 diff --git a/docs/static/screenshots/BarChart/facet-stack-long-data-dark-800w.webp b/docs/static/screenshots/BarChart/facet-stack-long-data-dark-800w.webp new file mode 100644 index 0000000000000000000000000000000000000000..8d20bf197efedd6eb186b97dacd140a22e400d16 GIT binary patch literal 9920 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 literal 0 HcmV?d00001 diff --git a/docs/static/screenshots/BarChart/facet-stack-long-data-light-400w.webp b/docs/static/screenshots/BarChart/facet-stack-long-data-light-400w.webp new file mode 100644 index 0000000000000000000000000000000000000000..360fc1eb3861d9964e0d8b532d3c2c395129db52 GIT binary patch literal 8702 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 literal 0 HcmV?d00001 diff --git a/docs/static/screenshots/BarChart/facet-stack-long-data-light-800w.webp b/docs/static/screenshots/BarChart/facet-stack-long-data-light-800w.webp new file mode 100644 index 0000000000000000000000000000000000000000..5bf5905ee97fc07c5c8d727887479a7277edd3fb GIT binary patch literal 9624 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 literal 0 HcmV?d00001 diff --git a/docs/static/screenshots/Chart/facet-click-dark-400w.webp b/docs/static/screenshots/Chart/facet-click-dark-400w.webp new file mode 100644 index 0000000000000000000000000000000000000000..1dffc3461f7bc545425e5029dc07e26ad1e2acd6 GIT binary patch literal 11526 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 literal 0 HcmV?d00001 diff --git a/docs/static/screenshots/Chart/facet-click-dark-800w.webp b/docs/static/screenshots/Chart/facet-click-dark-800w.webp new file mode 100644 index 0000000000000000000000000000000000000000..782d241c052799e9d90f9cfb5a2878cd03089bf6 GIT binary patch literal 13996 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 i0GzKh-&+x#nPc#%&x5i-YdjDITt literal 0 HcmV?d00001 diff --git a/docs/static/screenshots/Chart/facet-click-light-240w.webp b/docs/static/screenshots/Chart/facet-click-light-240w.webp new file mode 100644 index 0000000000000000000000000000000000000000..1e22d75cf376e4fcc621803a05381a499943c504 GIT binary patch literal 7020 zcmV-y8dyQWdVli8;kBFeIVHN z2g;j9_s}qk(=R+aPResiOyFX)34QRb5@3jzrU;$F?}}7m+zur{8b>@hQWWPrMi`m_ z66JOb#jy~i+jEM2AufPFl+F`FTIWJDb5{_V5tL0l-bDw*YOWHoBdu*_j<7-BJufJUg zx7Ycxme`jFe|O&Ks89v%6Di37;P>53jG`JppHUJCb+o+t1hOlmHwo>p$(X4)L@&*(m;o}@S*87S94;cE9>Z{c(Jr0=s>ke} zeJi#N#l>coLg}AM(nYCXGWl4ia3IJ4*<(dzmo)>G39cNDrbDDoekei&RsP9&MdX<} z;?6cvTk)s+rJcreJ_C>dVgDaj7#fZ_)qjAHqjcKCk%>h{=l}tDLTKTn0~j4m8_bJt zwsBimf>N6;ov>tt#!NsfKnlN>t8|uOyA4KW=-BiO;z?==Qp!m*dG=3xe82F(dXP?O z1npkv#E@_T*uEDtIZKxexX&q)8KO%75bjycg5`Bx1%4*)K>i7{VH z1Sko`D3*oU(eeJzSA=j6^TpD#ob4w97+g@F>uoQSOkm@We-k<@KPKMz}V@Q zEL>qFuGm0WebuW+a?-oqy*}517>#P!4u`1K!$9WksXco8c6sN?P&604JC~QvMmClG z;|Mu>lS5Z8&cRr6r{g5RV)U)mx$C1@(ZiVidF2*=+^Q+(J|G=@16qJoRo#^ZWlUnU zJ`G?6kkfYN+6{JP%f3*2<_mxy#==R*n zhm*~P{ISktfZ}}_ohCwil{vQWJMw-U5d;R9Gw312FB~-@0afwrqf%u|oPKl*WdK?P zkFxT8(+<_-6faZ;JcM-Zz6d(n;)vhtj6EuB>58>CjsBY7M!ZFx(H}DB^*Pk*paeix z%oQJ}JK_QEw#nofvrHq8q5$@X^unZBo3y<5M0iX3Ol83^yGBsivH7eYW2D zZQq-k5;ey_5=i05H*Lw@t-%1fTa3v^1E!!$7mmTcT3@)BI9&|@r__+XIDpcj0~p^< z-6Qy^-Q;939f$;JD*#%!Ou>fNtgWO6w4H8$&>+}`2Z!ycfju>(W8`u(^40(^4Gi1+ zwA*eCioNNyi_TlA2hxJ?BCxxOv=hweK-RBzmNl|JC_$RsQ3!dF z=4FxUwu|Eipvr$bIfs?AW-u3ud?yZtNdV!%1#Lz0W*6IFS6^4fGK23Pw>18TQ%EwP zim9=3{A>PJB3w1*k4(MUu>-yG-Tb|+o>aa?8bTkw@kPFdftUVgJy1@*$(=8(=7_e)u5l5F3!T(Lu_cU^FQ*dBF>^rQfP)^fY2zr zv(YoyBa-9%swlf6m2_o@be7z(ASeC*A9&Xo>tbqJy9YZaCA4!g2LY^|6y%z$7_ORh z3OXhig=8-}Mj9GC=+e}{{^&@hpkwk&r&G|eaML-VwmEZE&Cs+S8po9oE*b{I^rCQ4 zGT=#P*bKmMQz%b5$`BngM<+5v2e$^(Vi3rK73@9np0RS{iSyr^BmkBCUT6fP(vTYo zro^|ggbpScYM-zHW1xe$vEC+?_)(728HU_YG9|xp)9qE}qHC(Nq2fPFMoG*t%nb}C z>&rw!hvE#iN2vj$ztcq*`^7;g1A+BTChLnt(n+^lNW$prB5tm=VMk{=HJByiboM8< zgO2Q-g9aPD-NY?5<8-qL4!Yoa0fzd-vUDg0Qac2sgU314B|9gBOm#s2D_2h7`Eu=5I+?M=Tee2}b|0)MoER z5g3&N<8&5r;Km9|PP)DksRQko z#>VN8aL}1o&U4VoKq|U5m)JT`HZ)F`AQ+b}CaxKE(Af?;hbg@BuMIw#TY?Bc2u~X{ zmv0>yI6Vdsho?qM7i>1V?KSVRc4ArbtpW08@=usKc}Lrm=ZA- zZEvo+z+wkd4Ww9)>ZM=lyo@ZD%2pCVp0Fs&OlC{9w1S@O<5rlCG@z;~gRuUzUY5KwMGxuYGzNXL55& zy7Gn(b{(qvw8o{O;q(35nt!3xbm8W&c5k2fQ9T$SuB`d=fHlpt($G**|M@{u)VAsDe3wT4@bD8svYA>Y4C`$cyLWwPing1 zBf?g2MOBO(6upO+MT2c+D^t_;9vO}WmsPbvKoPAuI^4%YWh?#VCutC^n$nlc<#A({?t{; zt%P(n2zAIYQ*OPc{IH`+evz^^RW?WMNIUs$4=7e$;(eHjB_ z!jU*GYW;QEA65~kPX`3Hw1(cBF}B%?nWOe zz2K0CdgABTH(c?tRB0Gl77oBgg(K-wC%Y~AGk^8T|nr@#ld3zeCLv>iCH zZ-+a#6(urcYv1^ZIj0~0X$6q_9G`aqtK-yOi?0>S1*PXU5;6pW2?83?O zcOMB1H!r3b(r*uqU%uXZYPCHS3iVY$0qNs?^+y@6shs#ONclM(S8wxqV|jmMgE<>D zAw$OKpN>BP%ixcbG59<2n;|Thntj2|{RiTBAHbMD2`k=VAelr2zO*vpuL5HE48Wh# z)>kkTkE0!f$dmyjwIdkNzF%6BG$k{!$`t?;D}O@W1d4qs1uP-8_J19Yz?51k09H^q zAf^uh08m2!odGKF09*h*Z7`EZBqE|AC(`WjfDMUiZLZLE2FNAEN&|p1SSKar}Vn@Z!G*^V9aeI^4PbgYJ9hxBE|0o?xG;et7<_zp8(}^%MHt`!nwC{#Vpr zpa<&bT3_xjum|$L?p~MQwBHCn*FWI?-1|m<^6LQMgZ~-Zcli&=j=;|?`xDBIr5XJG zcfWs(`8(Z<(!bRD0ebuN-}l}i8in`+pnvv0C7(h6hwKOZYx=+Xukas`A0$8S|C#gM z^(X#+^4|de%fGDu-1XJLn%96JYff_WLUQMyX+PgU&4t%$ zML)ogKb%)G`tJ2ZxqK6why8*|dypYEfi8AYkmPIdeNMAW#@yx@d9m@I+~6rTNF=}T zQD>4ROV7ShfB1pa>aq)iD2-o}_&$0Zdc&>QW0Ow5TUhfIPaeUP)-9CJ1;p@ zvBcU^{a=hynT<}UeK5kX>-#WCTWt_)a?!FgVWlj90RDrS#9_$SD1dtGw3(USK(GCB zngF;y#oy)Q8z6NWrK6k!7v_#vy%|_BRqDLk>}YK~x|M=J+St07oMIEgFhSt%kRY+b*EjkK ziwmr#s-24Moy6<(rTQPUxs~;q|974-4z{l+p<~F*X`ZU7Qv>eKyd0FXNq>=mu!U(j88s2f%oKr z>DSNhR~tP*Q1oK{zkUuIigHeWHdHe%@)a%)EI^gS`9lM~Sb=Wc$v-;wA-W?ks-I|A zY%Y!vJ=bvtgEvB06O^y741;n6kGcJh*a=kvZp;@%j|6?#;ai*|qS&d_v7QeDRyOuS zk6TRK6gtk5INO=yEvC7zydy|M1?bx2=kX3uNPvje{s5~KdL7}tOnkCQ^o?r!M@0Il z6Hxh(lef*2*9;(O&)zSf_MOw8yi&JnpuTXmfC^k?D#6iopnxc2^T{ci+{|0w!tg&Z z?@au-xT!O7!Eb>2Zg*8IAc2VenRoJdsoQ127HT~fqZFOic^~fClQP}(zA*U2^csNc zc(%Y#4_XYez&Q{a$kK$e#Fl>*T*NVPjmSdvL$sHBHg zEn~;~QMkb=;vuKiLi~sCEhs>sGNC?UYkIFom1(Lm!E=4`ts(|=@SGFGa4piz#mrZ( zd_3_$-q)(ID^1igpb3N%)gg0tS)0AFJ-&J2Af_Q*WLBV9+_E|JPZJppdcC7Rmc9;+ z{>t1N2Evxr7|WNf<~VI5UCxKgL}dgV8EzQm5~Uyd+Q0u|J``82eT?-t%jzyTW_*xJ z5zIlm)Z6Furr3$B16IDD{aDbB3HHzv`G2@g0&*Yf!8G-q0*f(Q^SJzSQ;$$5l!Z=v zFtqFd>u0b$Z@1QGC#POn@vFNJtJdF5=y#GaU+O~Fga3&;qnv=kI~AK5vivUb9T}$q znp5xx$;-tr`~+Iz*3cwc*b2<>GCPFt{%^VGokAE;Uy&e+EGL6Vtl7>}krWP-{R zH5B@|i{>(tU3sCGgbft`A1oS^EvC6kws)h(M}U*R*;sZe4Z+$UT;3OY#WL4p6UC0t zP=PN2g4vQ;g-w%1G}fmA&z{)_*1b#*w<_~%{QvSc4Z-)(@^}GzwoNH#`pu9Am1D)R zIn#Br9GV4Bd^AUKKFwMOd7!Rx?7#hJoL1l<{g~-0OP9t~fD8RdQ&se!@j)bVraha1 zHe@rIS10&rT!sU8OpYTEC$EJ@cIwlXx2Cl7BEdFdq#Ib6Mc?siKZoyV@%QVt3}(D; z8Q>ydD0G8|xYiH4)CWCI_Slo9Ilm@hsx8Oe#j72247Em}ER~-P^W-9z$f>Rd)>J3<{|RI z+KQlr?GA3C1;t}fR{#0kvpVL#@X>Wy{LpHSXD1D`3s5j?jD?6Sv=QW&)BUJ-U>j1i zcrIMS{u@}$H8}K)J*mW4jQLyueM1rXAmMS65OTvx#7e zZY9eTCwriLRC7*P6j6h2n}(5xgoU>S=ioBbDej^bsHuhcE>YEa2d6e<-$cO3`<>^6 zaCG4FHsMjt|2Tah!kpX>nhmGFo9B<~HD7jVEpG*@kgXcB!JeiJ)jL!8vTx_bzX$L9 zJ7QA}rWO4QGf=H)}Jq@3tSZl6SxL_UIzzi2U`tG36ElZuG8gVAL6+It;Ror z{j*dw<+%%;C*b>q9P_*r9Y-L#JWAK%vYVnpH`&>ED*R0Y5n|DJGr|e)@7=R2yNUAL3Qlf+4{jqL4Oa;%tSQJjppUX9RV|;jAd1%3qSd z!#YtfTMhLj(BF3L;=e4EV`(JXfX_DZVLt0afF6K~TiPnMn#m)kzimhev|G{}Y!o7B z``3-3pbf=U)(5fRItUQ9dz3DgZDRa6Y2si1%uPPWFAuXdMAWhnXCj#;#LGQ^sGl!76`3KOn&ZX~Kl$@-WNf1+Ja|0~;LLA(sP z{^t<6y1hFH?T4XL%AN1N+II};ho05U+he07NxghHglUg^Gv<3wbx9 zNrc|uG)C}NCNc^^X z1^-jLvHJ-D6;Vnwf zg@eWV_(VSo>!THQc?%hbyiOu-3nzG*gT0GvaW+)NlEZ*?4N<$N<_`_F5~(?A{f5cU zB>v>e>ZI;1(F-8!j zRwj#-5Tv^eH%`8Kv%pkyUfxmlNjz=y&@j*Pq1^*dh!g^VD2lkcNiJh!++oSpbDYPn zrtwjo)#c~+cTX`3pi}xmSVyf@;bL%}+lsxi<$YwI{P9|E^0ig{lHEl2<;cOgl5z{U Kz6sFoYybd&Zp`HX literal 0 HcmV?d00001 diff --git a/docs/static/screenshots/Chart/facet-click-light-400w.webp b/docs/static/screenshots/Chart/facet-click-light-400w.webp new file mode 100644 index 0000000000000000000000000000000000000000..c1d1724cdc991036bb724b140270f32ef7e2c41a GIT binary patch literal 11150 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 aX_;1#%Bj>Nvdyf>GL2-{^E3uppa1~!WJzQI literal 0 HcmV?d00001 diff --git a/docs/static/screenshots/Chart/facet-click-panel-dark-400w.webp b/docs/static/screenshots/Chart/facet-click-panel-dark-400w.webp new file mode 100644 index 0000000000000000000000000000000000000000..d1ad9f67fd9d2ce867643ef4ece6cad48e975b4d GIT binary patch literal 13660 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 literal 0 HcmV?d00001 diff --git a/docs/static/screenshots/Chart/facet-click-panel-dark-800w.webp b/docs/static/screenshots/Chart/facet-click-panel-dark-800w.webp new file mode 100644 index 0000000000000000000000000000000000000000..cc99d8ff6dbe91e758543e9899bed739891f5c17 GIT binary patch literal 18816 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 z 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 literal 0 HcmV?d00001 diff --git a/docs/static/screenshots/Chart/facet-click-panel-light-800w.webp b/docs/static/screenshots/Chart/facet-click-panel-light-800w.webp new file mode 100644 index 0000000000000000000000000000000000000000..0b3d4035bddabe1f11310e28e9a8dbd70c3bf91c GIT binary patch literal 18260 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 CxfM46 literal 0 HcmV?d00001 diff --git a/docs/static/screenshots/index.json b/docs/static/screenshots/index.json index bef659554..86ba6d9de 100644 --- a/docs/static/screenshots/index.json +++ b/docs/static/screenshots/index.json @@ -1,7 +1,7 @@ { - "generatedAt": "2026-08-20T18:45:21.306Z", + "generatedAt": "2026-08-23T18:54:59.937Z", "totalComponents": 80, - "totalExamples": 980, + "totalExamples": 982, "components": [ { "component": "AnnotationLine", @@ -1054,7 +1054,7 @@ { "name": "facet-stack-long-data", "path": "/example/BarChart/facet-stack-long-data", - "checksum": "" + "checksum": "6af9ab637814cf5cf397efac8eed50a1" }, { "name": "gradient", @@ -2156,6 +2156,16 @@ "path": "/example/Chart/facet-brush-zoom", "checksum": "2e16a5ad96c47b72e01f8f1ac61c53c6" }, + { + "name": "facet-click", + "path": "/example/Chart/facet-click", + "checksum": "ea6c3e1b40e02112839d1cb5212d308f" + }, + { + "name": "facet-click-panel", + "path": "/example/Chart/facet-click-panel", + "checksum": "f7cd534e38cef18bc42bddd749ee5584" + }, { "name": "facet-color", "path": "/example/Chart/facet-color", diff --git a/packages/layerchart/src/lib/components/charts/AreaChart/AreaChart.base.svelte b/packages/layerchart/src/lib/components/charts/AreaChart/AreaChart.base.svelte index 0a2543733..2bf2cd66f 100644 --- a/packages/layerchart/src/lib/components/charts/AreaChart/AreaChart.base.svelte +++ b/packages/layerchart/src/lib/components/charts/AreaChart/AreaChart.base.svelte @@ -101,9 +101,9 @@ }, }} > - {#snippet marks({ context }: { context: any })} + {#snippet marks({ context, facet }: { context: any; facet: any })} {#if typeof marks === 'function'} - {@render marks({ context })} + {@render marks({ context, facet })} {:else} {#each context.series.visibleSeries as s (s.key)} - {#snippet marks({ context }: { context: any })} + {#snippet marks({ context, facet }: { context: any; facet: any })} {#if typeof marks === 'function'} - {@render marks({ context })} + {@render marks({ context, facet })} {:else} {#each context.series.visibleSeries as s, i (s.key)} - {#snippet marks({ context }: { context: any })} + {#snippet marks({ context, facet }: { context: any; facet: any })} {#if typeof marks === 'function'} - {@render marks({ context })} + {@render marks({ context, facet })} {:else} {#each context.series.visibleSeries as s, i (s.key)} diff --git a/packages/layerchart/src/lib/components/charts/ScatterChart/ScatterChart.base.svelte b/packages/layerchart/src/lib/components/charts/ScatterChart/ScatterChart.base.svelte index 049c44487..cdd1af106 100644 --- a/packages/layerchart/src/lib/components/charts/ScatterChart/ScatterChart.base.svelte +++ b/packages/layerchart/src/lib/components/charts/ScatterChart/ScatterChart.base.svelte @@ -85,9 +85,9 @@ tooltip={tooltipProp} {props} > - {#snippet marks({ context }: { context: any })} + {#snippet marks({ context, facet }: { context: any; facet: any })} {#if typeof marks === 'function'} - {@render marks({ context })} + {@render marks({ context, facet })} {:else} {#each context.series.visibleSeries as s, i (s.key)} From 4c4d76b49d1d95c64b8a50e7f11eff507f50ef79 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 25 Aug 2026 16:15:30 -0400 Subject: [PATCH 4/9] Generate the docs server's StackBlitz inputs before the visual-regression runs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `docs/static/stackblitz-files.json` is generated and gitignored, so a fresh checkout has none. Every example route imports it transitively — `Example` pulls in `stackblitz.remote`, which imports the JSON — so the docs server 500s on all of them. `prebuild` generates it for a real build, but these workflows run a bare `vite dev`. Previously invisible: the readiness probe hit `/`, which doesn't reach that import, so the server looked healthy and every capture recorded "nothing drawn". The probe now hits an example route and fails here instead. Takes ~0.6s. Co-Authored-By: Claude Opus 5 --- .github/workflows/update-visual-baseline.yml | 6 ++++++ .github/workflows/visual-regression.yml | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/.github/workflows/update-visual-baseline.yml b/.github/workflows/update-visual-baseline.yml index a62bca30d..11a6e9d0d 100644 --- a/.github/workflows/update-visual-baseline.yml +++ b/.github/workflows/update-visual-baseline.yml @@ -45,6 +45,12 @@ jobs: - name: Build packages run: pnpm build:packages + # `stackblitz-files.json` is generated and gitignored, so a fresh checkout has none — and + # every example route imports it transitively, through `Example`'s "open in StackBlitz". + # `prebuild` covers this for a real build; a bare `vite dev` doesn't. + - name: Generate the docs server's inputs + run: pnpm --filter docs generate:stackblitz + - name: Start the docs server run: | pnpm --filter docs exec vite dev --port 3002 > /tmp/server.log 2>&1 & diff --git a/.github/workflows/visual-regression.yml b/.github/workflows/visual-regression.yml index ebc38b85e..dfa0ac4e6 100644 --- a/.github/workflows/visual-regression.yml +++ b/.github/workflows/visual-regression.yml @@ -52,6 +52,13 @@ jobs: echo "No baseline on ${{ github.base_ref }} — run the Update Visual Baseline workflow." >> "$GITHUB_STEP_SUMMARY" fi + # `stackblitz-files.json` is generated and gitignored, so a fresh checkout has none — and + # every example route imports it transitively, through `Example`'s "open in StackBlitz". + # `prebuild` covers this for a real build; a bare `vite dev` doesn't. + - name: Generate the docs server's inputs + if: steps.baseline.outputs.found == 'true' + run: pnpm --filter docs generate:stackblitz + - name: Start the docs server if: steps.baseline.outputs.found == 'true' run: | From 886c0e9f3de47ecbf57c066b0e8690fa5e0e5a8a Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 25 Aug 2026 16:33:45 -0400 Subject: [PATCH 5/9] Center data-anchored tooltips on the interval, not its leading edge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `dataCoords` centered on a band scale but not on the band-like width `xInterval` / `yInterval` give a time scale, so `x="data"` / `y="data"` landed on the leading edge of the bar rather than on the bar — off by half an interval. `Rect` already draws the bar across `[scale(floor(v)), scale(offset(floor(v)))]` and `Axis` already centers its ticks the same way; this brings the tooltip in line with both. Centers on the interval the value falls in rather than on the value, so data that isn't already on an interval boundary lands where its bar is. Band scales, multi-value accessors (`x={['start', 'end']}`) and plain scales are untouched — the new branch is reached only when an interval is set. Measured against `Tooltip/multiple-tooltips-with-fixed-single-axis-scaleband`, the one docs example that combines an interval with a data-anchored tooltip: both tooltips now center at 516.0 against a bar center of 515.9, previously 500.0. Co-Authored-By: Claude Opus 5 --- .changeset/tooltip-interval-data-position.md | 5 ++ .../layerchart/src/lib/utils/tooltip.test.ts | 75 ++++++++++++++++++- packages/layerchart/src/lib/utils/tooltip.ts | 38 +++++++++- 3 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 .changeset/tooltip-interval-data-position.md diff --git a/.changeset/tooltip-interval-data-position.md b/.changeset/tooltip-interval-data-position.md new file mode 100644 index 000000000..6e15040f9 --- /dev/null +++ b/.changeset/tooltip-interval-data-position.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +fix(Tooltip): Center `x="data"` / `y="data"` on the interval a value falls in when the chart sets `xInterval` / `yInterval`, matching where the bar is drawn instead of sitting on its leading edge diff --git a/packages/layerchart/src/lib/utils/tooltip.test.ts b/packages/layerchart/src/lib/utils/tooltip.test.ts index cdb4a44ac..457bedb9c 100644 --- a/packages/layerchart/src/lib/utils/tooltip.test.ts +++ b/packages/layerchart/src/lib/utils/tooltip.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from 'vitest'; -import { scaleBand, scaleLinear } from 'd3-scale'; +import { scaleBand, scaleLinear, scaleUtc } from 'd3-scale'; +import { utcDay } from 'd3-time'; import { bisectData, dataCoords, findDatumByValue, pickNearest } from './tooltip.js'; @@ -184,4 +185,76 @@ describe('dataCoords', () => { expect(dataCoords(coordCtx, {})).toEqual({ x: 150, y: 50 }); }); + + describe('with an interval', () => { + // Ten days across 300px, so a day is 30px wide and its center sits 15px in + const timeScale = scaleUtc() + .domain([new Date('2024-01-01'), new Date('2024-01-11')]) + .range([0, 300]); + + it('positions to the center of the interval rather than its leading edge', () => { + const coordCtx = { + xGet: (d: any) => timeScale(d.date), + yGet: (d: any) => yScale(d.y), + x: (d: any) => d.date, + y: (d: any) => d.y, + xScale: timeScale, + yScale, + xInterval: utcDay, + padding: { top: 0, right: 0, bottom: 0, left: 0 }, + } as any; + + expect(dataCoords(coordCtx, { date: new Date('2024-01-01'), y: 0 }).x).toBe(15); + expect(dataCoords(coordCtx, { date: new Date('2024-01-03'), y: 0 }).x).toBe(75); + }); + + it('centers on the interval a value falls in, not on the value', () => { + const coordCtx = { + xGet: (d: any) => timeScale(d.date), + yGet: () => 0, + x: (d: any) => d.date, + y: () => 0, + xScale: timeScale, + yScale, + xInterval: utcDay, + padding: { top: 0, right: 0, bottom: 0, left: 0 }, + } as any; + + // Midday on the 1st still belongs to the 1st, so it lands where the boundary does + expect(dataCoords(coordCtx, { date: new Date('2024-01-01T12:00:00Z') }).x).toBe(15); + }); + + it('applies to the y axis too, as a horizontal chart uses it', () => { + const yTimeScale = scaleUtc() + .domain([new Date('2024-01-01'), new Date('2024-01-11')]) + .range([0, 200]); + const coordCtx = { + xGet: () => 0, + yGet: (d: any) => yTimeScale(d.date), + x: () => 0, + y: (d: any) => d.date, + xScale, + yScale: yTimeScale, + yInterval: utcDay, + padding: { top: 0, right: 0, bottom: 0, left: 0 }, + } as any; + + expect(dataCoords(coordCtx, { date: new Date('2024-01-01') }).y).toBe(10); + }); + + it('leaves a multi-value accessor alone, which already spans the mark', () => { + const coordCtx = { + xGet: () => [100, 200], + yGet: () => 0, + x: (d: any) => d.date, + y: () => 0, + xScale: timeScale, + yScale, + xInterval: utcDay, + padding: { top: 0, right: 0, bottom: 0, left: 0 }, + } as any; + + expect(dataCoords(coordCtx, { date: new Date('2024-01-01') }).x).toBe(150); + }); + }); }); diff --git a/packages/layerchart/src/lib/utils/tooltip.ts b/packages/layerchart/src/lib/utils/tooltip.ts index 60eaf6d37..1f686f8f9 100644 --- a/packages/layerchart/src/lib/utils/tooltip.ts +++ b/packages/layerchart/src/lib/utils/tooltip.ts @@ -1,4 +1,5 @@ import { bisector } from 'd3-array'; +import type { TimeInterval } from 'd3-time'; import { sortFunc } from '@layerstack/utils'; import { isEqualValue } from './common.js'; @@ -33,6 +34,12 @@ export type TooltipCoordContext = { xScale: AnyScale; yScale: AnyScale; padding: { top: number; right: number; bottom: number; left: number }; + /** Domain accessors, needed to find the interval a value falls in */ + x?: (d: any) => any; + y?: (d: any) => any; + /** Interval giving a non-band scale a band-like width, as `xInterval` / `yInterval` do */ + xInterval?: TimeInterval | null; + yInterval?: TimeInterval | null; /** Present on a real `ChartState`; used to offset into the panel a row belongs to */ facet?: { enabled: boolean; panels: Array<{ x: number; y: number; has(row: any): boolean }> }; }; @@ -167,6 +174,33 @@ function coordCenter(value: any) { return Array.isArray(value) ? (value[0] + value[value.length - 1]) / 2 : value; } +/** + * Center of the span a data point occupies along one axis, in that axis' pixel space. + * + * Three ways a value can occupy a span rather than a point, in the order they take precedence: + * a band scale, a multi-value accessor (ex. `x={['start', 'end']}`), and an interval — which gives + * a time scale a band-like width, the same span `Rect` draws a bar across. All three place the + * value at the leading edge, so a tooltip anchored to the raw coordinate sits off to one side. + */ +function axisCenter( + scale: AnyScale, + interval: TimeInterval | null | undefined, + scaled: any, + value: any +) { + if (isScaleBand(scale)) return coordCenter(scaled) + bandCenterOffset(scale); + if (Array.isArray(scaled)) return coordCenter(scaled); + + if (interval && value != null) { + const start = interval.floor(value); + // The midpoint of the interval the value falls in, rather than of the value itself — the two + // differ for data that isn't already on an interval boundary + return (scale(start) + scale(interval.offset(start))) / 2; + } + + return coordCenter(scaled); +} + /** * Container-relative pixel coordinates of a data point, derived from the chart's own scales. * @@ -179,8 +213,8 @@ export function dataCoords(ctx: TooltipCoordContext, data: any) { const panel = ctx.facet?.enabled ? ctx.facet.panels.find((p) => p.has(data)) : undefined; return { - x: coordCenter(ctx.xGet(data)) + ctx.padding.left + bandCenterOffset(ctx.xScale) + (panel?.x ?? 0), // prettier-ignore - y: coordCenter(ctx.yGet(data)) + ctx.padding.top + bandCenterOffset(ctx.yScale) + (panel?.y ?? 0), // prettier-ignore + x: axisCenter(ctx.xScale, ctx.xInterval, ctx.xGet(data), ctx.x?.(data)) + ctx.padding.left + (panel?.x ?? 0), // prettier-ignore + y: axisCenter(ctx.yScale, ctx.yInterval, ctx.yGet(data), ctx.y?.(data)) + ctx.padding.top + (panel?.y ?? 0), // prettier-ignore }; } From c0424c98c3749c7997dfdf93d4eba6f2e4c86cd3 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 25 Aug 2026 16:51:44 -0400 Subject: [PATCH 6/9] Fix crash highlighting `c`-grouped points over nested chart data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hovering a chart whose `data` is nested — a `stack()`, one array per key, with the rows it was built from passed as `flatData` — threw `TypeError: Cannot read properties of undefined`, taking the whole chart down. `Tooltip/stacked-area` is the docs example; the `` around examples is the only reason it read as an error card rather than a blank page. Two problems in the `c`-grouped point path, both from 0a87ff06d: - it iterated `ctx.data`, so a nested chart handed the position accessors a series where they expect a row. `flatData` is what the tooltip resolves against and what the accessors are written for, so the two now agree by construction. - it scaled a category's value as a scalar, so `y={[0, 1]}` — a stack's bands — became `NaN` and the browser dropped the point with a console error. A span has no single position, so those fall through to the series path, which already points each of the values. Regression tests render the shape and hover it, with no boundary to swallow the throw; both fail on the code before this change, and the second still fails with only the `flatData` half applied. Co-Authored-By: Claude Opus 5 --- .changeset/highlight-nested-data-c-points.md | 5 ++ .../Highlight/Highlight.shared.svelte.ts | 49 +++++++------ .../Highlight/Highlight.svelte.test.ts | 69 +++++++++++++++++++ .../__fixtures__/StackedCategoryChart.svelte | 39 +++++++++++ 4 files changed, 142 insertions(+), 20 deletions(-) create mode 100644 .changeset/highlight-nested-data-c-points.md create mode 100644 packages/layerchart/src/lib/components/Highlight/Highlight.svelte.test.ts create mode 100644 packages/layerchart/src/lib/components/Highlight/__fixtures__/StackedCategoryChart.svelte diff --git a/.changeset/highlight-nested-data-c-points.md b/.changeset/highlight-nested-data-c-points.md new file mode 100644 index 000000000..e726c0bca --- /dev/null +++ b/.changeset/highlight-nested-data-c-points.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +fix(Highlight): Resolve `c`-grouped points against the chart's rows rather than its `data`, so a chart whose data is nested (a `stack()` passing its rows as `flatData`) no longer hands the position accessors a series, and a category whose value is a span (`y={[0, 1]}`) is pointed by the series path instead of being scaled to `NaN` diff --git a/packages/layerchart/src/lib/components/Highlight/Highlight.shared.svelte.ts b/packages/layerchart/src/lib/components/Highlight/Highlight.shared.svelte.ts index 2b2efc72c..4b5f5ab45 100644 --- a/packages/layerchart/src/lib/components/Highlight/Highlight.shared.svelte.ts +++ b/packages/layerchart/src/lib/components/Highlight/Highlight.shared.svelte.ts @@ -404,30 +404,39 @@ export class HighlightState { if (props.data === undefined && this.ctx.cGroups && this.ctx.series.isDefaultSeries) { const value = this.ctx.valueAxis === 'y' ? this.ctx.y : this.ctx.x; // Within a facet, only that panel's rows — the same category appears in every panel, and - // pointing all of them would put the other panels' values in this one - const source = this.#facetPanel?.().data ?? chartDataArray(this.ctx.data); + // pointing all of them would put the other panels' values in this one. Outside one it's + // `flatData`, which is what the tooltip resolves against and what the accessors are written + // for: a chart whose `data` is nested (a `stack()`, say) passes its rows as `flatData`, and + // iterating `data` there would hand the accessors a series rather than a row. + const source = this.#facetPanel?.().data ?? chartDataArray(this.ctx.flatData); const rows = source.filter((d: any) => isEqualValue(this.x(d), this.xValue)); + // A multi-value accessor (`y={[0, 1]}`, as a stack's bands use) gives a category a span + // rather than a position, so there is no single point to put on it. Those belong to the + // series path below, which points each of the values. + const spans = rows.some((row: any) => Array.isArray(value(row))); + // No visibility filter needed — rows of a `c` category the legend has hidden are already // gone from `ctx.data`, which is what keeps the scales in step with the legend - return rows - .map((row: any) => { - const seriesValue = value(row); - return { - x: - this.ctx.valueAxis === 'x' - ? this.ctx.xScale(seriesValue) + this.xOffset - : (this.xCoordScalar as number) + this.xOffset, - y: - this.ctx.valueAxis === 'x' - ? (this.yCoordScalar as number) + this.yOffset - : this.ctx.yScale(seriesValue) + this.yOffset, - fill: this.ctx.config.c ? this.ctx.cGet(row) : null, - data: { x: this.xValue, y: seriesValue }, - seriesKey: this.ctx.cKey(row) ?? undefined, - }; - }) - .filter(notNull) as HighlightPoint[]; + if (!spans) + return rows + .map((row: any) => { + const seriesValue = value(row); + return { + x: + this.ctx.valueAxis === 'x' + ? this.ctx.xScale(seriesValue) + this.xOffset + : (this.xCoordScalar as number) + this.xOffset, + y: + this.ctx.valueAxis === 'x' + ? (this.yCoordScalar as number) + this.yOffset + : this.ctx.yScale(seriesValue) + this.yOffset, + fill: this.ctx.config.c ? this.ctx.cGet(row) : null, + data: { x: this.xValue, y: seriesValue }, + seriesKey: this.ctx.cKey(row) ?? undefined, + }; + }) + .filter(notNull) as HighlightPoint[]; } if (props.data === undefined && this.ctx.tooltip.series.length > 0) { diff --git a/packages/layerchart/src/lib/components/Highlight/Highlight.svelte.test.ts b/packages/layerchart/src/lib/components/Highlight/Highlight.svelte.test.ts new file mode 100644 index 000000000..71bca1416 --- /dev/null +++ b/packages/layerchart/src/lib/components/Highlight/Highlight.svelte.test.ts @@ -0,0 +1,69 @@ +import { describe, expect, it, vi } from 'vitest'; +import { render } from 'vitest-browser-svelte'; + +import StackedCategoryChart from './__fixtures__/StackedCategoryChart.svelte'; + +const keys = ['apples', 'bananas']; +const data = [ + { date: 0, apples: 10, bananas: 20 }, + { date: 1, apples: 30, bananas: 40 }, + { date: 2, apples: 20, bananas: 50 }, +]; + +describe('Highlight points, `c`-grouped', () => { + /** Hover the middle of the plot area and hand back the highlight points drawn there */ + async function hoverForPoints(container: HTMLElement) { + const tooltipRect = container.querySelector('.lc-tooltip-context') as HTMLElement | null; + await expect.element(tooltipRect).toBeInTheDocument(); + + const rect = tooltipRect!.getBoundingClientRect(); + const eventInit = { + bubbles: true, + clientX: rect.x + rect.width / 2, + clientY: rect.y + rect.height / 2, + }; + + let points: Element[] = []; + await vi.waitFor(() => { + tooltipRect!.dispatchEvent(new PointerEvent('pointerenter', eventInit)); + tooltipRect!.dispatchEvent(new PointerEvent('pointermove', eventInit)); + + points = Array.from(document.querySelectorAll('.lc-highlight-point')); + expect(points.length).toBeGreaterThan(0); + }); + return points; + } + + it('resolves against the rows when the chart data is nested', async () => { + // `data` is a `stack()` — an array per key — so iterating it hands the chart's `x` accessor a + // series rather than a row, and the accessor throws on the row fields it isn't given. + // Rendering at all is the assertion: there is no boundary here, so the throw fails the test. + const { container } = render(StackedCategoryChart, { + data, + keys, + height: 300, + width: 400, + } as any); + + const points = await hoverForPoints(container as HTMLElement); + expect(points.length).toBe(keys.length); + }); + + it('places a point on each band rather than at NaN', async () => { + // `y={[0, 1]}` gives a category a span, and scaling the pair as though it were a single value + // puts the point at NaN — which the browser drops on the floor with a console error + const { container } = render(StackedCategoryChart, { + data, + keys, + height: 300, + width: 400, + } as any); + + const points = await hoverForPoints(container as HTMLElement); + for (const point of points) { + expect(Number(point.getAttribute('cx'))).toBeTypeOf('number'); + expect(Number.isFinite(Number(point.getAttribute('cx')))).toBe(true); + expect(Number.isFinite(Number(point.getAttribute('cy')))).toBe(true); + } + }); +}); diff --git a/packages/layerchart/src/lib/components/Highlight/__fixtures__/StackedCategoryChart.svelte b/packages/layerchart/src/lib/components/Highlight/__fixtures__/StackedCategoryChart.svelte new file mode 100644 index 000000000..c125a1398 --- /dev/null +++ b/packages/layerchart/src/lib/components/Highlight/__fixtures__/StackedCategoryChart.svelte @@ -0,0 +1,39 @@ + + + d.data.date} + y={[0, 1]} + c="key" + cDomain={keys} + cRange={['rgb(1, 1, 1)', 'rgb(2, 2, 2)']} + tooltipContext={{ mode: 'quadtree-x' }} + {...props} +> + + {#each series as seriesData (seriesData.key)} + + {/each} + + + From b729f6a0ff17d2d03a6842dee7632e3f27e6c645 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Wed, 26 Aug 2026 14:20:53 -0400 Subject: [PATCH 7/9] Fix Highlight and add colour channel inference from marks --- .changeset/highlight-nested-data-c-points.md | 2 +- .changeset/highlight-single-point-mode.md | 5 + .changeset/implied-color-channel.md | 5 + .changeset/tooltip-interval-data-position.md | 2 +- docs/src/content/guides/styles.md | 4 +- .../components/Chart/facet-tooltip.svelte | 1 - .../Highlight/Highlight.shared.svelte.ts | 30 ++-- .../components/Waffle/Waffle.svelte.test.ts | 28 ++++ .../Waffle/__fixtures__/StackedWaffle.svelte | 34 ++++ .../components/charts/DefaultTooltip.svelte | 11 +- .../charts/LineChart.svelte.test.ts | 58 +++++++ .../src/lib/states/chart.svelte.test.ts | 150 ++++++++++++++++++ .../layerchart/src/lib/states/chart.svelte.ts | 50 +++++- packages/layerchart/src/lib/utils/tooltip.ts | 8 + 14 files changed, 362 insertions(+), 26 deletions(-) create mode 100644 .changeset/highlight-single-point-mode.md create mode 100644 .changeset/implied-color-channel.md create mode 100644 packages/layerchart/src/lib/components/Waffle/Waffle.svelte.test.ts create mode 100644 packages/layerchart/src/lib/components/Waffle/__fixtures__/StackedWaffle.svelte diff --git a/.changeset/highlight-nested-data-c-points.md b/.changeset/highlight-nested-data-c-points.md index e726c0bca..21e636b0f 100644 --- a/.changeset/highlight-nested-data-c-points.md +++ b/.changeset/highlight-nested-data-c-points.md @@ -2,4 +2,4 @@ 'layerchart': patch --- -fix(Highlight): Resolve `c`-grouped points against the chart's rows rather than its `data`, so a chart whose data is nested (a `stack()` passing its rows as `flatData`) no longer hands the position accessors a series, and a category whose value is a span (`y={[0, 1]}`) is pointed by the series path instead of being scaled to `NaN` +fix(Highlight): Point `c`-grouped rows from `flatData`, fixing a crash on nested `stack()` data and `NaN` points where a category's value is a span (`y={[0, 1]}`) diff --git a/.changeset/highlight-single-point-mode.md b/.changeset/highlight-single-point-mode.md new file mode 100644 index 000000000..4c39070b5 --- /dev/null +++ b/.changeset/highlight-single-point-mode.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +fix(Highlight): Mark only the hovered row in `quadtree` / `voronoi` tooltips, rather than every row sharing its position diff --git a/.changeset/implied-color-channel.md b/.changeset/implied-color-channel.md new file mode 100644 index 000000000..c10556fd6 --- /dev/null +++ b/.changeset/implied-color-channel.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +feat(Chart): Take the colour channel from a mark's own `fill` / `stroke` (``) when no `c` is declared, so the colour domain and legend hold the categories rather than the rows — hiding one still needs `c` diff --git a/.changeset/tooltip-interval-data-position.md b/.changeset/tooltip-interval-data-position.md index 6e15040f9..86c222b6b 100644 --- a/.changeset/tooltip-interval-data-position.md +++ b/.changeset/tooltip-interval-data-position.md @@ -2,4 +2,4 @@ 'layerchart': patch --- -fix(Tooltip): Center `x="data"` / `y="data"` on the interval a value falls in when the chart sets `xInterval` / `yInterval`, matching where the bar is drawn instead of sitting on its leading edge +fix(Tooltip): Center `x="data"` / `y="data"` on the interval when `xInterval` / `yInterval` is set, instead of on its leading edge diff --git a/docs/src/content/guides/styles.md b/docs/src/content/guides/styles.md index 747cd64b0..c08552511 100644 --- a/docs/src/content/guides/styles.md +++ b/docs/src/content/guides/styles.md @@ -319,7 +319,7 @@ Many components support data-driven colors via the `c` (color) prop on `Chart`, :::tabs{key="color-enhancements"} ::tab{label="Linear gradient"} - :example{ component="AreaChart" name="gradient" noResize showCode highlight="11-15" } + :example{ component="AreaChart" name="gradient" noResize showCode highlight="10-14" } :: ::tab{label="Radial gradient"} @@ -341,7 +341,7 @@ Many components support data-driven colors via the `c` (color) prop on `Chart`, :: ::tab{label="Pattern"} - :example{ component="AnnotationRange" name="vertical-with-pattern-range" noResize showCode highlight="14-20" } + :example{ component="AnnotationRange" name="vertical-with-pattern-range" noResize showCode highlight="20-25" } :: ::: diff --git a/docs/src/examples/components/Chart/facet-tooltip.svelte b/docs/src/examples/components/Chart/facet-tooltip.svelte index 4a7f96d6b..164d20abb 100644 --- a/docs/src/examples/components/Chart/facet-tooltip.svelte +++ b/docs/src/examples/components/Chart/facet-tooltip.svelte @@ -23,7 +23,6 @@ height={300} > - diff --git a/packages/layerchart/src/lib/components/Highlight/Highlight.shared.svelte.ts b/packages/layerchart/src/lib/components/Highlight/Highlight.shared.svelte.ts index 4b5f5ab45..db2bccc1b 100644 --- a/packages/layerchart/src/lib/components/Highlight/Highlight.shared.svelte.ts +++ b/packages/layerchart/src/lib/components/Highlight/Highlight.shared.svelte.ts @@ -9,7 +9,7 @@ import type Line from '../Line/Line.svelte'; import type Rect from '../Rect/Rect.svelte'; import { accessor, chartDataArray, isEqualValue, type Accessor } from '$lib/utils/common.js'; import { isScaleBand, isScaleTime } from '$lib/utils/scales.svelte.js'; -import { panelDatum } from '$lib/utils/tooltip.js'; +import { isSinglePointMode, panelDatum } from '$lib/utils/tooltip.js'; import { getChartContext } from '$lib/contexts/chart.js'; import { getFacetPanel } from '$lib/contexts/facet.js'; import type { ChartState } from '$lib/states/chart.svelte.js'; @@ -360,7 +360,7 @@ export class HighlightState { * the rule the `facetAll` copies and the series-less path already follow. */ #pointFill(seriesInfo: { color?: string | null }) { - if (this.ctx.config.c && this.ctx.series.isDefaultSeries) { + if (this.ctx.cChannel && this.ctx.series.isDefaultSeries) { return (this.ctx.cGet(this.highlightData) as string) ?? seriesInfo.color ?? ''; } return seriesInfo.color ?? ''; @@ -385,7 +385,7 @@ export class HighlightState { return { x: (this.ctx.xScale(x) as number) + this.xOffset, y: (this.ctx.yScale(y) as number) + this.yOffset, - fill: (this.ctx.config.c ? this.ctx.cGet(match) : null) as string, + fill: (this.ctx.cChannel ? this.ctx.cGet(match) : null) as string, data: { x, y }, seriesKey: undefined, } satisfies HighlightPoint; @@ -401,7 +401,17 @@ export class HighlightState { // series list names only the row the pointer resolved to — one point, on whichever category // happened to be last. Point every category at this position instead, as the tooltip lists // them. - if (props.data === undefined && this.ctx.cGroups && this.ctx.series.isDefaultSeries) { + // + // Only where the pointer resolved to a *position*, though. `quadtree` and `voronoi` resolve + // to one row by proximity in both axes — a scatter, where the rows sharing an x are unrelated + // points rather than a category's line, and pointing all of them marks places nothing was + // hovered. + if ( + props.data === undefined && + this.ctx.cGroups && + this.ctx.series.isDefaultSeries && + !isSinglePointMode(this.ctx.tooltip.mode) + ) { const value = this.ctx.valueAxis === 'y' ? this.ctx.y : this.ctx.x; // Within a facet, only that panel's rows — the same category appears in every panel, and // pointing all of them would put the other panels' values in this one. Outside one it's @@ -431,7 +441,7 @@ export class HighlightState { this.ctx.valueAxis === 'x' ? (this.yCoordScalar as number) + this.yOffset : this.ctx.yScale(seriesValue) + this.yOffset, - fill: this.ctx.config.c ? this.ctx.cGet(row) : null, + fill: this.ctx.cChannel ? this.ctx.cGet(row) : null, data: { x: this.xValue, y: seriesValue }, seriesKey: this.ctx.cKey(row) ?? undefined, }; @@ -535,7 +545,7 @@ export class HighlightState { tmpPoints = seriesPointsData .map((seriesPoint) => { - const fill = this.ctx.config.c ? this.ctx.cGet(seriesPoint.series) : null; + const fill = this.ctx.cChannel ? this.ctx.cGet(seriesPoint.series) : null; return { x: this.ctx.xScale(seriesPoint.point[1]) + this.xOffset, y: (this.yCoordScalar as number) + this.yOffset, @@ -553,7 +563,7 @@ export class HighlightState { // @ts-expect-error - TODO: fix type const _key = this.ctx.config.x?.[i]; - const fill = this.ctx.config.c + const fill = this.ctx.cChannel ? this.ctx.cGet({ ...this.highlightData, $key: _key }) : null; @@ -580,7 +590,7 @@ export class HighlightState { tmpPoints = seriesPointsData .map((seriesPoint) => { - const fill = this.ctx.config.c ? this.ctx.cGet(seriesPoint.series) : null; + const fill = this.ctx.cChannel ? this.ctx.cGet(seriesPoint.series) : null; return { x: (this.xCoord as number) + this.xOffset, y: this.ctx.yScale(seriesPoint.point[1]) + this.yOffset, @@ -598,7 +608,7 @@ export class HighlightState { // @ts-expect-error - TODO: fix type const _key = this.ctx.config.y[i]; - const fill = this.ctx.config.c + const fill = this.ctx.cChannel ? this.ctx.cGet({ ...this.highlightData, $key: _key }) : null; @@ -613,7 +623,7 @@ export class HighlightState { .filter(notNull) as HighlightPoint[]; } } else if (this.xCoord != null && this.yCoord != null) { - const fill = this.ctx.config.c ? this.ctx.cGet(this.highlightData) : null; + const fill = this.ctx.cChannel ? this.ctx.cGet(this.highlightData) : null; tmpPoints = [ { x: (this.xCoord as number) + this.xOffset, diff --git a/packages/layerchart/src/lib/components/Waffle/Waffle.svelte.test.ts b/packages/layerchart/src/lib/components/Waffle/Waffle.svelte.test.ts new file mode 100644 index 000000000..eb5f0e16f --- /dev/null +++ b/packages/layerchart/src/lib/components/Waffle/Waffle.svelte.test.ts @@ -0,0 +1,28 @@ +import { describe, expect, it, vi } from 'vitest'; +import { render } from 'vitest-browser-svelte'; + +import StackedWaffle from './__fixtures__/StackedWaffle.svelte'; + +describe('Waffle mark registration', () => { + const data = [ + { period: 'Q1', apples: 400, bananas: 300 }, + { period: 'Q2', apples: 200, bananas: 500 }, + ]; + const series = [ + { key: 'apples', color: 'red' }, + { key: 'bananas', color: 'yellow' }, + ]; + + it('settles instead of re-registering itself in a loop', async () => { + // `Waffle`'s registered mark info tracks its props, so anything the chart derives from the + // mark registry and then feeds back into the scales would re-register on every pass. A loop + // here blows the update depth rather than failing an assertion, so rendering at all is the test + const { container } = render(StackedWaffle, { props: { data, series } } as any); + + await vi.waitFor(() => { + expect(container.querySelectorAll('.lc-waffle path, .lc-waffle rect').length).toBeGreaterThan( + 0 + ); + }); + }); +}); diff --git a/packages/layerchart/src/lib/components/Waffle/__fixtures__/StackedWaffle.svelte b/packages/layerchart/src/lib/components/Waffle/__fixtures__/StackedWaffle.svelte new file mode 100644 index 000000000..6ee525f1b --- /dev/null +++ b/packages/layerchart/src/lib/components/Waffle/__fixtures__/StackedWaffle.svelte @@ -0,0 +1,34 @@ + + + + {#snippet marks({ context }: any)} + {#each context.series.visibleSeries as s (s.key)} + + {/each} + {/snippet} + diff --git a/packages/layerchart/src/lib/components/charts/DefaultTooltip.svelte b/packages/layerchart/src/lib/components/charts/DefaultTooltip.svelte index 6f0d7bed2..6da13d94c 100644 --- a/packages/layerchart/src/lib/components/charts/DefaultTooltip.svelte +++ b/packages/layerchart/src/lib/components/charts/DefaultTooltip.svelte @@ -7,6 +7,7 @@ import { sum } from 'd3-array'; import { getChartContext } from '$lib/contexts/chart.js'; import { accessor, chartDataArray, isEqualValue } from '$lib/utils/common.js'; + import { isSinglePointMode } from '$lib/utils/tooltip.js'; import Root from '../tooltip/Tooltip.svelte'; import Header from '../tooltip/TooltipHeader.svelte'; import List from '../tooltip/TooltipList.svelte'; @@ -116,7 +117,7 @@ // what the equivalent `series` chart lists. The sub-band otherwise. label: context.cKey(row) ?? subBand(row), value: value(row), - color: context.config.c ? context.cGet(row) : undefined, + color: context.cChannel ? context.cGet(row) : undefined, })); } @@ -150,13 +151,11 @@ // Single-point modes find one specific data point (by proximity in both x+y), // so the tooltip shows dimensional info (x, y, r) for that point. // Multi-series modes find data at a single axis position, showing all series values. - const isSinglePointMode = $derived( - context.tooltip.mode === 'quadtree' || context.tooltip.mode === 'voronoi' - ); + const singlePointMode = $derived(isSinglePointMode(context.tooltip.mode)); // For single-point mode: find the active series for the hovered data point const activeSeries = $derived( - isSinglePointMode + singlePointMode ? (context.tooltip.series.find((s) => s.key === context.tooltip.data?.seriesKey) ?? context.tooltip.series[0]) : null @@ -221,7 +220,7 @@ {#snippet children({ data })} - {#if isSinglePointMode} + {#if singlePointMode} {#if activeSeries && activeSeries.key !== 'default'} { }); }); +describe('legend over a colour a mark implied', () => { + // The same chart as above with no `c` — `stroke="fruit"` on the mark names the column instead. + // Mounting this at all is half the test: the colour channel is derived from the mark registry, + // and marks register as they mount, so a bad edge here would loop rather than settle. + const longData = [ + { date: 0, fruit: 'apples', value: 10 }, + { date: 1, fruit: 'apples', value: 30 }, + { date: 0, fruit: 'bananas', value: 20 }, + { date: 1, fruit: 'bananas', value: 50 }, + ]; + + const impliedProps = { + data: longData, + x: 'date', + y: 'value', + cRange: ['red', 'yellow'], + props: { spline: { stroke: 'fruit' } }, + legend: true, + width: 400, + height: 300, + }; + + const splines = (container: HTMLElement) => + Array.from(container.querySelectorAll('.lc-path')).map((el) => ({ + stroke: el.getAttribute('stroke'), + opacity: (el as SVGElement).style.opacity || el.getAttribute('opacity') || '1', + })); + + it('lists the categories, not the rows', async () => { + const { container } = render(LineChart, { props: impliedProps } as any); + + await vi.waitFor(() => { + const labels = Array.from(container.querySelectorAll('.lc-legend-swatch-label')).map((el) => + el.textContent?.trim() + ); + expect(labels).toEqual(['apples', 'bananas']); + }); + }); + + it('does not filter on click — selection still needs a declared `c`', async () => { + // The swatches come from the colour scale, but hiding a category is `cGroups`' job and that + // stays on the declared prop. Pinned so the gap is deliberate rather than discovered + const { container } = render(LineChart, { props: impliedProps } as any); + + let buttons: NodeListOf = container.querySelectorAll('.lc-legend-swatch-button'); + await vi.waitFor(() => { + buttons = container.querySelectorAll('.lc-legend-swatch-button'); + expect(buttons.length).toBe(2); + }); + await vi.waitFor(() => expect(splines(container).length).toBe(2)); + + (buttons[0] as HTMLElement).click(); + await new Promise((r) => setTimeout(r, 50)); + + expect(splines(container).length).toBe(2); + }); +}); + describe('LineChart highlight over `c` groups', () => { // One implicit series draws every line here, so the tooltip's series list names only the row the // pointer resolved to — a single point, on whichever category happened to be last diff --git a/packages/layerchart/src/lib/states/chart.svelte.test.ts b/packages/layerchart/src/lib/states/chart.svelte.test.ts index 4a95512cc..bcf2c2997 100644 --- a/packages/layerchart/src/lib/states/chart.svelte.test.ts +++ b/packages/layerchart/src/lib/states/chart.svelte.test.ts @@ -2622,3 +2622,153 @@ describe('ChartState explicit null domain', () => { } }); }); + +describe('ChartState implied colour channel', () => { + type Row = { date: string; value: number; island: string }; + const data: Row[] = [ + { date: '2024-01', value: 10, island: 'Torgersen' }, + { date: '2024-02', value: 20, island: 'Biscoe' }, + { date: '2024-03', value: 30, island: 'Dream' }, + ]; + + const cRange = ['red', 'green', 'blue']; + + it('takes the colour column from a mark that named one', () => { + // `` names the column without the chart declaring `c="island"` + const { state, cleanup } = createChartState({ data, x: 'date', y: 'value', cRange }); + try { + state.registerMark({ x: 'date', y: 'value', color: 'island' }); + flushSync(); + + expect(state.cChannel).toBe('island'); + expect(state.cDomain).toEqual(['Torgersen', 'Biscoe', 'Dream']); + expect(state.cGet(data[0])).toBe('red'); + } finally { + cleanup(); + } + }); + + it('leaves the declared `c` alone', () => { + const { state, cleanup } = createChartState({ + data, + x: 'date', + y: 'value', + c: 'date', + cRange, + }); + try { + state.registerMark({ x: 'date', y: 'value', color: 'island' }); + flushSync(); + + // The chart said `c="date"`; a mark can't overrule it + expect(state.cChannel).toBe('date'); + expect(state.cDomain).toEqual(['2024-01', '2024-02', '2024-03']); + } finally { + cleanup(); + } + }); + + it('ignores a CSS colour, which names no column', () => { + const { state, cleanup } = createChartState({ data, x: 'date', y: 'value', cRange }); + try { + state.registerMark({ x: 'date', y: 'value', color: 'var(--color-primary)' }); + state.registerMark({ x: 'date', y: 'value', color: '#ff0000' }); + flushSync(); + + expect(state.cChannel).toBeUndefined(); + } finally { + cleanup(); + } + }); + + it('ignores a string that names nothing in the data', () => { + const { state, cleanup } = createChartState({ data, x: 'date', y: 'value', cRange }); + try { + state.registerMark({ x: 'date', y: 'value', color: 'rebeccapurple' }); + flushSync(); + + expect(state.cChannel).toBeUndefined(); + } finally { + cleanup(); + } + }); + + it('stays out of it when marks name different columns', () => { + // Nothing makes one of them the chart's colour channel, and picking either would be a guess + const { state, cleanup } = createChartState({ data, x: 'date', y: 'value', cRange }); + try { + state.registerMark({ x: 'date', y: 'value', color: 'island' }); + state.registerMark({ x: 'date', y: 'value', color: 'date' }); + flushSync(); + + expect(state.cChannel).toBeUndefined(); + } finally { + cleanup(); + } + }); + + it('colours without grouping — no legend selection, row filtering, or stack splitting', () => { + // `cGroups` drives all three, and `ChartState.data` is built from it. `data` is upstream of + // every scale, so letting it depend on the mark registry closes a loop: a scale change re-runs + // each mark's registration effect, which re-registers, which invalidates `data`. Measured on + // the stacked-waffle shape: drawn in 13s on the declared prop, blank after 254s on the implied + // channel. `Waffle.svelte.test.ts` guards the shape; this pins the boundary. + const { state, cleanup } = createChartState({ data, x: 'date', y: 'value', cRange }); + try { + state.registerMark({ x: 'date', y: 'value', color: 'island' }); + flushSync(); + + expect(state.cChannel).toBe('island'); + expect(state.cGroups).toBeNull(); + expect(state.cKey(data[0])).toBeNull(); + expect(state.data).toEqual(data); + } finally { + cleanup(); + } + }); + + it('groups nothing when a computed accessor gives a colour per row', () => { + // Naming a column says that column holds the category. A mark colouring by a function is a + // colour per row, which would cut one series into a path per colour + const { state, cleanup } = createChartState({ + data, + x: 'date', + y: 'value', + c: (d: Row) => (d.value > 15 ? 'high' : 'low'), + cRange, + }); + try { + flushSync(); + expect(state.cGroups).toBeNull(); + } finally { + cleanup(); + } + }); + + it('keeps a category on the same colour whatever else is in the data', () => { + // Without a channel the domain is the rows themselves, so an ordinal scale meets each category + // as an unknown value and answers with whatever the row count left next in the range — which + // moved every colour when a single row came or went + // Looked up by value, the way a mark's own `fill="island"` resolves it + const colourOf = (rows: Row[], island: string, withMark: boolean) => { + const { state, cleanup } = createChartState({ data: rows, x: 'date', y: 'value', cRange }); // prettier-ignore + try { + if (withMark) state.registerMark({ x: 'date', y: 'value', color: 'island' }); + flushSync(); + return state.cScale?.(island); + } finally { + cleanup(); + } + }; + + const extra = [...data, { date: '2024-04', value: 40, island: 'Biscoe' }]; + + // implied channel: 'Dream' is the third category either way + expect(colourOf(data, 'Dream', true)).toBe('blue'); + expect(colourOf(extra, 'Dream', true)).toBe('blue'); + + // without one, the domain is the rows, so the category is an unknown value the scale answers + // by extending — and one more row moves it to a different colour + expect(colourOf(data, 'Dream', false)).not.toBe(colourOf(extra, 'Dream', false)); + }); +}); diff --git a/packages/layerchart/src/lib/states/chart.svelte.ts b/packages/layerchart/src/lib/states/chart.svelte.ts index 06e7fabc3..626ae8d65 100644 --- a/packages/layerchart/src/lib/states/chart.svelte.ts +++ b/packages/layerchart/src/lib/states/chart.svelte.ts @@ -18,6 +18,7 @@ import { import type { ChartPropsWithoutHTML } from '$lib/components/Chart/Chart.svelte'; import type { Extents } from '$lib/utils/types.js'; import { accessor, chartDataArray, defaultChartPadding, type Accessor } from '$lib/utils/common.js'; +import { colorPropDataKey } from '$lib/utils/dataProp.js'; import { filterObject } from '$lib/utils/filterObject.js'; import { calcDomain, calcScaleExtents, createGetter, createChartScale } from '$lib/utils/chart.js'; import { printDebug } from '$lib/utils/debug.js'; @@ -609,6 +610,42 @@ export class ChartState< return []; }); + /** + * The colour column a mark named in its own `fill` / `stroke` — `` — for a + * chart that declared no `c` of its own. + * + * Only the domain and per-row lookups follow from this. `cGroups` deliberately does not, so an + * implied channel can't start naming a legend, filtering rows, or splitting a stack: those are + * what `ChartState.data` is built from, and `data` is read while marks are still registering. + * A colour never decides *which* marks render, so deriving one from the registry can't change + * the set being registered — the same reason `flatData` can read it. + */ + #impliedC = $derived.by(() => { + if (this.props.c != null) return undefined; + + const first = chartDataArray(this.#sourceData)[0]; + if (first == null) return undefined; + + let key: string | undefined; + for (const { info } of this._markInfos) { + const named = colorPropDataKey(info.color, first); + if (named == null) continue; + // Marks naming different columns leave the chart with no one colour channel, and picking + // either would be a guess — so it keeps what it declared, which is nothing + if (key != null && key !== named) return undefined; + key = named; + } + return key; + }); + + /** + * The colour channel: `c` where the chart declared one, else the column a mark implied. + * + * What to read to ask *whether the chart has colours at all* — `config.c` answers the narrower + * question of whether `c` was passed. + */ + cChannel = $derived(this.props.c ?? this.#impliedC); + /** * The groups `c` names, or `null` when the chart's `series` name them instead. * @@ -619,13 +656,16 @@ export class ChartState< * What a legend lists, what stacks, and what `cKey` reads a row's group from. */ cGroups = $derived.by(() => { + // The declared prop, never `cChannel` — an implied channel must not reach here. `data` is + // built from this and is upstream of every scale, so a dependency on the mark registry closes + // a loop: a scale change re-runs each mark's registration effect, which re-registers, which + // invalidates `data`, which changes the scales. Measured on `Waffle/stacked`: 13s and drawn + // with the prop, 254s and blank with `cChannel`. See `Waffle.svelte.test.ts`. if (this.props.c == null) return null; // Read from the `series` prop rather than `SeriesState.isDefaultSeries`, which also counts - // the series inferred from registered marks. `ChartState.data` depends on this, and marks - // register while deriveds are being read — so reaching into the mark registry from here - // makes registering a mark mutate state something is mid-read of. Series inferred from - // marks name nothing a legend could select anyway. + // the series inferred from registered marks — the same hazard by a different route. Series + // inferred from marks name nothing a legend could select anyway. const configured = this.props.series ?? []; const seriesNameThem = configured.length > 1 || (configured.length === 1 && configured[0].key !== 'default'); @@ -919,7 +959,7 @@ export class ChartState< y = $derived(this.resolveAccessor('y')); z = $derived(makeAccessor(this.props.z)); r = $derived(makeAccessor(this.props.r)); - c = $derived(accessor(this.props.c)); + c = $derived(accessor(this.cChannel)); x1 = $derived(makeAccessor(this.props.x1)); y1 = $derived(makeAccessor(this.props.y1)); diff --git a/packages/layerchart/src/lib/utils/tooltip.ts b/packages/layerchart/src/lib/utils/tooltip.ts index 1f686f8f9..04540657b 100644 --- a/packages/layerchart/src/lib/utils/tooltip.ts +++ b/packages/layerchart/src/lib/utils/tooltip.ts @@ -7,6 +7,14 @@ import { isEqualValue } from './common.js'; import { isScaleBand, type AnyScale } from './scales.svelte.js'; import type { TooltipMode } from '$lib/components/tooltip/TooltipContext.svelte'; +/** + * Whether a mode resolves to one specific row, by proximity in both axes, rather than to every + * series at a position on one — which is what decides whether a hover marks a point or a column. + */ +export function isSinglePointMode(mode: TooltipMode) { + return mode === 'quadtree' || mode === 'voronoi'; +} + /** * Strategy for picking between the two data points surrounding a value. * - `closest` — whichever of the two is nearer the value From 91778f7e9bca833e51d6aa901bfd2d8020611c58 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Wed, 26 Aug 2026 18:28:14 -0400 Subject: [PATCH 8/9] perf(Chart): Defer domain registry and optimize plain-key accessors --- .changeset/accessor-plain-key-fast-path.md | 5 +++++ .changeset/chart-mount-domain-registry.md | 5 +++++ packages/layerchart/src/lib/states/chart.svelte.ts | 8 ++++++-- packages/layerchart/src/lib/utils/common.ts | 7 ++++++- 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 .changeset/accessor-plain-key-fast-path.md create mode 100644 .changeset/chart-mount-domain-registry.md diff --git a/.changeset/accessor-plain-key-fast-path.md b/.changeset/accessor-plain-key-fast-path.md new file mode 100644 index 000000000..79e84065e --- /dev/null +++ b/.changeset/accessor-plain-key-fast-path.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +perf(Chart): Resolve a plain-key accessor (`x="date"`) directly instead of re-parsing the path string on every row diff --git a/.changeset/chart-mount-domain-registry.md b/.changeset/chart-mount-domain-registry.md new file mode 100644 index 000000000..aa03e607a --- /dev/null +++ b/.changeset/chart-mount-domain-registry.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +perf(Chart): Keep the value domain off the mark registry, so mounting a chart no longer rebuilds its scales — and every path drawn from them — once per mark registered diff --git a/packages/layerchart/src/lib/states/chart.svelte.ts b/packages/layerchart/src/lib/states/chart.svelte.ts index 626ae8d65..2c46143c9 100644 --- a/packages/layerchart/src/lib/states/chart.svelte.ts +++ b/packages/layerchart/src/lib/states/chart.svelte.ts @@ -1230,9 +1230,13 @@ export class ChartState< // `Spline`s compared against each other, say) would otherwise be scaled to totals nothing // on it draws. No registered marks at all means the chart hasn't been composed by hand, // so the stack stands. - const marks = this._markInfos; - if (this.isStacked) { + // Read inside the guard. This is the value domain — every scale hangs off it, and every + // mark off those — so subscribing it to the mark registry meant each mark registering + // during mount invalidated the domain, rebuilt the scales, and redrew every path from + // them. Measured on a 5,000-point `LineChart`: 4 path builds per mount instead of 2. + const marks = this._markInfos; + // Collect in a single pass — see `getStackedValues`, which hoists the // `keyBy` accessor and stack derived reads out of the per-row loop. const stacked = this.seriesState.getStackedValues(chartDataArray(this.data)); diff --git a/packages/layerchart/src/lib/utils/common.ts b/packages/layerchart/src/lib/utils/common.ts index b45afebb4..e61398e5a 100644 --- a/packages/layerchart/src/lib/utils/common.ts +++ b/packages/layerchart/src/lib/utils/common.ts @@ -19,7 +19,12 @@ export function accessor(prop: Accessor): (d: TData) => any // function return prop; } else if (typeof prop === 'string' || typeof prop === 'number') { - // path string or number (array index) + // A plain key needs no path resolution, and `get` re-parses the string on every call — which + // is once per row per channel, so a 5,000-point chart parses `"date"` 5,000 times per pass + if (typeof prop === 'number' || (!prop.includes('.') && !prop.includes('['))) { + return (d: TData) => (d == null ? undefined : (d as any)[prop]); + } + // path string (dot / bracket notation) return (d: TData) => get(d, prop); } else { // return full object From 20213d61d6b558cc9e5276bd2caf699bc20abee3 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Wed, 26 Aug 2026 22:37:19 -0400 Subject: [PATCH 9/9] improve colors --- .../examples/components/BrushContext/synced-brushes.svelte | 5 +---- .../src/examples/components/ChartGroup/synced-brushes.svelte | 5 +---- docs/src/lib/components/Example.svelte | 2 +- docs/src/routes/docs/components/[name]/+layout.svelte | 3 +++ 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/docs/src/examples/components/BrushContext/synced-brushes.svelte b/docs/src/examples/components/BrushContext/synced-brushes.svelte index ceb2e2fec..347dcc125 100644 --- a/docs/src/examples/components/BrushContext/synced-brushes.svelte +++ b/docs/src/examples/components/BrushContext/synced-brushes.svelte @@ -66,10 +66,7 @@ - + {#snippet children({ gradient })} {/snippet} diff --git a/docs/src/examples/components/ChartGroup/synced-brushes.svelte b/docs/src/examples/components/ChartGroup/synced-brushes.svelte index 41eb81d6a..3b517dfe1 100644 --- a/docs/src/examples/components/ChartGroup/synced-brushes.svelte +++ b/docs/src/examples/components/ChartGroup/synced-brushes.svelte @@ -61,10 +61,7 @@ - + {#snippet children({ gradient })} {/snippet} diff --git a/docs/src/lib/components/Example.svelte b/docs/src/lib/components/Example.svelte index e2bb2f2fe..aec89ab4e 100644 --- a/docs/src/lib/components/Example.svelte +++ b/docs/src/lib/components/Example.svelte @@ -262,7 +262,7 @@
{#each layers as layer} {toTitleCase(layer)}