feat(tabletop): add free-interaction layer (layer 3)
Add the interaction half of the sandbox: a held part and dialog stack as UI state outside the game store, with pure helpers (interactionsFor, dropPaths, pickPath, partFacings, nextFacing). PartPlacement is now interactive (pick up, drag to move, click to cycle facing), and a drop on a path with a stack-dialog interaction opens the deck dialog instead of moving directly. DialogLayer renders the stack-inspector dialog whose insert button issues a move. Add the dialog role, Setup.interactions, and Package.dialogs to @tts/bgm, and declare the deck insert dialog in games/poker.
This commit is contained in:
@@ -5,9 +5,10 @@ with a bgm game that has no rules yet: a sandbox. It builds on the state model:
|
||||
see [`state-model.md`](./state-model.md) for components-vs-setup, path→stack ×
|
||||
facing, and the anchoring scope.
|
||||
|
||||
> **Status:** Design. Proposes the operation set, the command/dialog split, and
|
||||
> the deck-pick-up dialog before the interaction half of `@tts/tabletop` is
|
||||
> built.
|
||||
> **Status:** Implemented (layer 3, sandbox). The operation set, the
|
||||
> command/dialog split, and the deck-pick-up dialog are built in
|
||||
> `@tts/tabletop` (`interactions.ts`, `dialog.tsx`). Rule-enforced play (layer
|
||||
> 4) is not yet wired — the rule seam is a no-op filter over free interaction.
|
||||
|
||||
## 1. The operation set is closed and tiny
|
||||
|
||||
|
||||
@@ -173,6 +173,28 @@ consumers share them (see Open decisions).
|
||||
- `pnpm --filter @tts/web build` — the part inspection route renders `PartView`
|
||||
from the library (work item 2), proving it end-to-end.
|
||||
|
||||
## Free interaction (layer 3) ✅
|
||||
|
||||
Sandbox interaction is built per [`../bgm/interactions.md`](../bgm/interactions.md):
|
||||
|
||||
- `interactions.ts` — the held part + dialog stack (UI state, outside the game
|
||||
store), plus pure helpers (`interactionsFor`, `dropPaths`, `pickPath`,
|
||||
`partFacings`, `nextFacing`).
|
||||
- `state.ts` — `setFacing` alongside `movePart` (the `move(id, path, index?)`
|
||||
primitive, defaulting to top of stack).
|
||||
- `placement.tsx` — `PartPlacement` is now interactive: pick up a part (held,
|
||||
lifted above the board), drag to a path anchor to `move`, click to cycle
|
||||
facing. A drop on a path with a stack-dialog interaction opens the deck
|
||||
dialog instead of moving directly.
|
||||
- `dialog.tsx` — `DialogLayer`, the stack-inspector dialog: an alternate view
|
||||
of a stack with an insertion cursor; its insert button issues a `move`.
|
||||
- `@tts/bgm` — the `dialog` role, `Setup.interactions`, and `Package.dialogs`
|
||||
(schema + collection + serialization).
|
||||
- Demo: `games/poker` declares an `interactions:` + `role: dialog` (stack
|
||||
insert) on the deck.
|
||||
|
||||
The rule seam (layer 4) is a no-op filter: sandbox applies intents directly.
|
||||
|
||||
## Commands (not yet implemented)
|
||||
|
||||
Scripted interaction is designed in [`../bgm/commands.md`](../bgm/commands.md):
|
||||
|
||||
Reference in New Issue
Block a user