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.
Files changed (186) hide show
  1. package/dist/{chunk-EYYWGWTO.js → chunk-2RCUHMGL.js} +343 -1911
  2. package/dist/chunk-2RCUHMGL.js.map +1 -0
  3. package/dist/{chunk-MOVHYB6E.js → chunk-GN7232BY.js} +1025 -695
  4. package/dist/chunk-GN7232BY.js.map +1 -0
  5. package/dist/{chunk-BMYC6772.js → chunk-H3O43F5P.js} +9765 -3068
  6. package/dist/chunk-H3O43F5P.js.map +1 -0
  7. package/dist/dev-host/dev-api-proxy-plugin.ts +330 -0
  8. package/dist/dev-host/dev-diagnostics.ts +62 -0
  9. package/dist/dev-host/dev-fallback-stylesheet.ts +50 -0
  10. package/dist/dev-host/dev-host-controller.ts +686 -0
  11. package/dist/dev-host/dev-host-player-query.ts +17 -0
  12. package/dist/dev-host/dev-host-session-transport.ts +52 -0
  13. package/dist/dev-host/dev-host-storage.ts +56 -0
  14. package/dist/dev-host/dev-log-relay-plugin.ts +469 -0
  15. package/dist/dev-host/dev-runtime-config.ts +14 -0
  16. package/dist/dev-host/dev-runtime-platform.ts +419 -0
  17. package/dist/dev-host/dev-virtual-modules-plugin.ts +63 -0
  18. package/dist/dev-host/host-main.css +182 -0
  19. package/dist/dev-host/host-main.tsx +754 -0
  20. package/dist/dev-host/index.html +56 -0
  21. package/dist/dev-host/plugin-main.ts +55 -0
  22. package/dist/dev-host/plugin.html +24 -0
  23. package/dist/dev-host/start-dev-server.ts +138 -0
  24. package/dist/dev-host/virtual-modules.d.ts +27 -0
  25. package/dist/dist-FEPN3BDN.js +16543 -0
  26. package/dist/dist-FEPN3BDN.js.map +1 -0
  27. package/dist/{dist-WJRJNFLI.js → dist-FRURQI7Q.js} +4 -2
  28. package/dist/index.js +3 -3
  29. package/dist/internal.js +159 -124
  30. package/dist/internal.js.map +1 -1
  31. package/dist/runtime-packages/tailwind-config/shared-styles.css +146 -0
  32. package/dist/runtime-packages/ui/src/components/.gitkeep +0 -0
  33. package/dist/runtime-packages/ui/src/components/accordion.tsx +66 -0
  34. package/dist/runtime-packages/ui/src/components/ai-elements/actions.tsx +65 -0
  35. package/dist/runtime-packages/ui/src/components/ai-elements/artifact.tsx +147 -0
  36. package/dist/runtime-packages/ui/src/components/ai-elements/branch.tsx +215 -0
  37. package/dist/runtime-packages/ui/src/components/ai-elements/canvas.tsx +22 -0
  38. package/dist/runtime-packages/ui/src/components/ai-elements/chain-of-thought.tsx +228 -0
  39. package/dist/runtime-packages/ui/src/components/ai-elements/code-block.tsx +179 -0
  40. package/dist/runtime-packages/ui/src/components/ai-elements/confirmation.tsx +158 -0
  41. package/dist/runtime-packages/ui/src/components/ai-elements/connection.tsx +28 -0
  42. package/dist/runtime-packages/ui/src/components/ai-elements/context.tsx +408 -0
  43. package/dist/runtime-packages/ui/src/components/ai-elements/controls.tsx +18 -0
  44. package/dist/runtime-packages/ui/src/components/ai-elements/conversation.tsx +97 -0
  45. package/dist/runtime-packages/ui/src/components/ai-elements/edge.tsx +140 -0
  46. package/dist/runtime-packages/ui/src/components/ai-elements/image.tsx +24 -0
  47. package/dist/runtime-packages/ui/src/components/ai-elements/inline-citation.tsx +287 -0
  48. package/dist/runtime-packages/ui/src/components/ai-elements/loader.tsx +96 -0
  49. package/dist/runtime-packages/ui/src/components/ai-elements/message.tsx +463 -0
  50. package/dist/runtime-packages/ui/src/components/ai-elements/node.tsx +71 -0
  51. package/dist/runtime-packages/ui/src/components/ai-elements/open-in-chat.tsx +365 -0
  52. package/dist/runtime-packages/ui/src/components/ai-elements/panel.tsx +15 -0
  53. package/dist/runtime-packages/ui/src/components/ai-elements/plan.tsx +142 -0
  54. package/dist/runtime-packages/ui/src/components/ai-elements/prompt-input.tsx +1380 -0
  55. package/dist/runtime-packages/ui/src/components/ai-elements/queue.tsx +274 -0
  56. package/dist/runtime-packages/ui/src/components/ai-elements/reasoning.tsx +182 -0
  57. package/dist/runtime-packages/ui/src/components/ai-elements/response.tsx +22 -0
  58. package/dist/runtime-packages/ui/src/components/ai-elements/shimmer.tsx +64 -0
  59. package/dist/runtime-packages/ui/src/components/ai-elements/sources.tsx +77 -0
  60. package/dist/runtime-packages/ui/src/components/ai-elements/suggestion.tsx +53 -0
  61. package/dist/runtime-packages/ui/src/components/ai-elements/task.tsx +87 -0
  62. package/dist/runtime-packages/ui/src/components/ai-elements/tool.tsx +165 -0
  63. package/dist/runtime-packages/ui/src/components/ai-elements/toolbar.tsx +16 -0
  64. package/dist/runtime-packages/ui/src/components/ai-elements/web-preview.tsx +263 -0
  65. package/dist/runtime-packages/ui/src/components/alert-dialog.tsx +157 -0
  66. package/dist/runtime-packages/ui/src/components/alert.tsx +66 -0
  67. package/dist/runtime-packages/ui/src/components/avatar.tsx +53 -0
  68. package/dist/runtime-packages/ui/src/components/badge.tsx +46 -0
  69. package/dist/runtime-packages/ui/src/components/button-group.tsx +83 -0
  70. package/dist/runtime-packages/ui/src/components/button.tsx +65 -0
  71. package/dist/runtime-packages/ui/src/components/card.tsx +92 -0
  72. package/dist/runtime-packages/ui/src/components/carousel.tsx +241 -0
  73. package/dist/runtime-packages/ui/src/components/collapsible.tsx +33 -0
  74. package/dist/runtime-packages/ui/src/components/command.tsx +184 -0
  75. package/dist/runtime-packages/ui/src/components/context-menu.tsx +252 -0
  76. package/dist/runtime-packages/ui/src/components/counter.tsx +11 -0
  77. package/dist/runtime-packages/ui/src/components/dialog.tsx +146 -0
  78. package/dist/runtime-packages/ui/src/components/drawer.tsx +132 -0
  79. package/dist/runtime-packages/ui/src/components/dropdown-menu.tsx +257 -0
  80. package/dist/runtime-packages/ui/src/components/form.tsx +168 -0
  81. package/dist/runtime-packages/ui/src/components/header.tsx +13 -0
  82. package/dist/runtime-packages/ui/src/components/hover-card.tsx +44 -0
  83. package/dist/runtime-packages/ui/src/components/input-group.tsx +178 -0
  84. package/dist/runtime-packages/ui/src/components/input.tsx +21 -0
  85. package/dist/runtime-packages/ui/src/components/item.tsx +193 -0
  86. package/dist/runtime-packages/ui/src/components/label.tsx +24 -0
  87. package/dist/runtime-packages/ui/src/components/navigation-menu.tsx +168 -0
  88. package/dist/runtime-packages/ui/src/components/popover.tsx +55 -0
  89. package/dist/runtime-packages/ui/src/components/progress.tsx +31 -0
  90. package/dist/runtime-packages/ui/src/components/radio-group.tsx +45 -0
  91. package/dist/runtime-packages/ui/src/components/resizable.tsx +56 -0
  92. package/dist/runtime-packages/ui/src/components/scroll-area.tsx +58 -0
  93. package/dist/runtime-packages/ui/src/components/select.tsx +187 -0
  94. package/dist/runtime-packages/ui/src/components/separator.tsx +28 -0
  95. package/dist/runtime-packages/ui/src/components/skeleton.tsx +13 -0
  96. package/dist/runtime-packages/ui/src/components/sonner.tsx +25 -0
  97. package/dist/runtime-packages/ui/src/components/spinner.tsx +16 -0
  98. package/dist/runtime-packages/ui/src/components/switch.tsx +31 -0
  99. package/dist/runtime-packages/ui/src/components/table.tsx +137 -0
  100. package/dist/runtime-packages/ui/src/components/tabs.tsx +74 -0
  101. package/dist/runtime-packages/ui/src/components/textarea.tsx +23 -0
  102. package/dist/runtime-packages/ui/src/components/theme-provider.tsx +73 -0
  103. package/dist/runtime-packages/ui/src/components/tooltip.tsx +61 -0
  104. package/dist/runtime-packages/ui/src/components/ui/file-upload.tsx +195 -0
  105. package/dist/runtime-packages/ui/src/hooks/.gitkeep +0 -0
  106. package/dist/runtime-packages/ui/src/index.ts +68 -0
  107. package/dist/runtime-packages/ui/src/lib/utils.ts +6 -0
  108. package/dist/runtime-packages/ui-host-runtime/src/actor-principal.ts +68 -0
  109. package/dist/runtime-packages/ui-host-runtime/src/components/host-controls.tsx +359 -0
  110. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback-toaster.tsx +274 -0
  111. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback.tsx +214 -0
  112. package/dist/runtime-packages/ui-host-runtime/src/components/host-session-metadata.tsx +135 -0
  113. package/dist/runtime-packages/ui-host-runtime/src/components/index.ts +5 -0
  114. package/dist/runtime-packages/ui-host-runtime/src/components/perf-overlay.tsx +194 -0
  115. package/dist/runtime-packages/ui-host-runtime/src/host-controls.tsx +1 -0
  116. package/dist/runtime-packages/ui-host-runtime/src/host-feedback.tsx +1 -0
  117. package/dist/runtime-packages/ui-host-runtime/src/host-session-transport.ts +162 -0
  118. package/dist/runtime-packages/ui-host-runtime/src/index.ts +2 -0
  119. package/dist/runtime-packages/ui-host-runtime/src/logger.ts +11 -0
  120. package/dist/runtime-packages/ui-host-runtime/src/perf.ts +253 -0
  121. package/dist/runtime-packages/ui-host-runtime/src/plugin-bridge.ts +195 -0
  122. package/dist/runtime-packages/ui-host-runtime/src/plugin-health-check.ts +138 -0
  123. package/dist/runtime-packages/ui-host-runtime/src/plugin-messages.ts +159 -0
  124. package/dist/runtime-packages/ui-host-runtime/src/plugin-session-gateway.ts +524 -0
  125. package/dist/runtime-packages/ui-host-runtime/src/runtime/index.ts +12 -0
  126. package/dist/runtime-packages/ui-host-runtime/src/screenshot/projection-to-snapshot.ts +122 -0
  127. package/dist/runtime-packages/ui-host-runtime/src/screenshot/static-store-api.ts +26 -0
  128. package/dist/runtime-packages/ui-host-runtime/src/session-ingress-controller.ts +477 -0
  129. package/dist/runtime-packages/ui-host-runtime/src/session-ingress.ts +209 -0
  130. package/dist/runtime-packages/ui-host-runtime/src/session-live-runtime.ts +112 -0
  131. package/dist/runtime-packages/ui-host-runtime/src/session-model.ts +318 -0
  132. package/dist/runtime-packages/ui-host-runtime/src/session-projection.ts +211 -0
  133. package/dist/runtime-packages/ui-host-runtime/src/session-state-reducer.ts +814 -0
  134. package/dist/runtime-packages/ui-host-runtime/src/sse-manager.ts +334 -0
  135. package/dist/runtime-packages/ui-host-runtime/src/unified-session-store.ts +180 -0
  136. package/dist/scaffold/assets/static/app/tsconfig.framework.json +3 -1
  137. package/dist/scaffold/assets/static/ui/tsconfig.framework.json +7 -19
  138. package/package.json +52 -17
  139. package/skills/dreamboard/SKILL.md +41 -75
  140. package/LICENSE +0 -89
  141. package/NOTICE +0 -1
  142. package/dist/chunk-BMYC6772.js.map +0 -1
  143. package/dist/chunk-EYYWGWTO.js.map +0 -1
  144. package/dist/chunk-MOVHYB6E.js.map +0 -1
  145. package/dist/scaffold/assets/static/ui/App.tsx +0 -22
  146. package/dist/src-CUL7EGGG.js +0 -634
  147. package/dist/src-CUL7EGGG.js.map +0 -1
  148. package/skills/dreamboard/references/authoring-lifecycle.md +0 -102
  149. package/skills/dreamboard/references/board-surfaces.md +0 -36
  150. package/skills/dreamboard/references/board-topology.md +0 -443
  151. package/skills/dreamboard/references/boards-and-topology.md +0 -100
  152. package/skills/dreamboard/references/card-actions.md +0 -107
  153. package/skills/dreamboard/references/cli.md +0 -120
  154. package/skills/dreamboard/references/core-concepts.md +0 -514
  155. package/skills/dreamboard/references/custom-renderers.md +0 -26
  156. package/skills/dreamboard/references/derived-values.md +0 -55
  157. package/skills/dreamboard/references/effects.md +0 -111
  158. package/skills/dreamboard/references/game-contract.md +0 -89
  159. package/skills/dreamboard/references/game-definition.md +0 -89
  160. package/skills/dreamboard/references/game-shell.md +0 -80
  161. package/skills/dreamboard/references/hand-surfaces.md +0 -33
  162. package/skills/dreamboard/references/index.md +0 -112
  163. package/skills/dreamboard/references/inputs-and-targets.md +0 -160
  164. package/skills/dreamboard/references/interactions.md +0 -158
  165. package/skills/dreamboard/references/manifest-fields.md +0 -137
  166. package/skills/dreamboard/references/manifest.md +0 -81
  167. package/skills/dreamboard/references/package-surfaces.md +0 -69
  168. package/skills/dreamboard/references/phases.md +0 -145
  169. package/skills/dreamboard/references/prompts-and-choices.md +0 -55
  170. package/skills/dreamboard/references/quickstart.md +0 -71
  171. package/skills/dreamboard/references/rule-authoring.md +0 -144
  172. package/skills/dreamboard/references/setup-bootstrap.md +0 -78
  173. package/skills/dreamboard/references/stages-and-zones.md +0 -59
  174. package/skills/dreamboard/references/static-views.md +0 -67
  175. package/skills/dreamboard/references/table-queries-and-ops.md +0 -103
  176. package/skills/dreamboard/references/testing-bases.md +0 -147
  177. package/skills/dreamboard/references/testing-generated-contracts.md +0 -142
  178. package/skills/dreamboard/references/testing-runtime-assertions.md +0 -124
  179. package/skills/dreamboard/references/testing-scenarios.md +0 -148
  180. package/skills/dreamboard/references/testing-ui-tests.md +0 -174
  181. package/skills/dreamboard/references/testing.md +0 -161
  182. package/skills/dreamboard/references/ui-architecture.md +0 -137
  183. package/skills/dreamboard/references/ui-components.md +0 -34
  184. package/skills/dreamboard/references/views.md +0 -72
  185. package/skills/dreamboard/references/workspace-layout.md +0 -136
  186. /package/dist/{dist-WJRJNFLI.js.map → dist-FRURQI7Q.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../packages/testing/src/definitions.ts","../../../packages/testing/src/create-expect-api.ts","../../../packages/testing/src/create-test-runtime.ts"],"sourcesContent":["export type TestRunner = \"reducer\" | \"embedded\" | \"browser\";\n\nexport type InteractionDescriptorLike = {\n interactionId?: string;\n surface?: string;\n kind?: string;\n available?: boolean;\n unavailableReason?: string;\n context?: {\n to?: string;\n };\n} & Record<string, unknown>;\n\nexport type SnapshotMatcherHandler = (\n name: string | undefined,\n actual: unknown,\n) => void;\n\nexport type RejectionExpectation = {\n errorCode?: string;\n message?: string | RegExp;\n};\n\nexport type ExpectMatchers = {\n toBe: (expected: unknown) => void;\n toEqual: (expected: unknown) => void;\n toMatchObject: (expected: Record<string, unknown>) => void;\n toBeDefined: () => void;\n toBeUndefined: () => void;\n toBeNull: () => void;\n toContain: (expected: unknown) => void;\n toContainEqual: (expected: unknown) => void;\n toHaveLength: (expected: number) => void;\n toBeGreaterThan: (expected: number) => void;\n toBeGreaterThanOrEqual: (expected: number) => void;\n toThrow: (predicate?: string | RegExp | ((error: Error) => boolean)) => void;\n toMatchSnapshot: (filename?: string) => void;\n toRejectWith: (expected: RejectionExpectation) => Promise<void>;\n toHaveInteraction: (\n interactionId: string,\n opts?: Partial<InteractionDescriptorLike>,\n ) => void;\n toBeGatedBy: (reason: string, opts?: { interactionId?: string }) => void;\n toBeActiveFor: (playerId: string, opts?: { interactionId?: string }) => void;\n not: {\n toHaveInteraction: (interactionId: string) => void;\n };\n};\n\nexport type ExpectFn = (actual: unknown) => ExpectMatchers;\n\nexport interface BaseContext<PlayerId extends string = string> {\n game: {\n start(): Promise<void>;\n submit(\n playerId: PlayerId,\n interactionId: string,\n params?: unknown,\n ): Promise<void>;\n };\n players(): readonly PlayerId[];\n seat(index: number): PlayerId;\n}\n\nexport interface SharedScenarioContext<\n PlayerId extends string = string,\n StateName extends string = string,\n View = unknown,\n Descriptor extends InteractionDescriptorLike = InteractionDescriptorLike,\n> extends BaseContext<PlayerId> {\n state(): StateName;\n view(playerId: PlayerId): View;\n interactions(playerId: PlayerId): readonly Descriptor[];\n expect: ExpectFn;\n}\n\nexport interface BaseDefinition {\n id: string;\n seed?: number;\n players?: number;\n setupProfileId?: string | null;\n extends?: string;\n setup: (ctx: BaseContext) => void | Promise<void>;\n}\n\nexport interface ScenarioDefinition<\n Runners extends readonly TestRunner[] = readonly [\"reducer\"],\n PhaseName extends string = string,\n StageName extends string = string,\n> {\n id: string;\n description?: string;\n from: string;\n runners?: Runners;\n phase?: PhaseName;\n stage?: StageName;\n when: (ctx: SharedScenarioContext) => void | Promise<void>;\n then: (ctx: SharedScenarioContext) => void | Promise<void>;\n}\n\nexport function defineBase<const Definition extends BaseDefinition>(\n definition: Definition,\n): Definition {\n return definition;\n}\n\nexport function defineScenario<\n const Runners extends readonly TestRunner[] = readonly [\"reducer\"],\n const PhaseName extends string = string,\n const StageName extends string = string,\n>(\n definition: ScenarioDefinition<Runners, PhaseName, StageName>,\n): ScenarioDefinition<Runners, PhaseName, StageName> {\n return definition;\n}\n","import { isDeepStrictEqual } from \"node:util\";\nimport type {\n ExpectFn,\n ExpectMatchers,\n InteractionDescriptorLike,\n RejectionExpectation,\n SnapshotMatcherHandler,\n} from \"./definitions.js\";\n\ntype CreateExpectApiOptions = {\n matchSnapshot?: SnapshotMatcherHandler;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction matchPartial(\n actual: unknown,\n expected: unknown,\n path: string = \"value\",\n): string | null {\n if (!isRecord(expected)) {\n return isDeepStrictEqual(actual, expected)\n ? null\n : `${path} does not match`;\n }\n if (!isRecord(actual)) {\n return `${path} is not an object`;\n }\n for (const [key, expectedValue] of Object.entries(expected)) {\n const actualValue = actual[key];\n if (!(key in actual)) {\n return `${path}.${key} is missing`;\n }\n const mismatch = matchPartial(actualValue, expectedValue, `${path}.${key}`);\n if (mismatch) {\n return mismatch;\n }\n }\n return null;\n}\n\nfunction asDescriptorList(actual: unknown): InteractionDescriptorLike[] {\n if (!Array.isArray(actual)) {\n throw new Error(\"Expected interaction descriptor array.\");\n }\n return actual as InteractionDescriptorLike[];\n}\n\nfunction findInteraction(\n descriptors: readonly InteractionDescriptorLike[],\n interactionId: string,\n): InteractionDescriptorLike | null {\n return (\n descriptors.find(\n (descriptor) => descriptor.interactionId === interactionId,\n ) ?? null\n );\n}\n\nfunction assertDescriptorMatches(\n descriptor: InteractionDescriptorLike,\n opts: Partial<InteractionDescriptorLike> | undefined,\n): void {\n if (!opts) {\n return;\n }\n const mismatch = matchPartial(descriptor, opts, \"interaction\");\n if (mismatch) {\n throw new Error(mismatch);\n }\n}\n\nfunction createSubmissionErrorMatcher(\n actual: unknown,\n expected: RejectionExpectation,\n): Promise<void> {\n const resolvePromise = (): Promise<unknown> => {\n if (typeof actual === \"function\") {\n return Promise.resolve().then(() => (actual as () => unknown)());\n }\n return Promise.resolve(actual);\n };\n\n return resolvePromise()\n .then(() => {\n throw new Error(\"Expected promise to reject.\");\n })\n .catch((error: unknown) => {\n if (!(error instanceof Error)) {\n throw new Error(\"Expected rejection to be an Error.\");\n }\n if (\n expected.errorCode !== undefined &&\n (error as Error & { errorCode?: string }).errorCode !==\n expected.errorCode\n ) {\n throw new Error(\n `Expected rejection errorCode '${expected.errorCode}', received '${\n (error as Error & { errorCode?: string }).errorCode ?? \"undefined\"\n }'.`,\n );\n }\n if (\n typeof expected.message === \"string\" &&\n error.message !== expected.message\n ) {\n throw new Error(\n `Expected rejection message '${expected.message}', received '${error.message}'.`,\n );\n }\n if (\n expected.message instanceof RegExp &&\n !expected.message.test(error.message)\n ) {\n throw new Error(\n `Expected rejection message '${error.message}' to match ${String(expected.message)}.`,\n );\n }\n });\n}\n\nfunction assertLength(actual: unknown, expected: number): void {\n if (\n actual === null ||\n actual === undefined ||\n typeof (actual as { length?: unknown }).length !== \"number\"\n ) {\n throw new Error(\"toHaveLength expects a value with a numeric length.\");\n }\n const length = (actual as { length: number }).length;\n if (length !== expected) {\n throw new Error(`Expected length ${expected}, received ${length}.`);\n }\n}\n\nfunction assertThrown(\n actual: unknown,\n predicate?: string | RegExp | ((error: Error) => boolean),\n): void {\n if (typeof actual !== \"function\") {\n throw new Error(\"toThrow expects a function.\");\n }\n try {\n (actual as () => unknown)();\n } catch (error) {\n if (!(error instanceof Error)) {\n throw new Error(\"Thrown value is not an Error.\");\n }\n if (predicate === undefined) {\n return;\n }\n if (typeof predicate === \"string\" && error.message !== predicate) {\n throw new Error(\n `Expected thrown message '${predicate}', received '${error.message}'.`,\n );\n }\n if (predicate instanceof RegExp && !predicate.test(error.message)) {\n throw new Error(\n `Expected thrown message '${error.message}' to match ${String(predicate)}.`,\n );\n }\n if (typeof predicate === \"function\" && !predicate(error)) {\n throw new Error(\"Thrown error did not satisfy predicate.\");\n }\n return;\n }\n throw new Error(\"Expected function to throw.\");\n}\n\nexport function createExpectApi(\n options: CreateExpectApiOptions = {},\n): ExpectFn {\n const buildMatchers = (actual: unknown): ExpectMatchers => ({\n toBe: (expected: unknown) => {\n if (actual !== expected) {\n throw new Error(\n `Expected '${String(actual)}' to be '${String(expected)}'.`,\n );\n }\n },\n toEqual: (expected: unknown) => {\n if (!isDeepStrictEqual(actual, expected)) {\n throw new Error(\"Expected values to be deeply equal.\");\n }\n },\n toMatchObject: (expected: Record<string, unknown>) => {\n const mismatch = matchPartial(actual, expected);\n if (mismatch) {\n throw new Error(mismatch);\n }\n },\n toBeDefined: () => {\n if (actual === undefined) {\n throw new Error(\"Expected value to be defined.\");\n }\n },\n toBeUndefined: () => {\n if (actual !== undefined) {\n throw new Error(\n `Expected value to be undefined, but received '${String(actual)}'.`,\n );\n }\n },\n toBeNull: () => {\n if (actual !== null) {\n throw new Error(\n `Expected value to be null, but received '${String(actual)}'.`,\n );\n }\n },\n toContain: (expected: unknown) => {\n if (Array.isArray(actual)) {\n if (!actual.includes(expected)) {\n throw new Error(\"Expected array to contain value.\");\n }\n return;\n }\n if (typeof actual === \"string\") {\n if (!actual.includes(String(expected))) {\n throw new Error(\"Expected string to contain value.\");\n }\n return;\n }\n throw new Error(\"toContain expects an array or string actual value.\");\n },\n toContainEqual: (expected: unknown) => {\n if (!Array.isArray(actual)) {\n throw new Error(\"toContainEqual expects an array actual value.\");\n }\n if (!actual.some((value) => isDeepStrictEqual(value, expected))) {\n throw new Error(\"Expected array to contain an equal value.\");\n }\n },\n toHaveLength: (expected: number) => {\n assertLength(actual, expected);\n },\n toBeGreaterThan: (expected: number) => {\n if (typeof actual !== \"number\") {\n throw new Error(\"toBeGreaterThan expects a number actual value.\");\n }\n if (actual <= expected) {\n throw new Error(`Expected ${actual} to be > ${expected}.`);\n }\n },\n toBeGreaterThanOrEqual: (expected: number) => {\n if (typeof actual !== \"number\") {\n throw new Error(\n \"toBeGreaterThanOrEqual expects a number actual value.\",\n );\n }\n if (actual < expected) {\n throw new Error(`Expected ${actual} to be >= ${expected}.`);\n }\n },\n toThrow: (predicate) => {\n assertThrown(actual, predicate);\n },\n toMatchSnapshot: (filename) => {\n if (!options.matchSnapshot) {\n throw new Error(\n \"Snapshot matching is not configured for this expect API.\",\n );\n }\n options.matchSnapshot(filename, actual);\n },\n toRejectWith: (expected) => createSubmissionErrorMatcher(actual, expected),\n toHaveInteraction: (interactionId, opts) => {\n const descriptors = asDescriptorList(actual);\n const descriptor = findInteraction(descriptors, interactionId);\n if (!descriptor) {\n throw new Error(`Expected interaction '${interactionId}' to exist.`);\n }\n assertDescriptorMatches(descriptor, opts);\n },\n toBeGatedBy: (reason, opts) => {\n const descriptor = Array.isArray(actual)\n ? (() => {\n if (!opts?.interactionId) {\n throw new Error(\n \"toBeGatedBy on a descriptor array requires opts.interactionId.\",\n );\n }\n return findInteraction(\n asDescriptorList(actual),\n opts.interactionId,\n );\n })()\n : (actual as InteractionDescriptorLike | null);\n if (!descriptor) {\n throw new Error(\"Expected interaction descriptor to exist.\");\n }\n if (descriptor.available !== false) {\n throw new Error(\"Expected interaction to be unavailable.\");\n }\n if (descriptor.unavailableReason !== reason) {\n throw new Error(\n `Expected unavailableReason '${reason}', received '${\n descriptor.unavailableReason ?? \"undefined\"\n }'.`,\n );\n }\n },\n toBeActiveFor: (playerId, opts) => {\n const descriptor = Array.isArray(actual)\n ? (() => {\n if (!opts?.interactionId) {\n throw new Error(\n \"toBeActiveFor on a descriptor array requires opts.interactionId.\",\n );\n }\n return findInteraction(\n asDescriptorList(actual),\n opts.interactionId,\n );\n })()\n : (actual as InteractionDescriptorLike | null);\n if (!descriptor) {\n throw new Error(\"Expected interaction descriptor to exist.\");\n }\n if (descriptor.context?.to !== playerId) {\n throw new Error(\n `Expected interaction to target '${playerId}', received '${\n descriptor.context?.to ?? \"undefined\"\n }'.`,\n );\n }\n if (descriptor.available !== true) {\n throw new Error(\"Expected interaction to be available.\");\n }\n },\n not: {\n toHaveInteraction: (interactionId) => {\n const descriptors = asDescriptorList(actual);\n if (findInteraction(descriptors, interactionId)) {\n throw new Error(\n `Expected interaction '${interactionId}' to be absent.`,\n );\n }\n },\n },\n });\n\n return (actual: unknown) => buildMatchers(actual);\n}\n","import type {\n HostPlayerGameplayView,\n HostSessionContext,\n HostSessionSnapshot,\n SeatAssignment,\n} from \"@dreamboard/api-client\";\nimport type { ReducerBundleContract } from \"@dreamboard/reducer-contract/bundle\";\nimport type * as Wire from \"@dreamboard/reducer-contract/wire\";\nimport type { PluginStateSnapshot } from \"@dreamboard/ui-sdk/reducer\";\nimport type {\n PluginSessionState,\n RuntimeAPI,\n SubmissionError,\n ValidationResult,\n} from \"@dreamboard/ui-sdk\";\nimport {\n createUnifiedSessionStore,\n type GameplayViewport,\n type SessionContext,\n type SSEManagerLike,\n} from \"@dreamboard/ui-host-runtime/runtime\";\n\ntype ReducerStaticProjection = Wire.BoardStaticProjection;\ntype ReducerBundleLike = Pick<\n ReducerBundleContract,\n \"projectSeatsDynamic\" | \"projectStatic\" | \"validateInput\" | \"dispatch\"\n>;\n\ntype BaseStateArtifact = {\n snapshot: Wire.ReducerSessionState;\n fingerprint: {\n players: number;\n };\n};\n\nexport type CreateTestRuntimeOptions = {\n baseId: string;\n baseStates: Record<string, BaseStateArtifact>;\n bundle: ReducerBundleLike;\n phase?: string;\n playerIds?: readonly string[];\n sessionId?: string;\n userId?: string | null;\n gameId?: string;\n displayNameByPlayerId?: Record<string, string>;\n};\n\nexport type CreatedTestRuntime = {\n runtime: RuntimeAPI & {\n getSnapshot(): PluginStateSnapshot;\n subscribeToState(\n listener: (state: PluginStateSnapshot) => void,\n ): () => void;\n _subscribeToSessionState(\n listener: (state: PluginSessionState) => void,\n ): () => void;\n };\n getSnapshot(): PluginStateSnapshot;\n players(): readonly string[];\n seat(index: number): string;\n submit(\n playerId: string,\n interactionId: string,\n params?: unknown,\n ): Promise<void>;\n validate(\n playerId: string,\n interactionId: string,\n params?: unknown,\n ): Promise<ValidationResult>;\n setControllingPlayer(playerId: string): void;\n};\n\nfunction cloneState<T>(value: T): T {\n return structuredClone(value);\n}\n\nfunction createSubmissionError(\n errorCode: string | undefined,\n message: string | undefined,\n): SubmissionError {\n const error = new Error(message ?? \"Interaction rejected\") as SubmissionError;\n error.name = \"SubmissionError\";\n error.errorCode = errorCode;\n return error;\n}\n\nfunction readFlowState(state: Wire.ReducerSessionState): {\n currentPhase: string | null;\n activePlayers: string[];\n} {\n const flow = ((\n state.domain as\n | { flow?: { currentPhase?: string; activePlayers?: string[] } }\n | undefined\n )?.flow ?? {}) as {\n currentPhase?: string;\n activePlayers?: string[];\n };\n return {\n currentPhase: flow.currentPhase ?? null,\n activePlayers: Array.isArray(flow.activePlayers) ? flow.activePlayers : [],\n };\n}\n\nfunction buildSeatAssignments(\n playerIds: readonly string[],\n userId: string | null,\n displayNameByPlayerId: Record<string, string> | undefined,\n): SeatAssignment[] {\n const actor =\n userId != null ? { kind: \"AUTH_USER\" as const, id: userId } : undefined;\n return playerIds.map((playerId) => ({\n playerId,\n controllerActor: actor,\n displayName: displayNameByPlayerId?.[playerId] ?? playerId,\n }));\n}\n\nfunction resolvePlayerIds(options: {\n baseState: BaseStateArtifact;\n explicitPlayerIds?: readonly string[];\n}): string[] {\n if (options.explicitPlayerIds && options.explicitPlayerIds.length > 0) {\n return [...options.explicitPlayerIds];\n }\n return Array.from(\n { length: options.baseState.fingerprint.players },\n (_, index) => `player-${index + 1}`,\n );\n}\n\n// Stub SSE manager for the in-memory store. `createTestRuntime` never\n// connects to a live backend; updates are delivered through\n// `applyGameplaySnapshotLocal(...)` instead.\nfunction createStubSseManager(): SSEManagerLike {\n return {\n connect: () => undefined,\n disconnect: () => undefined,\n on: () => () => undefined,\n onAnyMessage: () => () => undefined,\n };\n}\n\nfunction buildGameplaySnapshot(options: {\n state: Wire.ReducerSessionState;\n bundle: ReducerBundleLike;\n staticProjection: ReducerStaticProjection | null;\n playerId: string;\n version: number;\n expectedPhase: string | undefined;\n baseId: string;\n}): HostPlayerGameplayView {\n const projection = options.bundle.projectSeatsDynamic({\n state: options.state,\n playerIds: [options.playerId],\n });\n\n const flow = readFlowState(options.state);\n if (options.expectedPhase && flow.currentPhase !== options.expectedPhase) {\n throw new Error(\n `Expected base '${options.baseId}' to be in phase '${options.expectedPhase}', received '${\n flow.currentPhase ?? \"null\"\n }'.`,\n );\n }\n\n const seats = projection.seats ?? {};\n const seat = seats[options.playerId];\n\n return {\n version: options.version,\n actionSetVersion: `${options.version}:test`,\n playerId: options.playerId,\n activePlayers: flow.activePlayers,\n currentPhase: flow.currentPhase ?? \"\",\n currentStage: projection.currentStage ?? \"\",\n stageSeats: projection.stageSeats ?? [],\n view: JSON.stringify(seat?.view ?? null),\n availableInteractions:\n (seat?.availableInteractions as HostPlayerGameplayView[\"availableInteractions\"]) ??\n [],\n zones: (seat?.zones as HostPlayerGameplayView[\"zones\"]) ?? {},\n boardStatic: options.staticProjection\n ? JSON.stringify(options.staticProjection.view)\n : undefined,\n boardStaticHash: options.staticProjection?.hash,\n };\n}\n\nfunction createHostContext(options: {\n sessionId: string;\n userId: string;\n gameId: string;\n phase: HostSessionContext[\"phase\"];\n hostActor: { kind: \"AUTH_USER\"; id: string };\n switchablePlayerIds: string[];\n}): HostSessionContext {\n return {\n sessionId: options.sessionId,\n shortCode: options.sessionId,\n phase: options.phase,\n status: \"active\",\n hostActor: options.hostActor,\n gameSource: {\n kind: \"USER_COMPILED\",\n ownerUserId: options.userId,\n gameId: options.gameId,\n compiledResultId: \"00000000-0000-0000-0000-000000000000\",\n },\n switchablePlayerIds: options.switchablePlayerIds,\n history: {\n entries: [],\n currentIndex: -1,\n canGoBack: false,\n canGoForward: false,\n },\n };\n}\n\nfunction createRuntimeSessionContext(options: {\n sessionId: string;\n userId: string;\n gameId: string;\n hostActor: { kind: \"AUTH_USER\"; id: string };\n switchablePlayerIds: string[];\n seats: SeatAssignment[];\n canStart: boolean;\n}): SessionContext {\n return {\n identity: {\n sessionId: options.sessionId,\n shortCode: options.sessionId,\n gameId: options.gameId,\n },\n userId: options.userId,\n seats: options.seats,\n canStart: options.canStart,\n hostActor: options.hostActor,\n switchablePlayerIds: options.switchablePlayerIds,\n history: {\n entries: [],\n currentIndex: -1,\n canGoBack: false,\n canGoForward: false,\n },\n };\n}\n\nfunction gameplayViewportFromSnapshot(\n snapshot: HostPlayerGameplayView,\n): GameplayViewport {\n return {\n version: snapshot.version,\n actionSetVersion: snapshot.actionSetVersion,\n activePlayers: snapshot.activePlayers,\n currentPhase: snapshot.currentPhase,\n currentStage: snapshot.currentStage,\n stageSeats: snapshot.stageSeats,\n simultaneousPhase: snapshot.simultaneousPhase ?? null,\n view: JSON.parse(snapshot.view) as GameplayViewport[\"view\"],\n availableInteractions: snapshot.availableInteractions,\n zones: snapshot.zones,\n boardStatic: snapshot.boardStatic\n ? (JSON.parse(snapshot.boardStatic) as Record<string, unknown>)\n : null,\n boardStaticHash: snapshot.boardStaticHash ?? null,\n };\n}\n\n// Reuses `packages/ui-host-runtime`'s unified session store so the\n// `getPluginSnapshot()` projection and `applyGameplaySnapshotLocal(...)`\n// reducer running inside workspace tests are the same code paths\n// running inside the host app. Prevents snapshot-shape drift between\n// host plugin UI and authored UI tests.\nexport function createTestRuntime(\n options: CreateTestRuntimeOptions,\n): CreatedTestRuntime {\n const baseState = options.baseStates[options.baseId];\n if (!baseState) {\n throw new Error(`Unknown test base '${options.baseId}'.`);\n }\n\n let currentState = cloneState(baseState.snapshot);\n const playerIds = resolvePlayerIds({\n baseState,\n explicitPlayerIds: options.playerIds,\n });\n const userId = options.userId ?? \"test-user\";\n const sessionId = options.sessionId ?? \"test-session\";\n const gameId = options.gameId ?? \"test-game\";\n const seats = buildSeatAssignments(\n playerIds,\n userId,\n options.displayNameByPlayerId,\n );\n const storeApi = createUnifiedSessionStore({\n createSseManager: createStubSseManager,\n // Test runtimes keep `userId` present so the unified store derives\n // controllable player ids from seat assignments whenever the\n // incoming snapshot omits `controllablePlayerIds`.\n fallbackToAllSeatsWhenUserIdMissing: false,\n });\n\n const hostActor = { kind: \"AUTH_USER\" as const, id: userId };\n const lobbySnapshot: HostSessionSnapshot = {\n type: \"lobby\",\n context: createHostContext({\n sessionId,\n userId,\n gameId,\n phase: \"lobby\",\n hostActor,\n switchablePlayerIds: playerIds,\n }),\n lobby: {\n seats,\n canStart: true,\n hostActor,\n },\n };\n const setSessionState = (input: {\n selectedPlayerId: string;\n gameplay?: HostPlayerGameplayView;\n }): void => {\n const context = createRuntimeSessionContext({\n sessionId,\n userId,\n gameId,\n hostActor,\n switchablePlayerIds: playerIds,\n seats,\n canStart: true,\n });\n storeApi.setState((state) => ({\n ...state,\n session: input.gameplay\n ? {\n type: \"gameplay\",\n context,\n perspective: { playerId: input.selectedPlayerId },\n gameplay: gameplayViewportFromSnapshot(input.gameplay),\n }\n : {\n type: \"lobby\",\n context,\n preferredPlayerId: input.selectedPlayerId || null,\n },\n connection: { ...state.connection, error: null },\n activity: {\n ...state.activity,\n syncId: state.activity.syncId + 1,\n lastSyncTimestamp: Date.now(),\n },\n }));\n };\n\n setSessionState({\n selectedPlayerId: playerIds[0] ?? \"\",\n });\n\n let version = 0;\n let currentPlayerId = playerIds[0] ?? \"\";\n const staticProjection = options.bundle.projectStatic?.() ?? null;\n\n const applyCurrentState = (): void => {\n version += 1;\n const snapshot = buildGameplaySnapshot({\n state: currentState,\n bundle: options.bundle,\n staticProjection,\n playerId: currentPlayerId,\n version,\n expectedPhase: version === 1 ? options.phase : undefined,\n baseId: options.baseId,\n });\n setSessionState({\n selectedPlayerId: currentPlayerId,\n gameplay: snapshot,\n });\n };\n\n applyCurrentState();\n\n const stateListeners = new Set<(state: PluginStateSnapshot) => void>();\n const sessionListeners = new Set<(state: PluginSessionState) => void>();\n\n let lastPluginSnapshot = storeApi.getState().getPluginSnapshot();\n let lastSessionState: PluginSessionState = {\n ...lastPluginSnapshot.session,\n status: \"ready\",\n };\n\n storeApi.subscribe((state, previous) => {\n const nextPluginSnapshot = state.getPluginSnapshot();\n if (nextPluginSnapshot !== lastPluginSnapshot) {\n lastPluginSnapshot = nextPluginSnapshot;\n for (const listener of stateListeners) {\n listener(nextPluginSnapshot);\n }\n }\n const previousSession = previous.getPluginSnapshot().session;\n const nextSession = nextPluginSnapshot.session;\n const controllingPlayerChanged =\n nextSession.controllingPlayerId !== previousSession.controllingPlayerId;\n const controllableIdsChanged =\n nextSession.controllablePlayerIds.join(\"\\0\") !==\n previousSession.controllablePlayerIds.join(\"\\0\");\n if (controllingPlayerChanged || controllableIdsChanged) {\n lastSessionState = {\n ...nextPluginSnapshot.session,\n status: \"ready\",\n };\n for (const listener of sessionListeners) {\n listener(lastSessionState);\n }\n }\n });\n\n const validate = async (\n playerId: string,\n interactionId: string,\n params: unknown = {},\n ): Promise<ValidationResult> => {\n const result = await options.bundle.validateInput({\n state: currentState,\n input: {\n kind: \"interaction\",\n playerId,\n interactionId,\n params: params as Wire.JsonValue,\n },\n });\n return {\n valid: result.valid,\n errorCode: result.errorCode,\n message: result.message,\n };\n };\n\n const submit = async (\n playerId: string,\n interactionId: string,\n params: unknown = {},\n ): Promise<void> => {\n const validation = await validate(playerId, interactionId, params);\n if (!validation.valid) {\n throw createSubmissionError(validation.errorCode, validation.message);\n }\n const result = await options.bundle.dispatch({\n state: currentState,\n input: {\n kind: \"interaction\",\n playerId,\n interactionId,\n params: params as Wire.JsonValue,\n },\n });\n if (result.kind === \"reject\") {\n throw createSubmissionError(result.errorCode, result.message);\n }\n currentState = cloneState(result.state);\n applyCurrentState();\n };\n\n const setControllingPlayer = (playerId: string): void => {\n if (!playerIds.includes(playerId)) {\n throw new Error(`Unknown controlling player '${playerId}'.`);\n }\n currentPlayerId = playerId;\n storeApi.getState().selectPlayer(playerId);\n applyCurrentState();\n };\n\n const runtime = {\n validateInteraction: validate,\n submitInteraction: submit,\n getSessionState: (): PluginSessionState => ({ ...lastSessionState }),\n disconnect: () => undefined,\n switchPlayer: (playerId: string) => {\n setControllingPlayer(playerId);\n },\n getSnapshot: (): PluginStateSnapshot => lastPluginSnapshot,\n subscribeToState: (listener: (state: PluginStateSnapshot) => void) => {\n stateListeners.add(listener);\n return () => {\n stateListeners.delete(listener);\n };\n },\n _subscribeToSessionState: (\n listener: (state: PluginSessionState) => void,\n ) => {\n sessionListeners.add(listener);\n return () => {\n sessionListeners.delete(listener);\n };\n },\n };\n\n return {\n runtime,\n getSnapshot: () => lastPluginSnapshot,\n players: () => [...playerIds],\n seat: (index: number) => {\n if (!Number.isInteger(index) || index < 0 || index >= playerIds.length) {\n throw new Error(\n `seat(${index}) is out of range; base '${options.baseId}' has ${playerIds.length} player(s).`,\n );\n }\n return playerIds[index]!;\n },\n submit,\n validate,\n setControllingPlayer,\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,102 +0,0 @@
1
- # Authoring lifecycle
2
-
3
- See how authored Dreamboard files flow through sync, compile, runtime, UI projection, and tests.
4
-
5
- Dreamboard has one recommended lifecycle: author static structure, bind it into a reducer contract, register runtime behavior, project UI state, then verify it with generated tests.
6
-
7
- ```mermaid
8
- flowchart TD
9
- Rule["rule.md"]
10
- Manifest["manifest.ts"]
11
- Contract["app/game-contract.ts"]
12
- Game["app/game.ts"]
13
- Sync["dreamboard sync"]
14
- Generated["shared/manifest-contract.ts and shared/generated/ui-contract.ts"]
15
- Compile["dreamboard compile"]
16
- Runtime["Reducer runtime"]
17
- View["defineView / defineStaticView"]
18
- UI["Generated UI primitives"]
19
- Tests["defineBase / defineScenario"]
20
-
21
- Rule --> Manifest
22
- Manifest --> Sync
23
- Sync --> Generated
24
- Generated --> Contract
25
- Contract --> Game
26
- Game --> Compile
27
- Compile --> Runtime
28
- Runtime --> View
29
- View --> UI
30
- Generated --> Tests
31
- Game --> Tests
32
- ```
33
-
34
- ## 1. Author the manifest
35
-
36
- Start with `manifest.ts`. The manifest names the table pieces that the rest of the project should refer to: player ids, card ids, zone ids, board ids, resource ids, setup options, and setup profiles.
37
-
38
- After a manifest change, run:
39
-
40
- ```bash
41
- dreamboard sync
42
- ```
43
-
44
- `sync` regenerates the manifest contract. If you renamed a zone, any reducer/UI/test code still using the old zone id should fail to compile.
45
-
46
- ## 2. Bind the reducer contract
47
-
48
- `app/game-contract.ts` imports `manifestContract` and calls `defineGameContract`.
49
-
50
- This is where authored state starts:
51
-
52
- - `public` for state every player can see
53
- - `private` for per-player secrets
54
- - `hidden` for game-owned secrets
55
- - `phaseNames` for the legal phase-name union
56
-
57
- Use manifest-backed schemas from `gameContract.schemas` or generated `ids` so state and params stay tied to the manifest.
58
-
59
- ## 3. Define phases and interactions
60
-
61
- Phases define game flow. Interactions define what players can submit.
62
-
63
- The runtime path for an interaction is:
64
-
65
- 1. Find the active phase.
66
- 2. Check actor authorization.
67
- 3. Parse client params from collectors.
68
- 4. Validate board/card/choice targets from target rules.
69
- 5. Run `available` and `validate`.
70
- 6. Call `reduce`.
71
- 7. Apply returned state and queued runtime instructions.
72
-
73
- The UI should not reimplement this. It reads descriptors and eligible targets generated from the same interaction definition.
74
-
75
- ## 4. Project views
76
-
77
- Use `defineView` for dynamic per-player payloads. Use `defineStaticView` for immutable session payloads.
78
-
79
- Dynamic views can see state and `playerId`; static views cannot. That split keeps large static topology out of every runtime update.
80
-
81
- ## 5. Render UI primitives
82
-
83
- The generated UI contract creates typed interaction keys, input keys, prompt
84
- options, zones, cards, phases, and board target ids. Compose those generated
85
- primitives in `ui/App.tsx`.
86
-
87
- Prefer `Interaction`, `PromptInbox`, `Prompt`, and `Zone` components first. Use
88
- hooks only when the game needs domain-specific custom rendering, such as an SVG
89
- board, not to reimplement validation or turn logic.
90
-
91
- ## 6. Test the reducer
92
-
93
- Run:
94
-
95
- ```bash
96
- dreamboard test generate
97
- dreamboard test run
98
- ```
99
-
100
- `test generate` writes workspace-narrowed test types from the current game definition. Scenarios submit typed interactions and assert against reducer state and projected views.
101
-
102
- If tests fail after a manifest or reducer change, regenerate the testing contract before assuming the scenario logic is wrong.
@@ -1,36 +0,0 @@
1
- # Board targets
2
-
3
- Route board clicks through generated reducer-aware target helpers.
4
-
5
- Board renderers are the main escape hatch for custom visuals. Keep legality in
6
- the reducer and route clicks through generated `useBoardInteractions()`.
7
-
8
- ```tsx
9
- import { useBoardInteractions } from "@dreamboard/ui-contract";
10
- import { HexGrid } from "@dreamboard/ui-sdk";
11
-
12
- function Board({ view }) {
13
- const board = useBoardInteractions();
14
- return (
15
- <HexGrid
16
- board={view.board}
17
- interactiveVertices={board.targetLayers.vertex()}
18
- interactiveEdges={board.targetLayers.edge()}
19
- interactiveSpaces={board.targetLayers.space()}
20
- renderTile={(tile, geometry) => <polygon points={geometry.points()} />}
21
- renderEdge={(edge) => <line />}
22
- renderVertex={(vertex) => <circle />}
23
- />
24
- );
25
- }
26
- ```
27
-
28
- The hook merges target domains from the current descriptors and submits the
29
- selected target to the best matching interaction. If two equal-priority
30
- interactions can handle the same target, it fails loudly so the reducer can
31
- declare a clearer `dispatchPriority` or the UI can route explicitly.
32
-
33
- Use this for SVG, canvas, or geometry-heavy boards. `HexGrid` and `SquareGrid`
34
- still need normal render callbacks for spaces, edges, and vertices; the
35
- interactive layers only add reducer-aware target overlays. Ordinary buttons and card
36
- inputs should use `Interaction` and `Zone` primitives instead.
@@ -1,443 +0,0 @@
1
- # Board topology
2
-
3
- Author hex and square boards with shared reducer and UI topology primitives.
4
-
5
- Use tiled boards when your game has stable spaces plus meaningful borders or
6
- corners.
7
-
8
- Dreamboard currently supports two fixed-topology tiled layouts:
9
-
10
- - `layout: "hex"` for axial hex maps
11
- - `layout: "square"` for row and column grids
12
-
13
- Keep `layout: "generic"` for authored graphs that are not tile-based, such as
14
- tracks, networks, or map nodes.
15
-
16
- It is normal for one manifest to mix these layouts. For example, a game can use
17
- one shared generic market board, one shared hex frontier map, and one
18
- per-player square mat without splitting that coverage across multiple
19
- workspaces.
20
-
21
- The generated manifest contract now preserves that mixed topology directly with
22
- template-level literals plus board-scoped edge and vertex helpers:
23
-
24
- {/* Generated from examples/board-contract-lab/app/authoring-benchmark-typing-smoke.ts (tiled-board-helpers) */}
25
-
26
- ```ts
27
- const playerMatId = boardHelpers.boardIdForPlayer("player-mat", "player-1");
28
- const hexBoardIds = boardHelpers.boardIdsForLayout("hex");
29
- const frontierRouteId = boardHelpers.edgeIds("frontier-map", "ferry-route")[0]!;
30
- const frontierCheckpointId = boardHelpers.vertexIds(
31
- "frontier-map",
32
- "checkpoint",
33
- )[0]!;
34
- const marketTemplateBoards =
35
- boardHelpers.boardBaseIdsForTemplate("market-template");
36
- const playerMatTemplateLayout = boardHelpers.boardTemplateLayout(
37
- "player-mat-template",
38
- );
39
- //
40
- ```
41
-
42
- ## What lives where
43
-
44
- Put immutable topology in the manifest:
45
-
46
- - spaces and their coordinates
47
- - optional authored edge and vertex metadata
48
- - authored containers and extra relations
49
-
50
- Put mutable gameplay state in reducer state:
51
-
52
- - ownership keyed by `spaceId`, `edgeId`, or `vertexId`
53
- - placed tiles, markers, units, or hazards
54
- - highlights, legal targets, and temporary UI state
55
-
56
- That split keeps the board reusable across different games and avoids treating
57
- manifest topology as a mutable gameplay store.
58
-
59
- ## Fixed-topology constraint
60
-
61
- Hex and square boards in this release are fixed once the session starts.
62
-
63
- - Terraforming Mars fits this model: spaces stay fixed while ownership and tile
64
- state change.
65
- - Gloomhaven fits this model: spaces stay fixed while units move and range is
66
- recalculated.
67
- - Cascadia fits this model when the habitat map is pre-authored and scoring
68
- reads adjacency from the fixed board.
69
-
70
- Carcassonne-style board growth is not part of this release. Treat that as a
71
- future topology adapter rather than part of the current `square` layout.
72
-
73
- ## Shared topology vocabulary
74
-
75
- Reducer helpers and UI hooks use the same terms:
76
-
77
- | Term | Meaning |
78
- | ----------- | ----------------------------------------------------- |
79
- | `space` | One tile or cell on the board |
80
- | `edge` | One border shared by one or two spaces |
81
- | `vertex` | One corner touched by one to four spaces |
82
- | `adjacent` | The default movement or scoring graph for a layout |
83
- | `incident` | Edges touching a vertex, or vertices touching an edge |
84
- | `occupancy` | Components currently on a space, edge, or vertex |
85
-
86
- Reducer-side board helpers are covered in [Table queries and ops](./table-queries-and-ops.md).
87
- UI-side board rendering is covered in [Board targets](./board-surfaces.md)
88
- and [UI components](./ui-components.md).
89
-
90
- ## Choosing a layout
91
-
92
- | Layout | Use it for | Default adjacency |
93
- | --------- | ----------------------------------------------------- | ---------------------------------- |
94
- | `generic` | Tracks, networks, arbitrary relation graphs | Whatever you author in `relations` |
95
- | `hex` | Terraforming Mars, Gloomhaven, Cascadia, wargame maps | Derived hex adjacency |
96
- | `square` | Chess, Checkers, Onitama, fixed tile grids | Orthogonal 4-way adjacency |
97
-
98
- Square boards can still use diagonal logic. The reducer and UI helpers expose
99
- square-specific variants for diagonal neighbors and Chebyshev distance.
100
-
101
- ## Reducer state pattern
102
-
103
- Store dynamic tiled state in plain overlay maps keyed by stable location IDs.
104
-
105
- ```ts
106
- import { z } from "zod";
107
- import type {
108
- TiledEdgeMap,
109
- TiledSpaceMap,
110
- TiledVertexMap,
111
- } from "@dreamboard/app-sdk/reducer";
112
- import { ids } from "../shared/manifest-contract";
113
-
114
- const publicState = z.object({
115
- ownershipBySpaceId: z.partialRecord(ids.spaceId, ids.playerId).default({}),
116
- effectByEdgeId: z.partialRecord(ids.edgeId, z.string()).default({}),
117
- markerByVertexId: z
118
- .partialRecord(
119
- ids.vertexId,
120
- z.object({
121
- ownerId: ids.playerId,
122
- kind: z.string(),
123
- }),
124
- )
125
- .default({}),
126
- });
127
-
128
- type OwnershipBySpaceId = TiledSpaceMap<
129
- typeof manifestContract.table,
130
- "mars",
131
- string
132
- >;
133
- type EffectByEdgeId = TiledEdgeMap<
134
- typeof manifestContract.table,
135
- "arena",
136
- string
137
- >;
138
- type MarkerByVertexId = TiledVertexMap<
139
- typeof manifestContract.table,
140
- "arena",
141
- { ownerId: string; kind: string }
142
- >;
143
- ```
144
-
145
- Use `z.partialRecord(...)` for mutable tiled overlays. Runtime gameplay state is
146
- usually sparse, so empty-object initialization should compile and missing keys
147
- should mean "nothing placed here yet".
148
-
149
- Use this pattern for:
150
-
151
- - Terraforming Mars: `ownershipBySpaceId`, placed tile type, adjacency-bonus flags
152
- - Gloomhaven: movement blockers by edge, trap markers by vertex, units keyed by
153
- space
154
- - Cascadia: adjacency-driven scoring keyed by placed habitat or wildlife tiles
155
-
156
- ## Projecting UI-ready boards
157
-
158
- Reducer views should join immutable topology with mutable overlay state before
159
- rendering. Destructure the injected `q` inside `project({ state, playerId, q })`
160
- instead of constructing a fresh query from state.
161
-
162
- ```ts
163
- import { defineView } from "@dreamboard/app-sdk/reducer";
164
- import type { GameContract } from "./game-contract";
165
-
166
- export const playerView = defineView<GameContract>()({
167
- project({ state, q }) {
168
- const board = q.board.tiled("arena");
169
-
170
- return {
171
- boardId: board.id,
172
- layout: board.layout,
173
- spaces: Object.values(board.spaces).map((space) => ({
174
- ...space,
175
- ownerId: state.publicState.ownershipBySpaceId[space.id] ?? null,
176
- edgeIds: q.board.spaceEdges(board.id, space.id),
177
- vertexIds: q.board.spaceVertices(board.id, space.id),
178
- })),
179
- legalEdgeIds: state.publicState.legalEdgeIds,
180
- legalVertexIds: state.publicState.legalVertexIds,
181
- };
182
- },
183
- });
184
- ```
185
-
186
- Keep canonical legality and scoring in reducer code. The UI should consume a
187
- projected board view plus simple highlight or legal-target sets.
188
-
189
- ## Board shape and traversal
190
-
191
- - `board.spaces` is an ID-keyed record.
192
- - `board.edges` is an array of edge records.
193
- - `board.vertices` is an array of vertex records.
194
-
195
- <Warning>
196
- Do not use `Object.keys(board.edges)` or `Object.keys(board.vertices)` to
197
- discover runtime IDs. Those expressions return array indexes, not edge or
198
- vertex IDs.
199
- </Warning>
200
-
201
- Use reducer-native query helpers when you need topology traversal:
202
-
203
- - `q.board.spaceEdges(boardId, spaceId)`
204
- - `q.board.spaceVertices(boardId, spaceId)`
205
- - `q.board.incidentEdges(boardId, vertexId)`
206
- - `q.board.incidentVertices(boardId, edgeId)`
207
-
208
- `incidentEdges(...)` and `incidentVertices(...)` are geometry helpers. They
209
- return all tiled edges or vertices that share the same incident spaces as the
210
- input location. They do not apply gameplay-specific filters such as road
211
- ownership or blocked-path rules.
212
-
213
- ## Wiring the UI
214
-
215
- Use one of the layout-specific renderers:
216
-
217
- - `HexGrid` for hex spaces, edges, and vertices
218
- - `SquareGrid` for square cells, edges, and vertices
219
-
220
- Use the headless topology hooks when the UI needs geometry-aware logic:
221
-
222
- - `useBoardTopology(...)` for shared tiled queries
223
- - `useHexBoard(...)` for hex-specific coordinate helpers
224
- - `useSquareBoard(...)` for square-specific neighbor and distance variants
225
-
226
- ```tsx
227
- import { HexGrid, SquareGrid, useBoardTopology, useSquareBoard } from "@dreamboard/ui-sdk";
228
-
229
- function ArenaBoard({ board, onEdgeClick, onVertexClick }) {
230
- const topology = useSquareBoard(board);
231
-
232
- return (
233
- <SquareGrid
234
- board={board}
235
- interactiveEdges={{ selectTargetId: onEdgeClick }}
236
- interactiveVertices={{ selectTargetId: onVertexClick }}
237
- renderCell={(row, col) => {
238
- const cell = topology.getCellAt(row, col);
239
- return <Cell ownerId={cell?.owner ?? null} />;
240
- }}
241
- renderPiece={(piece) => <Piece piece={piece} />}
242
- />
243
- );
244
- }
245
- ```
246
-
247
- This keeps interactivity consistent across layouts. Authors do not need to
248
- re-derive borders, corners, or adjacency in UI code.
249
-
250
- Project the whole tiled board record into the reducer view. Then keep
251
- game-specific legality beside it:
252
-
253
- ```ts
254
- project({ state, q }) {
255
- return {
256
- board: q.board.tiled("arena"),
257
- legalEdgeIds: state.publicState.legalEdgeIds,
258
- legalVertexIds: state.publicState.legalVertexIds,
259
- };
260
- }
261
- ```
262
-
263
- Use this rule when deciding what to expose:
264
-
265
- - `spaces` are enough for tile or cell rendering only
266
- - `edges` are required when the UI should render or interact with borders
267
- - `vertices` are required when the UI should render or interact with corners
268
-
269
- For example, a route-building board view should project all three so the UI can
270
- render paths and markers and also expose placement targets.
271
-
272
- The important reducer-native detail is that target-layer IDs keep the board's
273
- exact runtime types. If the reducer view projects typed `edge.id` and
274
- `vertex.id` values, `board={board}` preserves those same ids through
275
- `selectTargetId` instead of forcing the UI to remap topology ids by hand.
276
-
277
- ## Runtime IDs
278
-
279
- Hex and square edge and vertex IDs are derived runtime IDs based on authored
280
- space topology.
281
-
282
- - author spaces in the manifest
283
- - optionally attach authored edge and vertex metadata by `ref.spaces`
284
- - read the runtime `edgeId` and `vertexId` values from reducer helpers,
285
- `boardHelpers.edgeIds(...)`, `boardHelpers.vertexIds(...)`,
286
- `boardHelpers.boardIdForPlayer(...)`, or the projected board view
287
- - use those IDs as keys in reducer state and as click targets in the UI
288
-
289
- <Warning>
290
- Do not hardcode the derived string format in app code. Read the runtime
291
- `edgeId` and `vertexId` values from the helpers and projected board view
292
- above instead.
293
- </Warning>
294
-
295
- ## Valid and invalid tiled refs
296
-
297
- Author edge and vertex refs with real shared geometry, not just “nearby”
298
- spaces. These examples show the difference.
299
-
300
- ### Square edge refs
301
-
302
- Valid square edge ref: the two cells share one border.
303
-
304
- ```ts
305
- {
306
- layout: "square",
307
- spaces: [
308
- { id: "a1", row: 0, col: 0 },
309
- { id: "a2", row: 0, col: 1 },
310
- ],
311
- edges: [
312
- { ref: { spaces: ["a1", "a2"] }, typeId: "road" },
313
- ],
314
- }
315
- ```
316
-
317
- Invalid square edge ref: diagonal cells do not share an edge.
318
-
319
- ```ts
320
- {
321
- layout: "square",
322
- spaces: [
323
- { id: "a1", row: 0, col: 0 },
324
- { id: "b2", row: 1, col: 1 },
325
- ],
326
- edges: [
327
- { ref: { spaces: ["a1", "b2"] }, typeId: "road" },
328
- ],
329
- }
330
- ```
331
-
332
- Why invalid: `a1` and `b2` only meet at a corner, so this must be a vertex ref
333
- instead of an edge ref.
334
-
335
- ### Square vertex refs
336
-
337
- Valid square vertex ref: the cells resolve to one shared corner.
338
-
339
- ```ts
340
- {
341
- layout: "square",
342
- spaces: [
343
- { id: "a1", row: 0, col: 0 },
344
- { id: "a2", row: 0, col: 1 },
345
- { id: "b1", row: 1, col: 0 },
346
- { id: "b2", row: 1, col: 1 },
347
- ],
348
- vertices: [
349
- { ref: { spaces: ["a1", "a2", "b1", "b2"] }, typeId: "tower" },
350
- ],
351
- }
352
- ```
353
-
354
- Invalid square vertex ref: the cells do not collapse to exactly one corner.
355
-
356
- ```ts
357
- {
358
- layout: "square",
359
- spaces: [
360
- { id: "a1", row: 0, col: 0 },
361
- { id: "a2", row: 0, col: 1 },
362
- { id: "c1", row: 2, col: 0 },
363
- ],
364
- vertices: [
365
- { ref: { spaces: ["a1", "a2", "c1"] }, typeId: "tower" },
366
- ],
367
- }
368
- ```
369
-
370
- Why invalid: those three cells do not touch the same corner, so the ref cannot
371
- resolve to one runtime vertex ID.
372
-
373
- ### Hex edge refs
374
-
375
- Valid hex edge ref: the two hexes share one border.
376
-
377
- ```ts
378
- {
379
- layout: "hex",
380
- spaces: [
381
- { id: "hex-a", q: 0, r: 0 },
382
- { id: "hex-b", q: 1, r: 0 },
383
- ],
384
- edges: [
385
- { ref: { spaces: ["hex-a", "hex-b"] }, typeId: "road" },
386
- ],
387
- }
388
- ```
389
-
390
- Invalid hex edge ref: non-adjacent hexes do not form an edge.
391
-
392
- ```ts
393
- {
394
- layout: "hex",
395
- spaces: [
396
- { id: "hex-a", q: 0, r: 0 },
397
- { id: "hex-c", q: 2, r: 0 },
398
- ],
399
- edges: [
400
- { ref: { spaces: ["hex-a", "hex-c"] }, typeId: "road" },
401
- ],
402
- }
403
- ```
404
-
405
- Why invalid: `hex-a` and `hex-c` are separated by another hex, so there is no
406
- shared border to attach an edge to.
407
-
408
- ### Hex vertex refs
409
-
410
- Valid hex vertex ref: the three hexes meet at one corner.
411
-
412
- ```ts
413
- {
414
- layout: "hex",
415
- spaces: [
416
- { id: "hex-a", q: 0, r: 0 },
417
- { id: "hex-b", q: 1, r: 0 },
418
- { id: "hex-c", q: 0, r: 1 },
419
- ],
420
- vertices: [
421
- { ref: { spaces: ["hex-a", "hex-b", "hex-c"] }, typeId: "settlement" },
422
- ],
423
- }
424
- ```
425
-
426
- Invalid hex vertex ref: collinear hexes do not share a single corner.
427
-
428
- ```ts
429
- {
430
- layout: "hex",
431
- spaces: [
432
- { id: "hex-a", q: 0, r: 0 },
433
- { id: "hex-b", q: 1, r: 0 },
434
- { id: "hex-c", q: 2, r: 0 },
435
- ],
436
- vertices: [
437
- { ref: { spaces: ["hex-a", "hex-b", "hex-c"] }, typeId: "settlement" },
438
- ],
439
- }
440
- ```
441
-
442
- Why invalid: those three hexes never meet at one point, so the ref fails
443
- validation instead of producing an ambiguous runtime vertex.