Twin (grouped) interpolation with synced blocks#59
Merged
Conversation
Reproduce a real-world "twin" lookup format — Speed (rows) x Direction (columns) with a merged Season column (Summer/Winter) grouping the speed rows into two independent, stacked grids that share the Direction axis — and investigate whether Grid-Sight can offer interpolation over it. - public/demo/twin-table/index.html: faithful reproduction fixture (Summer 30-80 kts x 6 rows, Winter 20-60 kts x 4 rows), registered as demo #15 in the shared demo nav. - specs/016-twin-interpolation/investigation.md: feasibility write-up. Confirms (against the live addressing layer) that the current single row-header slider binding fails closed on this shape — both axes bind to null, so no slider is offered rather than a wrong number. Prototyped a group-aware binding that partitions on the rowspan group cell into two rectangular sub-grids and feeds the existing bilinear() unchanged; proves twin interpolation is a small, well-contained addressing-layer extension. Recommends a season-selector + shared re-ranging sliders design. Verified end-to-end in Chromium: the fixture renders both merged group cells, Grid-Sight mounts without error, and zero sliders appear (fail closed). No src changes; interpolation core untouched. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DQkMTSjZd2fWS8H45WLcsh
Contributor
|
🧹 PR preview for #59 has been removed. |
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 176 |
| Duplication | 6 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
Normalise pipe spacing and fill the reproduction table's cells so the tables lint cleanly (Codacy CodeStyle / markdownlint table-column-style). Uses a ditto mark for continuation rows instead of ragged empty cells. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DQkMTSjZd2fWS8H45WLcsh
The merged group column breaks enrichment lozenge placement the same way it breaks slider binding: H/# mount on the Speed label column and on the merged Season cell, and the first speed of each block gets none. Documents this as a second manifestation of the shared single-row-header assumption and notes twin support is an addressing-layer concern, not slider-only. Verified against the live rendered DOM. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DQkMTSjZd2fWS8H45WLcsh
Adds support for "twin" lookup tables — Speed (rows) x Direction (columns) grouped by a merged Season column (Summer/Winter) — which the single-grid addressing layer previously mis-read (no sliders offered; H/# lozenges mis-placed on the label columns and the merged group cell). New, isolated from the single-grid slider path so ordinary tables cannot regress: - src/core/twin-grid.ts — pure, rowspan-aware detection + model: partitions the body into one rowHeader x colHeader sub-grid per group. - src/enrichments/twin-interp.ts — pure per-block bilinear eval with the twin-specific out-of-range rule (clear, not clamp). - src/enrichments/twin-slider.ts — synced-blocks controller: one shared Direction slider + one Speed slider per block, synced by value; a block whose range excludes the shared speed is disabled and its readout + highlight cleared. Reuses bilinear + the slider highlight classes. - src/ui/header-utils.ts — on a twin table, offer only the twin-aware S toggle on the corner (the mis-placed H/# are no longer shown) and route slider applicable/active/toggle to the twin controller. Design (synced blocks, no selector) recorded in specs/016-twin-interpolation/investigation.md. The demo (#15) now drives the feature. Deferred: group-awareness for heatmap/statistics/sort/filter/outlier (not offered on twin tables rather than mis-applied). Tests: twin-grid (6), twin-interp (6), twin-slider controller (6), and e2e tests/e2e/twin-interpolation.spec.ts (4) covering sync + out-of-range + lozenge placement. Full node suite green (711); verified end-to-end in Chromium. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DQkMTSjZd2fWS8H45WLcsh
Three fixes from live testing of the twin sliders:
- Vertical Speed sliders were inverted vs the table rows (dragging down
raised the interpolation). Dropping `direction: rtl` puts the min at the
top so the thumb tracks the rows: top = slowest (top row), bottom =
fastest. Verified by click-mapping in Chromium (top→30, bottom→80).
- The shared corner readout now shows the current Speed alongside the
Direction ("Speed 45 · Direction 90"), not Direction alone.
- Turning Grid-Sight off left the injected direction row, per-block sliders,
and highlights behind. Both teardown paths (per-table deactivateToggle and
the global disable()) now call disableTwinSliders, so GS-off restores the
original markup on grouped tables too.
Tests: added a corner-readout unit assertion and an e2e GS-off teardown case
(no twin adornments remain). Full node suite green (712); all twin e2e green;
verified end-to-end in Chromium.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DQkMTSjZd2fWS8H45WLcsh
Each live block now shows the circle marker at the interpolated (speed, direction) point inside its highlight rectangle — matching the single-grid slider's [data-gs-marker]. The marker is placed by interpolating between the four bracketing cells' centres (same math as heatmap-marker.ts), reuses the existing marker CSS, repositions on window resize, hides when the block is out of range, and is removed on teardown. Tests: two unit cases (per-block marker shown/hidden by range; removed on teardown) and an e2e assertion (one visible marker per block). Node suite green (714); twin e2e green; verified in Chromium. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DQkMTSjZd2fWS8H45WLcsh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds support for a real-world lookup format Grid-Sight couldn't handle: Speed (rows) × Direction (columns) with a merged Season column —
Summer(30–80 kts, 6 rows) andWinter(20–60 kts, 4 rows) — i.e. two stacked grids sharing the Direction axis.Started as an investigation (both symptoms traced to one root cause: the addressing layer assumes a single leading row-header column with no row groups), then implemented the fix per the agreed synced-blocks design.
Behaviour
Verified in Chromium; hand-checked interpolation (Summer @45kt/90° = 13.85, Winter = 9.55).
Changes
New, isolated from the single-grid slider path so ordinary tables cannot regress:
src/core/twin-grid.ts— pure, rowspan-aware detection + model (onerowHeader × colHeadersub-grid per group).src/enrichments/twin-interp.ts— pure per-blockbilineareval + the twin-specific out-of-range rule (clear, not clamp).src/enrichments/twin-slider.ts— the synced-blocks controller (shared Direction slider, per-block Speed slider, value-sync, out-of-range disable). Reusesbilinearand the existing highlight classes.src/ui/header-utils.ts— branch the sliders descriptor to the twin controller and suppress the mis-placed classic lozenges on twin tables.public/demo/twin-table/index.html— reproduction fixture, now the driving demo (Introduce walkthrough #15).specs/016-twin-interpolation/investigation.md— findings + the decided design.Deferred: group-awareness for heatmap / statistics / sort / filter / outlier — today they are simply not offered on a twin table rather than mis-applied.
Tests
twin-grid(6),twin-interp(6),twin-slidercontroller (6) — model, per-block interpolation, sync, out-of-range disable, teardown.tests/e2e/twin-interpolation.spec.ts(4) — lozenge placement, slider injection, value-sync, out-of-range clearing.🤖 Generated with Claude Code
https://claude.ai/code/session_01DQkMTSjZd2fWS8H45WLcsh