@anweather/plugin-board-kit
v1.19.0
Published
Board-UI primitives for a web-boardgame-platform game board: the mount/update/unmount handle a remote plugin's bundle exports, BoardShell/TurnIdentity layout, turn/spectator/team helpers, the TurnClock display half, and the pinch/wheel canvas camera. Reac
Downloads
961
Readme
@anweather/plugin-board-kit
Board-UI primitives for any game board on web-boardgame-platform: a remote
plugin's frontend bundle (boardgame-plugins, tactics-game-plugin, the
platform's own plugins/tic-tac-toe-remote) and the native boards still in
this repo's frontend/. One implementation, one package, on the public npm
registry.
Published with the SDK, at the SDK's version. publish-plugin-sdk.yml
releases this package together with @anweather/game-plugin-ssdk and the
Kotlin runtime from one sdk-v* tag, so a plugin's board kit, SSDK and
runtime pin all name the same release. See plugin-protocol/CLAUDE.md,
"Publishing for cross-repo plugins".
Why a package and not a copy. A plugin's frontend bundles its own React
(nothing marked external). react and react-dom are peer
dependencies here, so the consumer's own node_modules/react is the one
this code binds to: exactly one React instance per bundle. The shell-script
vendoring this replaced existed to dodge the two-React failure a plain
cross-directory import produced ("Cannot read properties of null (reading
'useState')" at runtime), and left eight of ten copies stale.
Contents
mountReactBoard(Component, { onError?, fallback? })returns the{ mount, update, unmount }handle a remote bundle exports across the ShadowMount boundary. It wraps the board in an error boundary: a render error shows a message instead of a blank rectangle, is reported throughonError, and clears on the nextupdate().BoardShell(centered-column layout) andTurnIdentity(the "You are X" row, with a spectator variant). Inline styles throughout;TurnIdentitytakes a CSScolor, never a class name, so it renders the same inside a shadow root with no Tailwind in reach.computeIsMyTurn/computeIsAwaiting/computeIsSpectatorover a minimal structuralTurnState(anything withlifecycle,currentTurnParticipantId,participantsand optionallyawaitingParticipantIds,GameViewincluded).computeIsAwaitingis what "waiting on me" means during a simultaneous phase.teamOf/teamMembersfor a 4-seat, 2-team, alternating-seat game (mirrors platform-domain'sTeamAssignment).- The display half of platform-domain's
TurnClock:useClockNow,useClockTimeout,formatClock,remainingMs,clockReading, and theClockBadge/StartTurnGatecomponents. What running out does stays the engine's call. useCanvasCamera: pinch/wheel zoom and two-finger pan for a canvas-rendered board, renderer-agnostic (Canvas2D viaapplyTransform, or drive a Pixi container from.zoom/.offsetX/.offsetY).
Not here on purpose: nameplateAccent.ts (this repo's
frontend/src/plugins/) hardcodes per-gameType colours across the native
catalogue, which is platform logic, not a board primitive.
Developing
npm ci && npm run build && npm test && npm run typechecknpm test covers the pure helpers (turn, team and clock arithmetic) with
node:test; the components are typechecked and exercised by their
consumers' own Playwright suites. To try an unpublished change in a
consumer, npm pack here and install the tarball there; the consumer's
package.json should never point at this directory by path, since a
file: link resolves react through this directory's own node_modules
and reintroduces the two-React bundle.
