dreamboard 0.1.21 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-EYYWGWTO.js → chunk-2RCUHMGL.js} +343 -1911
- package/dist/chunk-2RCUHMGL.js.map +1 -0
- package/dist/{chunk-MOVHYB6E.js → chunk-GN7232BY.js} +1025 -695
- package/dist/chunk-GN7232BY.js.map +1 -0
- package/dist/{chunk-BMYC6772.js → chunk-H3O43F5P.js} +9765 -3068
- package/dist/chunk-H3O43F5P.js.map +1 -0
- package/dist/dev-host/dev-api-proxy-plugin.ts +330 -0
- package/dist/dev-host/dev-diagnostics.ts +62 -0
- package/dist/dev-host/dev-fallback-stylesheet.ts +50 -0
- package/dist/dev-host/dev-host-controller.ts +686 -0
- package/dist/dev-host/dev-host-player-query.ts +17 -0
- package/dist/dev-host/dev-host-session-transport.ts +52 -0
- package/dist/dev-host/dev-host-storage.ts +56 -0
- package/dist/dev-host/dev-log-relay-plugin.ts +469 -0
- package/dist/dev-host/dev-runtime-config.ts +14 -0
- package/dist/dev-host/dev-runtime-platform.ts +419 -0
- package/dist/dev-host/dev-virtual-modules-plugin.ts +63 -0
- package/dist/dev-host/host-main.css +182 -0
- package/dist/dev-host/host-main.tsx +754 -0
- package/dist/dev-host/index.html +56 -0
- package/dist/dev-host/plugin-main.ts +55 -0
- package/dist/dev-host/plugin.html +24 -0
- package/dist/dev-host/start-dev-server.ts +138 -0
- package/dist/dev-host/virtual-modules.d.ts +27 -0
- package/dist/dist-FEPN3BDN.js +16543 -0
- package/dist/dist-FEPN3BDN.js.map +1 -0
- package/dist/{dist-WJRJNFLI.js → dist-FRURQI7Q.js} +4 -2
- package/dist/index.js +3 -3
- package/dist/internal.js +159 -124
- package/dist/internal.js.map +1 -1
- package/dist/runtime-packages/tailwind-config/shared-styles.css +146 -0
- package/dist/runtime-packages/ui/src/components/.gitkeep +0 -0
- package/dist/runtime-packages/ui/src/components/accordion.tsx +66 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/actions.tsx +65 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/artifact.tsx +147 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/branch.tsx +215 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/canvas.tsx +22 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/chain-of-thought.tsx +228 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/code-block.tsx +179 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/confirmation.tsx +158 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/connection.tsx +28 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/context.tsx +408 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/controls.tsx +18 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/conversation.tsx +97 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/edge.tsx +140 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/image.tsx +24 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/inline-citation.tsx +287 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/loader.tsx +96 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/message.tsx +463 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/node.tsx +71 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/open-in-chat.tsx +365 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/panel.tsx +15 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/plan.tsx +142 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/prompt-input.tsx +1380 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/queue.tsx +274 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/reasoning.tsx +182 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/response.tsx +22 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/shimmer.tsx +64 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/sources.tsx +77 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/suggestion.tsx +53 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/task.tsx +87 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/tool.tsx +165 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/toolbar.tsx +16 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/web-preview.tsx +263 -0
- package/dist/runtime-packages/ui/src/components/alert-dialog.tsx +157 -0
- package/dist/runtime-packages/ui/src/components/alert.tsx +66 -0
- package/dist/runtime-packages/ui/src/components/avatar.tsx +53 -0
- package/dist/runtime-packages/ui/src/components/badge.tsx +46 -0
- package/dist/runtime-packages/ui/src/components/button-group.tsx +83 -0
- package/dist/runtime-packages/ui/src/components/button.tsx +65 -0
- package/dist/runtime-packages/ui/src/components/card.tsx +92 -0
- package/dist/runtime-packages/ui/src/components/carousel.tsx +241 -0
- package/dist/runtime-packages/ui/src/components/collapsible.tsx +33 -0
- package/dist/runtime-packages/ui/src/components/command.tsx +184 -0
- package/dist/runtime-packages/ui/src/components/context-menu.tsx +252 -0
- package/dist/runtime-packages/ui/src/components/counter.tsx +11 -0
- package/dist/runtime-packages/ui/src/components/dialog.tsx +146 -0
- package/dist/runtime-packages/ui/src/components/drawer.tsx +132 -0
- package/dist/runtime-packages/ui/src/components/dropdown-menu.tsx +257 -0
- package/dist/runtime-packages/ui/src/components/form.tsx +168 -0
- package/dist/runtime-packages/ui/src/components/header.tsx +13 -0
- package/dist/runtime-packages/ui/src/components/hover-card.tsx +44 -0
- package/dist/runtime-packages/ui/src/components/input-group.tsx +178 -0
- package/dist/runtime-packages/ui/src/components/input.tsx +21 -0
- package/dist/runtime-packages/ui/src/components/item.tsx +193 -0
- package/dist/runtime-packages/ui/src/components/label.tsx +24 -0
- package/dist/runtime-packages/ui/src/components/navigation-menu.tsx +168 -0
- package/dist/runtime-packages/ui/src/components/popover.tsx +55 -0
- package/dist/runtime-packages/ui/src/components/progress.tsx +31 -0
- package/dist/runtime-packages/ui/src/components/radio-group.tsx +45 -0
- package/dist/runtime-packages/ui/src/components/resizable.tsx +56 -0
- package/dist/runtime-packages/ui/src/components/scroll-area.tsx +58 -0
- package/dist/runtime-packages/ui/src/components/select.tsx +187 -0
- package/dist/runtime-packages/ui/src/components/separator.tsx +28 -0
- package/dist/runtime-packages/ui/src/components/skeleton.tsx +13 -0
- package/dist/runtime-packages/ui/src/components/sonner.tsx +25 -0
- package/dist/runtime-packages/ui/src/components/spinner.tsx +16 -0
- package/dist/runtime-packages/ui/src/components/switch.tsx +31 -0
- package/dist/runtime-packages/ui/src/components/table.tsx +137 -0
- package/dist/runtime-packages/ui/src/components/tabs.tsx +74 -0
- package/dist/runtime-packages/ui/src/components/textarea.tsx +23 -0
- package/dist/runtime-packages/ui/src/components/theme-provider.tsx +73 -0
- package/dist/runtime-packages/ui/src/components/tooltip.tsx +61 -0
- package/dist/runtime-packages/ui/src/components/ui/file-upload.tsx +195 -0
- package/dist/runtime-packages/ui/src/hooks/.gitkeep +0 -0
- package/dist/runtime-packages/ui/src/index.ts +68 -0
- package/dist/runtime-packages/ui/src/lib/utils.ts +6 -0
- package/dist/runtime-packages/ui-host-runtime/src/actor-principal.ts +68 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/host-controls.tsx +359 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback-toaster.tsx +274 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback.tsx +214 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/host-session-metadata.tsx +135 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/index.ts +5 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/perf-overlay.tsx +194 -0
- package/dist/runtime-packages/ui-host-runtime/src/host-controls.tsx +1 -0
- package/dist/runtime-packages/ui-host-runtime/src/host-feedback.tsx +1 -0
- package/dist/runtime-packages/ui-host-runtime/src/host-session-transport.ts +162 -0
- package/dist/runtime-packages/ui-host-runtime/src/index.ts +2 -0
- package/dist/runtime-packages/ui-host-runtime/src/logger.ts +11 -0
- package/dist/runtime-packages/ui-host-runtime/src/perf.ts +253 -0
- package/dist/runtime-packages/ui-host-runtime/src/plugin-bridge.ts +195 -0
- package/dist/runtime-packages/ui-host-runtime/src/plugin-health-check.ts +138 -0
- package/dist/runtime-packages/ui-host-runtime/src/plugin-messages.ts +159 -0
- package/dist/runtime-packages/ui-host-runtime/src/plugin-session-gateway.ts +524 -0
- package/dist/runtime-packages/ui-host-runtime/src/runtime/index.ts +12 -0
- package/dist/runtime-packages/ui-host-runtime/src/screenshot/projection-to-snapshot.ts +122 -0
- package/dist/runtime-packages/ui-host-runtime/src/screenshot/static-store-api.ts +26 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-ingress-controller.ts +477 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-ingress.ts +209 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-live-runtime.ts +112 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-model.ts +318 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-projection.ts +211 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-state-reducer.ts +814 -0
- package/dist/runtime-packages/ui-host-runtime/src/sse-manager.ts +334 -0
- package/dist/runtime-packages/ui-host-runtime/src/unified-session-store.ts +180 -0
- package/dist/scaffold/assets/static/app/tsconfig.framework.json +3 -1
- package/dist/scaffold/assets/static/ui/tsconfig.framework.json +7 -19
- package/package.json +52 -17
- package/skills/dreamboard/SKILL.md +41 -75
- package/LICENSE +0 -89
- package/NOTICE +0 -1
- package/dist/chunk-BMYC6772.js.map +0 -1
- package/dist/chunk-EYYWGWTO.js.map +0 -1
- package/dist/chunk-MOVHYB6E.js.map +0 -1
- package/dist/scaffold/assets/static/ui/App.tsx +0 -22
- package/dist/src-CUL7EGGG.js +0 -634
- package/dist/src-CUL7EGGG.js.map +0 -1
- package/skills/dreamboard/references/authoring-lifecycle.md +0 -102
- package/skills/dreamboard/references/board-surfaces.md +0 -36
- package/skills/dreamboard/references/board-topology.md +0 -443
- package/skills/dreamboard/references/boards-and-topology.md +0 -100
- package/skills/dreamboard/references/card-actions.md +0 -107
- package/skills/dreamboard/references/cli.md +0 -120
- package/skills/dreamboard/references/core-concepts.md +0 -514
- package/skills/dreamboard/references/custom-renderers.md +0 -26
- package/skills/dreamboard/references/derived-values.md +0 -55
- package/skills/dreamboard/references/effects.md +0 -111
- package/skills/dreamboard/references/game-contract.md +0 -89
- package/skills/dreamboard/references/game-definition.md +0 -89
- package/skills/dreamboard/references/game-shell.md +0 -80
- package/skills/dreamboard/references/hand-surfaces.md +0 -33
- package/skills/dreamboard/references/index.md +0 -112
- package/skills/dreamboard/references/inputs-and-targets.md +0 -160
- package/skills/dreamboard/references/interactions.md +0 -158
- package/skills/dreamboard/references/manifest-fields.md +0 -137
- package/skills/dreamboard/references/manifest.md +0 -81
- package/skills/dreamboard/references/package-surfaces.md +0 -69
- package/skills/dreamboard/references/phases.md +0 -145
- package/skills/dreamboard/references/prompts-and-choices.md +0 -55
- package/skills/dreamboard/references/quickstart.md +0 -71
- package/skills/dreamboard/references/rule-authoring.md +0 -144
- package/skills/dreamboard/references/setup-bootstrap.md +0 -78
- package/skills/dreamboard/references/stages-and-zones.md +0 -59
- package/skills/dreamboard/references/static-views.md +0 -67
- package/skills/dreamboard/references/table-queries-and-ops.md +0 -103
- package/skills/dreamboard/references/testing-bases.md +0 -147
- package/skills/dreamboard/references/testing-generated-contracts.md +0 -142
- package/skills/dreamboard/references/testing-runtime-assertions.md +0 -124
- package/skills/dreamboard/references/testing-scenarios.md +0 -148
- package/skills/dreamboard/references/testing-ui-tests.md +0 -174
- package/skills/dreamboard/references/testing.md +0 -161
- package/skills/dreamboard/references/ui-architecture.md +0 -137
- package/skills/dreamboard/references/ui-components.md +0 -34
- package/skills/dreamboard/references/views.md +0 -72
- package/skills/dreamboard/references/workspace-layout.md +0 -136
- /package/dist/{dist-WJRJNFLI.js.map → dist-FRURQI7Q.js.map} +0 -0
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
# Interactions
|
|
2
|
-
|
|
3
|
-
Use defineInteraction to author player commands, prompts, inputs, validation, and reducer logic.
|
|
4
|
-
|
|
5
|
-
Interactions are the canonical player-facing reducer primitive. They define what
|
|
6
|
-
a player can submit and how the reducer responds.
|
|
7
|
-
|
|
8
|
-
```ts
|
|
9
|
-
const placeThingCard = defineInteraction<
|
|
10
|
-
GameContract,
|
|
11
|
-
typeof placeThingPhaseStateSchema
|
|
12
|
-
>()({
|
|
13
|
-
step: "placing",
|
|
14
|
-
inputs: {
|
|
15
|
-
cardId: cardInput<GameState, ThingsDeckCardId>({
|
|
16
|
-
target: placeableThingCardTarget,
|
|
17
|
-
}),
|
|
18
|
-
ringId: formInput(zoneIdSchema),
|
|
19
|
-
},
|
|
20
|
-
rules: [
|
|
21
|
-
{
|
|
22
|
-
id: "knower-cannot-place",
|
|
23
|
-
errorCode: "KNOWER_CANNOT_PLACE",
|
|
24
|
-
message: "The Knower cannot place Things.",
|
|
25
|
-
validate: ({ state, input }) =>
|
|
26
|
-
input.playerId === state.publicState.knowerPlayerId
|
|
27
|
-
? {
|
|
28
|
-
errorCode: "KNOWER_CANNOT_PLACE",
|
|
29
|
-
message: "The Knower cannot place Things.",
|
|
30
|
-
}
|
|
31
|
-
: null,
|
|
32
|
-
},
|
|
33
|
-
],
|
|
34
|
-
reduce({ state, input, accept, fx, ops }) {
|
|
35
|
-
return accept(
|
|
36
|
-
pipe(
|
|
37
|
-
state,
|
|
38
|
-
ops.moveCardFromPlayerZoneToSharedZone({
|
|
39
|
-
playerId: input.playerId,
|
|
40
|
-
fromZoneId: "things-hand",
|
|
41
|
-
toZoneId: input.params.ringId,
|
|
42
|
-
cardId: input.params.cardId,
|
|
43
|
-
playedBy: input.playerId,
|
|
44
|
-
}),
|
|
45
|
-
),
|
|
46
|
-
[fx.transition("judgeRings")],
|
|
47
|
-
);
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Required shape
|
|
53
|
-
|
|
54
|
-
| Field | Purpose |
|
|
55
|
-
| --- | --- |
|
|
56
|
-
| `inputs` | Collector map that defines params, target metadata, defaults, and client schemas. |
|
|
57
|
-
| `rules` | Shared availability and validation rules that can disable descriptors before params exist and reject parsed submissions. |
|
|
58
|
-
| `paramsSchema` | Optional cross-field Zod schema layered on top of collector params. |
|
|
59
|
-
| `cost` | Optional resource cost descriptor for UI-visible affordability. |
|
|
60
|
-
| `commit` | Optional draft submit policy such as `{ mode: "manual" }` or `{ mode: "autoWhenReady" }`. |
|
|
61
|
-
| `reduce` | Pure reducer callback that accepts or rejects a state transition. |
|
|
62
|
-
|
|
63
|
-
Optional reducer fields such as `step`, `steps`, `actor`, `to`, `visibility`,
|
|
64
|
-
`rules`, `paramsSchema`, `cost`, and `commit` are still reducer authority:
|
|
65
|
-
they control who can act, when the descriptor exists, which targets are legal,
|
|
66
|
-
which params are accepted, and how the UI can present affordability.
|
|
67
|
-
|
|
68
|
-
Reducers do not own visual placement, labels, salience, icons, grouping, dialog
|
|
69
|
-
chrome, or presentation policy. Put those choices in React, CSS, or default UI
|
|
70
|
-
wrappers built on the generated primitives.
|
|
71
|
-
|
|
72
|
-
## Authorization
|
|
73
|
-
|
|
74
|
-
Actor authorization is handled by the trusted bundle before `reduce` runs.
|
|
75
|
-
|
|
76
|
-
Use phase-level `actor` for ordinary turns:
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
actor: ({ state }) => state.flow.activePlayers
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
Use interaction-level `actor` when one interaction has a different actor. Use
|
|
83
|
-
`to` for addressed prompt interactions.
|
|
84
|
-
|
|
85
|
-
Do not duplicate the same turn check in every `validate` callback unless the
|
|
86
|
-
interaction has a business rule that differs from actor authorization.
|
|
87
|
-
|
|
88
|
-
## Availability and validation
|
|
89
|
-
|
|
90
|
-
Use `rules` to share descriptor availability and submit validation. Each rule
|
|
91
|
-
can expose `available` for pre-param UI state, `validate` for parsed params, or
|
|
92
|
-
both. Extract repeated rules with `defineInteractionRule`.
|
|
93
|
-
|
|
94
|
-
```ts
|
|
95
|
-
const canAffordBuild = defineInteractionRule<GameContract, typeof phaseState>()({
|
|
96
|
-
id: "can-afford-build",
|
|
97
|
-
errorCode: "INSUFFICIENT_RESOURCES",
|
|
98
|
-
message: "You need more resources.",
|
|
99
|
-
available: ({ input, q }) => q.player.canAfford(input.playerId, BUILD_COST),
|
|
100
|
-
validate: ({ input, q }) =>
|
|
101
|
-
q.player.canAfford(input.playerId, BUILD_COST)
|
|
102
|
-
? null
|
|
103
|
-
: { errorCode: "INSUFFICIENT_RESOURCES" },
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const build = defineInteraction<GameContract, typeof phaseState>()({
|
|
107
|
-
inputs: {},
|
|
108
|
-
cost: BUILD_COST,
|
|
109
|
-
rules: [canAffordBuild],
|
|
110
|
-
reduce({ state, accept }) {
|
|
111
|
-
return accept(state);
|
|
112
|
-
},
|
|
113
|
-
});
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
Target collectors run their own validation before authored rules. Use
|
|
117
|
-
`paramsSchema` when a rule spans multiple fields. For example, Star Settlers
|
|
118
|
-
uses collector domains for trade controls and a `paramsSchema` to require at
|
|
119
|
-
least one offered and requested resource.
|
|
120
|
-
|
|
121
|
-
## Prompts
|
|
122
|
-
|
|
123
|
-
Prompt-kind interactions are ordinary `defineInteraction` entries with a
|
|
124
|
-
`promptInput` collector. The runtime projects them as prompt descriptors and
|
|
125
|
-
addresses them with `to`.
|
|
126
|
-
|
|
127
|
-
```ts
|
|
128
|
-
const respondToTrade = defineInteraction<GameContract, typeof phaseState>()({
|
|
129
|
-
inputs: {
|
|
130
|
-
response: promptInput({
|
|
131
|
-
schema: z.enum(["accept", "reject"]),
|
|
132
|
-
target: choiceTarget
|
|
133
|
-
.options<GameState, "accept" | "reject">([
|
|
134
|
-
{ id: "accept", label: "Accept" },
|
|
135
|
-
{ id: "reject", label: "Reject" },
|
|
136
|
-
])
|
|
137
|
-
.build(),
|
|
138
|
-
}),
|
|
139
|
-
},
|
|
140
|
-
to: ({ state }) => state.phase.pendingTrade?.targetPlayerIds ?? null,
|
|
141
|
-
reduce({ state, input, accept }) {
|
|
142
|
-
// input.params.response is "accept" | "reject"
|
|
143
|
-
return accept(state);
|
|
144
|
-
},
|
|
145
|
-
});
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
Render prompt descriptors with `PromptInbox`, `Prompt`, and `Prompt.Option`
|
|
149
|
-
from `@dreamboard/ui-contract`; the reducer only declares the response domain.
|
|
150
|
-
|
|
151
|
-
## Client params vs reducer params
|
|
152
|
-
|
|
153
|
-
Generated UI/test params omit engine-sampled collectors such as
|
|
154
|
-
`rngInput.d6(2)`. Reducer params include them because the trusted bundle samples
|
|
155
|
-
them before calling `reduce`.
|
|
156
|
-
|
|
157
|
-
See [Inputs and targets](./inputs-and-targets.md) for collector
|
|
158
|
-
details.
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
# Manifest fields
|
|
2
|
-
|
|
3
|
-
Reference manifest schemas, component homes, visibility, slot hosts, and setup fields.
|
|
4
|
-
|
|
5
|
-
Manifest fields let you attach typed static data to cards, pieces, dice, boards, spaces, edges, vertices, relations, and containers.
|
|
6
|
-
|
|
7
|
-
## Field schemas
|
|
8
|
-
|
|
9
|
-
Schemas use Dreamboard's manifest property schema format, not Zod. The generated manifest contract turns these into typed values.
|
|
10
|
-
|
|
11
|
-
```ts
|
|
12
|
-
cardSets: [
|
|
13
|
-
{
|
|
14
|
-
type: "manual",
|
|
15
|
-
id: "contracts",
|
|
16
|
-
name: "Contracts",
|
|
17
|
-
cardSchema: {
|
|
18
|
-
properties: {
|
|
19
|
-
rewardCoins: { type: "integer" },
|
|
20
|
-
route: { type: "enum", enums: ["market", "river", "trail"] },
|
|
21
|
-
targetBoard: { type: "boardId" },
|
|
22
|
-
targetSpace: { type: "spaceId" },
|
|
23
|
-
bonusResource: { type: "resourceId", optional: true },
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
cards: [
|
|
27
|
-
{
|
|
28
|
-
type: "ferry-charter",
|
|
29
|
-
name: "Ferry Charter",
|
|
30
|
-
count: 2,
|
|
31
|
-
properties: {
|
|
32
|
-
rewardCoins: 2,
|
|
33
|
-
route: "river",
|
|
34
|
-
targetBoard: "frontier-map",
|
|
35
|
-
targetSpace: "ford",
|
|
36
|
-
bonusResource: "provisions",
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
},
|
|
41
|
-
];
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Reference fields by their manifest ids instead of plain strings. `defineTopologyManifest` rejects values that do not match the current manifest.
|
|
45
|
-
|
|
46
|
-
## Component homes
|
|
47
|
-
|
|
48
|
-
Cards, pieces, and dice can start in zones, board spaces, board containers, tiled edges, tiled vertices, or slots.
|
|
49
|
-
|
|
50
|
-
```ts
|
|
51
|
-
pieceSeeds: [
|
|
52
|
-
{
|
|
53
|
-
id: "worker-1",
|
|
54
|
-
typeId: "worker",
|
|
55
|
-
ownerId: "player-1",
|
|
56
|
-
home: {
|
|
57
|
-
type: "slot",
|
|
58
|
-
host: { kind: "piece", id: "mat-player-1" },
|
|
59
|
-
slotId: "farm",
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
];
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Use `ownerId` for player-owned seeds. For per-player board or zone homes, include enough ownership data for the runtime to resolve the actual player-scoped container.
|
|
66
|
-
|
|
67
|
-
## Visibility
|
|
68
|
-
|
|
69
|
-
Visibility belongs in the manifest when it is a static property of a component or zone.
|
|
70
|
-
|
|
71
|
-
Common patterns:
|
|
72
|
-
|
|
73
|
-
| Visibility | Use for |
|
|
74
|
-
| --- | --- |
|
|
75
|
-
| `public` | Shared face-up information. |
|
|
76
|
-
| `hidden` | Decks or piles where contents/order are not public. |
|
|
77
|
-
| `ownerOnly` | Per-player hands or private player areas. |
|
|
78
|
-
| `{ faceUp: false }` | Manual cards that should start face down. |
|
|
79
|
-
|
|
80
|
-
Runtime secrecy still belongs in state and projections. A card being in an owner-only zone does not mean every view should expose all secret data about that card.
|
|
81
|
-
|
|
82
|
-
## Slots
|
|
83
|
-
|
|
84
|
-
Slots model fixed attachment points on pieces or dice. They are useful for worker mats, die trays, upgrade sockets, or other component-hosted positions.
|
|
85
|
-
|
|
86
|
-
```ts
|
|
87
|
-
pieceTypes: [
|
|
88
|
-
{
|
|
89
|
-
id: "player-mat",
|
|
90
|
-
name: "Player Mat",
|
|
91
|
-
slots: [
|
|
92
|
-
{ id: "farm", name: "Farm" },
|
|
93
|
-
{ id: "market", name: "Market" },
|
|
94
|
-
],
|
|
95
|
-
},
|
|
96
|
-
];
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
Slots are static topology. Runtime occupancy is read through `q.slot.*` and moved through table operations.
|
|
100
|
-
|
|
101
|
-
## Setup options and profiles
|
|
102
|
-
|
|
103
|
-
Use `setupOptions` for knobs that change game setup. Use `setupProfiles` for named presets.
|
|
104
|
-
|
|
105
|
-
```ts
|
|
106
|
-
setupOptions: [
|
|
107
|
-
{
|
|
108
|
-
id: "map-size",
|
|
109
|
-
name: "Map size",
|
|
110
|
-
choices: [
|
|
111
|
-
{ id: "small", name: "Small" },
|
|
112
|
-
{ id: "wide", name: "Wide" },
|
|
113
|
-
],
|
|
114
|
-
},
|
|
115
|
-
],
|
|
116
|
-
setupProfiles: [
|
|
117
|
-
{
|
|
118
|
-
id: "default",
|
|
119
|
-
name: "Default",
|
|
120
|
-
optionValues: { "map-size": "small" },
|
|
121
|
-
},
|
|
122
|
-
],
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
The generated setup profile helper keeps authored `optionValues` aligned with the available setup option and choice ids.
|
|
126
|
-
|
|
127
|
-
## When not to use fields
|
|
128
|
-
|
|
129
|
-
Do not use manifest fields to mirror mutable state. Examples that should be reducer state or table state:
|
|
130
|
-
|
|
131
|
-
- current resource balances
|
|
132
|
-
- whether a card has been played this turn
|
|
133
|
-
- which player owns a temporary claim
|
|
134
|
-
- current turn step
|
|
135
|
-
- pending selected target
|
|
136
|
-
|
|
137
|
-
The manifest should describe what can exist. The reducer state and table describe what is currently true.
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
# Manifest
|
|
2
|
-
|
|
3
|
-
Use defineTopologyManifest to declare the static table model for a Dreamboard game.
|
|
4
|
-
|
|
5
|
-
The manifest is the static source of truth for a game. It names the objects that the reducer, UI, tests, and setup code should agree on: players, card sets, zones, boards, pieces, dice, resources, setup options, and setup profiles.
|
|
6
|
-
|
|
7
|
-
Author it in `manifest.ts`:
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
import { defineTopologyManifest } from "@dreamboard/sdk-types";
|
|
11
|
-
|
|
12
|
-
export default defineTopologyManifest({
|
|
13
|
-
players: {
|
|
14
|
-
minPlayers: 2,
|
|
15
|
-
maxPlayers: 4,
|
|
16
|
-
optimalPlayers: 3,
|
|
17
|
-
},
|
|
18
|
-
cardSets: [],
|
|
19
|
-
zones: [],
|
|
20
|
-
boards: [],
|
|
21
|
-
});
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
`defineTopologyManifest` returns the manifest unchanged at runtime, but it gives TypeScript enough information to reject invalid IDs and incompatible component locations while you author.
|
|
25
|
-
|
|
26
|
-
## What belongs in the manifest
|
|
27
|
-
|
|
28
|
-
Put static, setup-time structure in the manifest:
|
|
29
|
-
|
|
30
|
-
| Manifest section | Use for |
|
|
31
|
-
| --- | --- |
|
|
32
|
-
| `players` | Player count bounds and generated player ids. |
|
|
33
|
-
| `cardSets` | Manual or preset card sets, card schemas, card counts, starting homes. |
|
|
34
|
-
| `zones` | Shared piles and per-player hands. |
|
|
35
|
-
| `boardTemplates` | Reusable board definitions. |
|
|
36
|
-
| `boards` | Shared or per-player board instances. |
|
|
37
|
-
| `pieceTypes` and `pieceSeeds` | Piece schemas, slots, starting pieces, ownership, starting homes. |
|
|
38
|
-
| `dieTypes` and `dieSeeds` | Dice, dice fields, starting dice, ownership, starting homes. |
|
|
39
|
-
| `resources` | Player resource ids and labels. |
|
|
40
|
-
| `setupOptions` | User-selectable setup knobs. |
|
|
41
|
-
| `setupProfiles` | Named setup presets that choose setup-option values. |
|
|
42
|
-
|
|
43
|
-
Do not put runtime facts in the manifest. Current scores, active turn, pending prompts, drawn card ids, resource balances, and temporary decisions belong in reducer state or the runtime table.
|
|
44
|
-
|
|
45
|
-
## Generated contract
|
|
46
|
-
|
|
47
|
-
After changing the manifest, run:
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
dreamboard sync
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
The generated `shared/manifest-contract.ts` exposes:
|
|
54
|
-
|
|
55
|
-
- `literals`, including ids such as `playerIds`, `cardIds`, `zoneIds`, and `setupProfileIds`
|
|
56
|
-
- `ids`, a Zod schema namespace for manifest-backed ids
|
|
57
|
-
- `manifestContract`, the object passed into `defineGameContract`
|
|
58
|
-
- runtime table types such as `TableState`
|
|
59
|
-
- setup profile helpers
|
|
60
|
-
- typed helper constructors for setup bootstrap steps
|
|
61
|
-
|
|
62
|
-
Use generated exports instead of duplicating string unions:
|
|
63
|
-
|
|
64
|
-
```ts
|
|
65
|
-
import { ids, literals, manifestContract } from "../shared/manifest-contract";
|
|
66
|
-
|
|
67
|
-
const playerIdSchema = ids.playerId;
|
|
68
|
-
const knownZones = literals.zoneIds;
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Canonical authoring rule
|
|
72
|
-
|
|
73
|
-
If a thing has an identity that the reducer, UI, or tests need to agree on, define that identity in the manifest. Let generated types carry that identity forward.
|
|
74
|
-
|
|
75
|
-
Avoid local parallel lists such as `const ZONES = [...]` unless they are derived from, or intentionally narrower than, manifest-generated ids.
|
|
76
|
-
|
|
77
|
-
## Related pages
|
|
78
|
-
|
|
79
|
-
- [Manifest fields](./manifest-fields.md) for schemas, homes, visibility, and strict slots.
|
|
80
|
-
- [Boards and topology](./boards-and-topology.md) for board layouts and tiled IDs.
|
|
81
|
-
- [Game contract](./game-contract.md) for binding the manifest into reducer state.
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# Public package imports
|
|
2
|
-
|
|
3
|
-
Which Dreamboard packages game authors should import.
|
|
4
|
-
|
|
5
|
-
Dreamboard keeps the author-facing package surface narrow. Prefer generated
|
|
6
|
-
workspace contracts for game-specific typing and package primitives for generic
|
|
7
|
-
runtime or visuals.
|
|
8
|
-
|
|
9
|
-
## Package roles
|
|
10
|
-
|
|
11
|
-
| Surface | Role |
|
|
12
|
-
| --- | --- |
|
|
13
|
-
| `@dreamboard/app-sdk/reducer` | Public reducer authoring API. |
|
|
14
|
-
| `@dreamboard/ui-sdk` | Public React runtime hooks, primitives, themes, and generic components. |
|
|
15
|
-
| `@dreamboard/ui-sdk/defaults` | Default UI wrappers exported from `ui-sdk`; `@dreamboard/ui-defaults` is retired. |
|
|
16
|
-
| `@dreamboard/ui-contract` | Generated per-workspace alias backed by `shared/generated/ui-contract.ts`, not an npm package. |
|
|
17
|
-
| `@dreamboard/testing` | Public reducer-native testing helpers used by generated `test/testing-types.ts`. |
|
|
18
|
-
| `@dreamboard/api-client` | Generated public API client used by tooling and integrations. |
|
|
19
|
-
| `@dreamboard/sdk-types` | Manifest and authoring types shared by generated code. |
|
|
20
|
-
| `@dreamboard/workspace-codegen` | Internal generator package used by the CLI. |
|
|
21
|
-
|
|
22
|
-
## Authored reducer code
|
|
23
|
-
|
|
24
|
-
```ts
|
|
25
|
-
import {
|
|
26
|
-
defineGame,
|
|
27
|
-
defineInteraction,
|
|
28
|
-
definePhase,
|
|
29
|
-
formInput,
|
|
30
|
-
} from "@dreamboard/app-sdk/reducer";
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Authored UI code
|
|
34
|
-
|
|
35
|
-
```tsx
|
|
36
|
-
import {
|
|
37
|
-
Interaction,
|
|
38
|
-
PromptInbox,
|
|
39
|
-
Zone,
|
|
40
|
-
useBoardInteractions,
|
|
41
|
-
useGameView,
|
|
42
|
-
useInteractionByKey,
|
|
43
|
-
} from "@dreamboard/ui-contract";
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Use `@dreamboard/ui-sdk` for generic components and runtime helpers:
|
|
47
|
-
|
|
48
|
-
```tsx
|
|
49
|
-
import { Card, HexGrid, ResourceCounter, ToastProvider } from "@dreamboard/ui-sdk";
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Use `@dreamboard/ui-sdk/defaults` when you want styled package-owned wrappers:
|
|
53
|
-
|
|
54
|
-
```tsx
|
|
55
|
-
import { DefaultPromptInbox, GameLayout } from "@dreamboard/ui-sdk/defaults";
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Do not import generated files by relative path from authored UI unless you are
|
|
59
|
-
inside generated test support. `@dreamboard/ui-contract` is the stable alias.
|
|
60
|
-
|
|
61
|
-
## Testing code
|
|
62
|
-
|
|
63
|
-
Use the generated testing contract:
|
|
64
|
-
|
|
65
|
-
```ts
|
|
66
|
-
import { defineScenario } from "../testing-types";
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
Generated contracts keep test params aligned with reducer inputs.
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
# Phases
|
|
2
|
-
|
|
3
|
-
Use definePhase to model game-flow states, actors, interactions, effects, stages, zones, and card actions.
|
|
4
|
-
|
|
5
|
-
A phase is a named state in the game flow. Phases are where reducers expose player interactions, automatic resolution, prompts, effects, zones, and card actions.
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
export const playerTurn = definePhase<GameContract>()({
|
|
9
|
-
kind: "player",
|
|
10
|
-
state: playerTurnPhaseStateSchema,
|
|
11
|
-
initialState: () => ({ step: "roll", diceRolled: false }),
|
|
12
|
-
enter({ state, accept, ops, q }) {
|
|
13
|
-
const activePlayer = state.flow.activePlayers[0] ?? q.player.order()[0]!;
|
|
14
|
-
return accept(pipe(state, ops.setActivePlayers([activePlayer])));
|
|
15
|
-
},
|
|
16
|
-
actor: ({ state }) => state.flow.activePlayers,
|
|
17
|
-
interactions: {
|
|
18
|
-
rollDice,
|
|
19
|
-
endTurn,
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Organize large phases
|
|
25
|
-
|
|
26
|
-
A single `app/phases/player-turn.ts` file is fine while the phase is small.
|
|
27
|
-
Once it has several action families, shared input/presentation helpers, card
|
|
28
|
-
actions, or grows past roughly 250-300 lines, move it into a phase folder and
|
|
29
|
-
split by game concept:
|
|
30
|
-
|
|
31
|
-
```txt
|
|
32
|
-
app/phases/player-turn/
|
|
33
|
-
index.ts # definePhase assembly only
|
|
34
|
-
state.ts # phase-local constants and types
|
|
35
|
-
inputs.ts # shared form inputs, targets, and presentation helpers
|
|
36
|
-
build.ts # build interactions
|
|
37
|
-
trade.ts # trade interactions and prompt lifecycle
|
|
38
|
-
dev-cards.ts # card actions
|
|
39
|
-
end-turn.ts # end-turn interaction
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Keep `index.ts` as the table of contents. It should import interactions and
|
|
43
|
-
card actions, register them in `definePhase`, and export only the phase plus
|
|
44
|
-
any stable test-facing schemas. Put reducer bodies in neighboring concept
|
|
45
|
-
files.
|
|
46
|
-
|
|
47
|
-
Do not split by reducer callback shape. Files named `validate.ts`,
|
|
48
|
-
`reduce.ts`, or `schemas.ts` usually force readers to jump across files to
|
|
49
|
-
understand one move. Prefer domain concepts such as build, trade, scoring,
|
|
50
|
-
discard, or dev cards.
|
|
51
|
-
|
|
52
|
-
## Phase fields
|
|
53
|
-
|
|
54
|
-
| Field | Purpose |
|
|
55
|
-
| -------------- | --------------------------------------------------------------------------------------------- |
|
|
56
|
-
| `kind` | `"player"` waits for player input; `"simultaneousPlayer"` waits for sealed player submissions; `"auto"` resolves through reducer logic. |
|
|
57
|
-
| `state` | Zod schema for phase-local state. |
|
|
58
|
-
| `initialState` | Optional initializer for phase-local state. |
|
|
59
|
-
| `enter` | Optional hook that runs when the phase is entered. |
|
|
60
|
-
| `actor` | Default actor selector for interactions in this phase. |
|
|
61
|
-
| `actors` | Actor selector for simultaneous-player submissions. |
|
|
62
|
-
| `submit` | Canonical sealed submission interaction for `kind: "simultaneousPlayer"`. |
|
|
63
|
-
| `resolve` | Batch resolver for a simultaneous phase after all actors submit. |
|
|
64
|
-
| `effects` | Registered engine-side effects dispatched through `fx.effect`. |
|
|
65
|
-
| `interactions` | Player commands and prompts authored with `defineInteraction`. |
|
|
66
|
-
| `stages` | First-match sub-phase selectors and allow lists. |
|
|
67
|
-
| `zones` | Declarative cardholder projections for generated `Zone` primitives. |
|
|
68
|
-
| `cardActions` | Card-instance actions authored with `defineCardAction`. |
|
|
69
|
-
|
|
70
|
-
## Player phases
|
|
71
|
-
|
|
72
|
-
Use `kind: "player"` when the runtime should wait for a player or prompt recipient to submit an interaction.
|
|
73
|
-
|
|
74
|
-
Actor selection is explicit. A phase-level `actor` is usually enough for ordinary turn-taking:
|
|
75
|
-
|
|
76
|
-
```ts
|
|
77
|
-
actor: ({ state }) => state.flow.activePlayers;
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Specific interactions can override `actor`. Prompt-style interactions can use `to` to address one or more players.
|
|
81
|
-
|
|
82
|
-
## Simultaneous player phases
|
|
83
|
-
|
|
84
|
-
Use `kind: "simultaneousPlayer"` when multiple players should choose at the same time, such as card passing in Sushi Go, choosing cards in Hearts, or any other hidden commitment step.
|
|
85
|
-
|
|
86
|
-
The runtime stores each player's `submit` params as sealed SDK-owned state. Individual submissions do not mutate game state. Once every actor has submitted, the phase-level `resolve` callback receives the full submission batch and applies one deterministic state change.
|
|
87
|
-
|
|
88
|
-
```ts
|
|
89
|
-
export const chooseCards = definePhase<GameContract>()({
|
|
90
|
-
kind: "simultaneousPlayer",
|
|
91
|
-
state: chooseCardsPhaseStateSchema,
|
|
92
|
-
actors: ({ q }) => q.player.order(),
|
|
93
|
-
submit: {
|
|
94
|
-
inputs: {
|
|
95
|
-
cardId: formInput.choice({
|
|
96
|
-
choices: [
|
|
97
|
-
{ value: "card-a", label: "Card A" },
|
|
98
|
-
{ value: "card-b", label: "Card B" },
|
|
99
|
-
],
|
|
100
|
-
}),
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
resolve({ state, submissions, accept, ops }) {
|
|
104
|
-
// Runs once, after every actor has submitted.
|
|
105
|
-
const revealed = Object.values(submissions).map((submission) => ({
|
|
106
|
-
playerId: submission.playerId,
|
|
107
|
-
cardId: submission.params.cardId,
|
|
108
|
-
}));
|
|
109
|
-
|
|
110
|
-
return accept(
|
|
111
|
-
pipe(state, ops.patchPublicState({ revealedChoices: revealed })),
|
|
112
|
-
);
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
By default each actor can submit once. Set `canResubmit: true` when players may replace their sealed choice before the final actor submits.
|
|
118
|
-
|
|
119
|
-
Use normal `interactions` for side actions that should mutate immediately, and use `to` prompts for addressed interrupts. The `submit` interaction is the barrier: the SDK validates it, hides it from players who already submitted, keeps choices hidden from other seats, and calls `resolve` only when the batch is complete.
|
|
120
|
-
|
|
121
|
-
## Auto phases
|
|
122
|
-
|
|
123
|
-
Use `kind: "auto"` for deterministic resolution steps: shuffle startup, deal cards, score cleanup, or final winner calculation.
|
|
124
|
-
|
|
125
|
-
Auto phases often do their work in a stage `onEnter` hook and immediately transition:
|
|
126
|
-
|
|
127
|
-
```ts
|
|
128
|
-
stages: {
|
|
129
|
-
shuffle: definePhaseStage<GameContract, typeof phaseState>()({
|
|
130
|
-
allow: [],
|
|
131
|
-
onEnter({ state, accept, fx }) {
|
|
132
|
-
return accept(state, [
|
|
133
|
-
fx.effect(shuffleDeck, { zoneId: "draw" }),
|
|
134
|
-
fx.transition("deal"),
|
|
135
|
-
]);
|
|
136
|
-
},
|
|
137
|
-
}),
|
|
138
|
-
}
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
## Keep phase state narrow
|
|
142
|
-
|
|
143
|
-
Put temporary, phase-specific facts in `state.phase`: current step, pending discard list, selected trade partner, or "has rolled this turn".
|
|
144
|
-
|
|
145
|
-
Put persistent cross-phase facts in `publicState`, `privateState`, `hiddenState`, or the table. If a value is recomputable from table state, prefer a [Derived value](./derived-values.md) instead of storing a mirror.
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# Prompts and choices
|
|
2
|
-
|
|
3
|
-
Render addressed prompt interactions with generated Prompt primitives.
|
|
4
|
-
|
|
5
|
-
Prompts are ordinary interactions with a `promptInput` collector and `to`
|
|
6
|
-
addressees. Render them with generated prompt primitives.
|
|
7
|
-
|
|
8
|
-
```tsx
|
|
9
|
-
import { PromptInbox } from "@dreamboard/ui-contract";
|
|
10
|
-
|
|
11
|
-
<PromptInbox.Root>
|
|
12
|
-
<PromptInbox.Empty>No prompts</PromptInbox.Empty>
|
|
13
|
-
<PromptInbox.Items />
|
|
14
|
-
</PromptInbox.Root>
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
For custom prompt chrome:
|
|
18
|
-
|
|
19
|
-
```tsx
|
|
20
|
-
import { Prompt } from "@dreamboard/ui-contract";
|
|
21
|
-
|
|
22
|
-
<Prompt.Root interaction="playerTurn.respondToTrade">
|
|
23
|
-
<Prompt.Title />
|
|
24
|
-
<Prompt.Message />
|
|
25
|
-
<Prompt.Options />
|
|
26
|
-
</Prompt.Root>
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
`Prompt.Option` submits the prompt response through the typed input from the
|
|
30
|
-
descriptor. The reducer controls recipients, options, availability, and
|
|
31
|
-
validation. React controls copy layout, dialog shells, and visual treatment.
|
|
32
|
-
|
|
33
|
-
Use `useInteractionByKey` only when the prompt is part of a bespoke local
|
|
34
|
-
component that needs draft state or a custom submit sequence.
|
|
35
|
-
|
|
36
|
-
## Dialog prompts
|
|
37
|
-
|
|
38
|
-
Use generated `PromptDialogHost` when you want package behavior with local
|
|
39
|
-
dialog chrome:
|
|
40
|
-
|
|
41
|
-
```tsx
|
|
42
|
-
import { PromptDialogHost } from "@dreamboard/ui-contract";
|
|
43
|
-
|
|
44
|
-
<PromptDialogHost
|
|
45
|
-
className="trade-dialog"
|
|
46
|
-
onSubmitError={showToast}
|
|
47
|
-
renderBody={({ prompt }) => (
|
|
48
|
-
<TradeOfferSummary prompt={prompt} />
|
|
49
|
-
)}
|
|
50
|
-
/>;
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Star Settlers uses this pattern for trade prompts: the reducer still owns
|
|
54
|
-
recipients and accepted options, while React owns the modal body and error
|
|
55
|
-
presentation.
|