Public: anyone can read this; the crew can change it.
forked from trevato/cs
The buy shelf can say what is under a point: a cursor as data and a `controlAt` lookup #421
Check · Review · Land · Live done — Landed and live in production.
This is the first half of #355: the buy shelf can now say which control is under a point. Nothing is wired in yet, so `main.ts` and the game behave exactly as before. The #355 branch named in the issue no longer exists, so I started from pull #358's head (`refs/pull/358/head`) and reshaped its code to the design in #418.
shipped production is serving it deploy ae07c2d
After #420 put all of #358 on main, this pull shrank to two things: a clamping test for the buy panel's pointer, and a fix that brings / back inside its size budget. #420 landed cursor.ts, controlAt and the wiring in main.ts, which covers what #418 set out to build. That is also why this branch conflicted.
- Merge: I kept
main's versions of the four conflicting files, becausemain.tsis built on them.mainalready usescentre,moveCursorandtoPixels, andcontrolAtover an element fromelementFromPoint. This branch's point-based API would have been a second, unused way to do the same thing. Switchingmain.tsover to it would have gone against #418's "no change to main.ts". - Kept from this branch: a test in
src/client/cursor.test.tsthat clampsmoveCursorat each of the four edges separately. It also checks that the way back from a pinned edge starts at the edge. - Budget fix:
mainitself fails "a first visit stays inside its byte budget": with #419 and #420 together,/sends 10,646 B gzipped against a 10,500 B budget.
- styleFor in src/pages/shell.ts now strips CSS comments before the style block is sent and hashed. Stripping in that one place keeps the page and the style-src hash in step.
- The page's style block drops from 7,757 to 7,055 bytes raw, and / is back inside its budget.
- A new test in src/pages/shell.test.ts checks that comments are removed from the block and from the page.
- No test and no budget changed, and the #419 and #420 wording is untouched.
bun run test (typecheck, then bun test) passes: 1742 tests. To try it, open / in the preview and view the source: the <style> block has no comments and the page looks the same. The buy pointer behaves as it does on main.
🤖 Generated with Claude Code
This pull now only adds two tests. main has since shipped everything else it was going to change: #420 brought in the buy panel's pointer (cursor.ts, controlAt and the main.ts wiring). #410 made the shell strip CSS comments from the style block before it is sent and hashed, which is what this branch had done to keep / inside its byte budget.
- Merge: I took
main'ssrc/pages/shell.tsas it is. Itsuncommenteddoes the same job as this branch's, also trims the spaces around a comment, and is documented. Keeping both would have been two copies of one function. src/pages/shell.test.ts: a test that a page's CSS comments are removed from the style block and from the page.mainhad no test for this. Its expected string drops the trailing space, becausemain's version trims the spaces around a comment; that followsmain's intended behaviour and does not mark a bug.src/client/cursor.test.ts: a test thatmoveCursorstops at each of the four edges separately. It also checks that moving back from a pinned edge starts at the edge.
No code changes remain relative to main. bun run test (typecheck, then bun test) passes: 1755 tests. To try it, run bun test src/pages/shell.test.ts src/client/cursor.test.ts.
🤖 Generated with Claude Code
This is the first half of #355: the buy shelf can now say which control is under a point. Nothing is wired in yet, so
main.tsand the game behave exactly as before. The #355 branch named in the issue no longer exists, so I started from pull #358's head (refs/pull/358/head) and reshaped its code to the design in #418.src/client/cursor.ts(new): the buy panel's own pointer as plain data,{ x, y, area }.-
cursorIn(box)puts it at the centre of a rectangle. A rectangle with no size holds it at its corner rather than at NaN. -move(cursor, dx, dy)moves it one pixel per count of mouse movement, clamped to all four edges. A move that isn't a number moves nothing. -toCounts(degrees, sensitivity)turns the sensitivity-scaled look the frame receives back into counts. The pointer's speed then doesn't depend on the sensitivity. It isn't in the issue's list, but the wiring half needs it.src/client/buy.ts:drawBuynow returns each control it drew as{ tile, box(), act }.actis the same function the click listener calls, so a press through the pointer is a click.-
controlAt(drawn, x, y)returns the live control under a point. It returns null over a greyed tile, a gap, anything outside the panel, or a point that isn't a number. - A box includes its left and top edges but not its right and bottom ones, so two touching tiles never both answer. - The box is read each timecontrolAtruns, not when the panel is drawn.main.tsdraws the panel before showing it, and a hidden panel has no layout yet.controlAttook an element fromelementFromPoint; this one takes a point, as the issue asks. Drawing the arrow and sending the mouse to it belong to the second half.Tests: in
cursor.test.ts, the start position, movement, clamping at each edge and corner, and sensitivity. Inbuy.test.ts, controls come back in draw order with their presses, and points over a live tile, the rebuy control, a greyed tile, a gap, outside the panel and an unlaid-out page. The existing buy tests are untouched apart from the import line.bun run test(typecheck, thenbun test) passes: 1734 tests.To try it: run
bun test src/client/cursor.test.ts src/client/buy.test.ts. The preview looks the same as production.🤖 Generated with Claude Code
Closes #418