miaoda-game-spades-react
v0.3.3
Published
React DOM bindings for the fixed four-player partnership Spades rules profile.
Readme
miaoda-game-spades-react
React bindings and a framework-neutral controller for four-player partnership Spades.
pnpm add miaoda-game-spades-reactimport { createSpadesGame, SpadesController, useSpadesView } from 'miaoda-game-spades-react';
const controller = new SpadesController(
createSpadesGame({ playerIds: ['north', 'east', 'south', 'west'], seed: 2026 }),
'north',
);
function BidControls() {
const view = useSpadesView(controller);
const tricks = view.legalActions.bidValues[3];
return tricks !== undefined ? (
<button onClick={() => controller.dispatch({ type: 'bid', playerId: view.viewerId, tricks })}>
Bid {tricks}
</button>
) : null;
}Render controls only from legalActions. The view contains the selected player's hand, bids,
tricks, team scores and bags, but never opponent hands.
Commits and reconnects
const unsubscribe = controller.onCommit(({ revision, view, events }) => {
queueAnimations(events);
persistRevision(revision);
renderHud(view);
});
controller.replaceSnapshot(JSON.parse(savedJson), serverRevision);
controller.setViewerId('east');Only accepted actions advance revision or publish commits. Invalid viewers, corrupt snapshots, and
lower revisions throw without partially changing the controller.
Phaser
pnpm add miaoda-game-command-phaserimport { PhaserGameBridge } from 'miaoda-game-command-phaser';
const bridge = new PhaserGameBridge().setup(controller);
bridge.consumeWith((event) => animateSpadesEvent(event));
bridge.dispatch({ type: 'bid', playerId: controller.state.activePlayerId, tricks: 3 });
bridge.destroy();
unsubscribe();The bridge consumes successful commits in order and exposes the same player-safe view and detached public events as React.
