@dreamboard-games/sdk 0.2.0

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 (369) hide show
  1. package/LICENSE.md +96 -0
  2. package/README.md +12 -0
  3. package/dist/HandView-ncJIVLhN.d.ts +193 -0
  4. package/dist/ResourceCounter-CTREyF73.d.ts +102 -0
  5. package/dist/ThemeProvider-fy0_QzgO.d.ts +99 -0
  6. package/dist/bundle-TIZcw8LB.d.ts +281 -0
  7. package/dist/cards-Sl3b40Mv.d.ts +13 -0
  8. package/dist/chunk-7YAHLYBR.js +481 -0
  9. package/dist/chunk-7YAHLYBR.js.map +1 -0
  10. package/dist/chunk-FDNZTDD6.js +8085 -0
  11. package/dist/chunk-FDNZTDD6.js.map +1 -0
  12. package/dist/chunk-GKKBPPSW.js +598 -0
  13. package/dist/chunk-GKKBPPSW.js.map +1 -0
  14. package/dist/chunk-I46YJSOD.js +1 -0
  15. package/dist/chunk-I46YJSOD.js.map +1 -0
  16. package/dist/chunk-KAELH4KC.js +104 -0
  17. package/dist/chunk-KAELH4KC.js.map +1 -0
  18. package/dist/chunk-PZ5AY32C.js +10 -0
  19. package/dist/chunk-PZ5AY32C.js.map +1 -0
  20. package/dist/chunk-T3ZKNUZ7.js +1 -0
  21. package/dist/chunk-T3ZKNUZ7.js.map +1 -0
  22. package/dist/chunk-T52J5RMF.js +1 -0
  23. package/dist/chunk-T52J5RMF.js.map +1 -0
  24. package/dist/chunk-TDSWKVZ4.js +5401 -0
  25. package/dist/chunk-TDSWKVZ4.js.map +1 -0
  26. package/dist/chunk-U5C6BONG.js +34 -0
  27. package/dist/chunk-U5C6BONG.js.map +1 -0
  28. package/dist/chunk-VDXOF4FW.js +69 -0
  29. package/dist/chunk-VDXOF4FW.js.map +1 -0
  30. package/dist/chunk-VFTAA4WO.js +115 -0
  31. package/dist/chunk-VFTAA4WO.js.map +1 -0
  32. package/dist/chunk-WN74KVNY.js +17 -0
  33. package/dist/chunk-WN74KVNY.js.map +1 -0
  34. package/dist/chunk-WYPQ3GG5.js +10990 -0
  35. package/dist/chunk-WYPQ3GG5.js.map +1 -0
  36. package/dist/components-D5ZRE2Hl.d.ts +1451 -0
  37. package/dist/generated/runtime/primitives.d.ts +12 -0
  38. package/dist/generated/runtime/primitives.js +180 -0
  39. package/dist/generated/runtime/primitives.js.map +1 -0
  40. package/dist/generated/runtime-api.d.ts +3 -0
  41. package/dist/generated/runtime-api.js +2 -0
  42. package/dist/generated/runtime-api.js.map +1 -0
  43. package/dist/generated/runtime.d.ts +14 -0
  44. package/dist/generated/runtime.js +18 -0
  45. package/dist/generated/runtime.js.map +1 -0
  46. package/dist/generated/workspace-contract.d.ts +14 -0
  47. package/dist/generated/workspace-contract.js +14 -0
  48. package/dist/generated/workspace-contract.js.map +1 -0
  49. package/dist/hex-board-view-D_07hO6O.d.ts +933 -0
  50. package/dist/hex-color-MhOyuY-o.d.ts +8 -0
  51. package/dist/index-BwqPQtBu.d.ts +1433 -0
  52. package/dist/index.d.ts +1 -0
  53. package/dist/index.js +12 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/infrastructure/reducer-bundle-abi.d.ts +1083 -0
  56. package/dist/infrastructure/reducer-bundle-abi.js +14 -0
  57. package/dist/infrastructure/reducer-bundle-abi.js.map +1 -0
  58. package/dist/infrastructure/workspace-codegen.d.ts +53 -0
  59. package/dist/infrastructure/workspace-codegen.js +44 -0
  60. package/dist/infrastructure/workspace-codegen.js.map +1 -0
  61. package/dist/manifest-contract-BNHVGFtU.d.ts +9 -0
  62. package/dist/package-set.d.ts +13 -0
  63. package/dist/package-set.js +12 -0
  64. package/dist/package-set.js.map +1 -0
  65. package/dist/primitive-props-DpKs-GCr.d.ts +11 -0
  66. package/dist/reducer.d.ts +3786 -0
  67. package/dist/reducer.js +8131 -0
  68. package/dist/reducer.js.map +1 -0
  69. package/dist/runtime/primitives.d.ts +226 -0
  70. package/dist/runtime/primitives.js +180 -0
  71. package/dist/runtime/primitives.js.map +1 -0
  72. package/dist/runtime/types/runtime-api.d.ts +1 -0
  73. package/dist/runtime/types/runtime-api.js +2 -0
  74. package/dist/runtime/types/runtime-api.js.map +1 -0
  75. package/dist/runtime/workspace-contract.d.ts +172 -0
  76. package/dist/runtime/workspace-contract.js +14 -0
  77. package/dist/runtime/workspace-contract.js.map +1 -0
  78. package/dist/runtime-api-3dshj6kK.d.ts +101 -0
  79. package/dist/runtime-api-DWxvTr-O.d.ts +379 -0
  80. package/dist/runtime.d.ts +58 -0
  81. package/dist/runtime.js +13 -0
  82. package/dist/runtime.js.map +1 -0
  83. package/dist/slots-1GPGihk8.d.ts +8 -0
  84. package/dist/testing.d.ts +149 -0
  85. package/dist/testing.js +513 -0
  86. package/dist/testing.js.map +1 -0
  87. package/dist/types.d.ts +496 -0
  88. package/dist/types.js +28 -0
  89. package/dist/types.js.map +1 -0
  90. package/dist/ui/components.d.ts +16 -0
  91. package/dist/ui/components.js +192 -0
  92. package/dist/ui/components.js.map +1 -0
  93. package/dist/ui/defaults.d.ts +19 -0
  94. package/dist/ui/defaults.js +104 -0
  95. package/dist/ui/defaults.js.map +1 -0
  96. package/dist/ui/plugin-styles.css +250 -0
  97. package/dist/ui/types/player-state.d.ts +365 -0
  98. package/dist/ui/types/player-state.js +1 -0
  99. package/dist/ui/types/player-state.js.map +1 -0
  100. package/dist/ui-contract-iQfTtUSL.d.ts +1161 -0
  101. package/dist/ui.d.ts +320 -0
  102. package/dist/ui.js +253 -0
  103. package/dist/ui.js.map +1 -0
  104. package/package.json +199 -0
  105. package/src/generated/reducer-contract/builders.ts +90 -0
  106. package/src/generated/reducer-contract/version.ts +9 -0
  107. package/src/generated/reducer-contract/wire.ts +100 -0
  108. package/src/generated/reducer-contract/zod.ts +101 -0
  109. package/src/generated/runtime/primitives.ts +2 -0
  110. package/src/generated/runtime-api.ts +5 -0
  111. package/src/generated/runtime.ts +35 -0
  112. package/src/generated/workspace-contract.ts +2 -0
  113. package/src/index.ts +7 -0
  114. package/src/infrastructure/reducer-bundle-abi.ts +8 -0
  115. package/src/infrastructure/reducer-contract/bundle.ts +37 -0
  116. package/src/infrastructure/workspace-codegen/hex-geometry.ts +69 -0
  117. package/src/infrastructure/workspace-codegen/index.ts +64 -0
  118. package/src/infrastructure/workspace-codegen/manifest-contract.ts +6632 -0
  119. package/src/infrastructure/workspace-codegen/manifest-validation.ts +795 -0
  120. package/src/infrastructure/workspace-codegen/ownership.ts +131 -0
  121. package/src/infrastructure/workspace-codegen/preset-card-sets.ts +169 -0
  122. package/src/infrastructure/workspace-codegen/seeds.ts +1705 -0
  123. package/src/infrastructure/workspace-codegen.ts +1 -0
  124. package/src/package-set.ts +19 -0
  125. package/src/reducer/authoring/contract.ts +157 -0
  126. package/src/reducer/authoring/effect.ts +224 -0
  127. package/src/reducer/authoring/game.ts +23 -0
  128. package/src/reducer/authoring/interaction.ts +98 -0
  129. package/src/reducer/authoring/phase.ts +300 -0
  130. package/src/reducer/authoring/types.ts +70 -0
  131. package/src/reducer/authoring/validation.ts +382 -0
  132. package/src/reducer/authoring/view-stage.ts +68 -0
  133. package/src/reducer/authoring.ts +29 -0
  134. package/src/reducer/bundle/ingress-bundle.ts +491 -0
  135. package/src/reducer/bundle/trusted/engine-instruction-resolver.ts +254 -0
  136. package/src/reducer/bundle/trusted/flow-instruction-resolver.ts +73 -0
  137. package/src/reducer/bundle/trusted/instruction-runner.ts +414 -0
  138. package/src/reducer/bundle/trusted/interaction-authorization.ts +137 -0
  139. package/src/reducer/bundle/trusted/interaction-collectors.ts +859 -0
  140. package/src/reducer/bundle/trusted/interaction-decision.ts +747 -0
  141. package/src/reducer/bundle/trusted/interaction-resolver.ts +95 -0
  142. package/src/reducer/bundle/trusted/interaction-types.ts +171 -0
  143. package/src/reducer/bundle/trusted/lifecycle-runner.ts +427 -0
  144. package/src/reducer/bundle/trusted/projection-builder.ts +356 -0
  145. package/src/reducer/bundle/trusted/projection-context.ts +39 -0
  146. package/src/reducer/bundle/trusted/rng-sampler.ts +150 -0
  147. package/src/reducer/bundle/trusted/runtime-registry.ts +120 -0
  148. package/src/reducer/bundle/trusted/runtime-scope.ts +336 -0
  149. package/src/reducer/bundle/trusted/simultaneous-player.ts +97 -0
  150. package/src/reducer/bundle/trusted/stage-resolver.ts +87 -0
  151. package/src/reducer/bundle/trusted/static-projection.ts +116 -0
  152. package/src/reducer/bundle/trusted/trusted-runtime-args.ts +97 -0
  153. package/src/reducer/bundle/trusted/trusted-runtime-result.ts +39 -0
  154. package/src/reducer/bundle/trusted/trusted-setup-profiles.ts +43 -0
  155. package/src/reducer/bundle/trusted/trusted-state-codec.ts +48 -0
  156. package/src/reducer/bundle/trusted-bundle.ts +97 -0
  157. package/src/reducer/bundle/types.ts +171 -0
  158. package/src/reducer/bundle.ts +2 -0
  159. package/src/reducer/client-param-schemas.ts +57 -0
  160. package/src/reducer/compose.ts +34 -0
  161. package/src/reducer/core/runtime-input.ts +30 -0
  162. package/src/reducer/core/runtime-instruction.ts +59 -0
  163. package/src/reducer/core/types.ts +62 -0
  164. package/src/reducer/definition-index.ts +277 -0
  165. package/src/reducer/derived.ts +106 -0
  166. package/src/reducer/effects.ts +92 -0
  167. package/src/reducer/engine/runtime-instruction-engine.ts +155 -0
  168. package/src/reducer/ingress/decode-runtime-input.ts +7 -0
  169. package/src/reducer/ingress/decode-session-state.ts +9 -0
  170. package/src/reducer/ingress/encode-session-state.ts +6 -0
  171. package/src/reducer/ingress/input-codec.ts +18 -0
  172. package/src/reducer/ingress/phase-schemas.ts +62 -0
  173. package/src/reducer/ingress/raw-types.ts +107 -0
  174. package/src/reducer/ingress/runtime-codec.ts +14 -0
  175. package/src/reducer/ingress/runtime-payload.ts +13 -0
  176. package/src/reducer/ingress/session-codec.ts +392 -0
  177. package/src/reducer/ingress/types.ts +6 -0
  178. package/src/reducer/inputs/boardInput.ts +217 -0
  179. package/src/reducer/inputs/boardTarget.ts +190 -0
  180. package/src/reducer/inputs/cardInput.ts +86 -0
  181. package/src/reducer/inputs/cardTarget.ts +101 -0
  182. package/src/reducer/inputs/choiceTarget.ts +104 -0
  183. package/src/reducer/inputs/defineInputs.ts +71 -0
  184. package/src/reducer/inputs/formInput.ts +809 -0
  185. package/src/reducer/inputs/many.ts +120 -0
  186. package/src/reducer/inputs/promptInput.ts +87 -0
  187. package/src/reducer/inputs/rngInput.ts +58 -0
  188. package/src/reducer/inputs/targetRule.ts +123 -0
  189. package/src/reducer/inputs.ts +41 -0
  190. package/src/reducer/model/definition.ts +1072 -0
  191. package/src/reducer/model/extract.ts +745 -0
  192. package/src/reducer/model/manifest.ts +570 -0
  193. package/src/reducer/model/queries.ts +641 -0
  194. package/src/reducer/model/runtime.ts +264 -0
  195. package/src/reducer/model/spec.ts +1386 -0
  196. package/src/reducer/model/table.ts +260 -0
  197. package/src/reducer/model.ts +7 -0
  198. package/src/reducer/ops.ts +1034 -0
  199. package/src/reducer/parse-utils.ts +28 -0
  200. package/src/reducer/per-player.ts +422 -0
  201. package/src/reducer/rng.ts +69 -0
  202. package/src/reducer/schema-helpers.ts +185 -0
  203. package/src/reducer/setup-bootstrap-helpers.ts +171 -0
  204. package/src/reducer/setup-bootstrap.ts +481 -0
  205. package/src/reducer/table-ops.ts +2671 -0
  206. package/src/reducer/table-queries.ts +372 -0
  207. package/src/reducer/transaction.ts +120 -0
  208. package/src/reducer.ts +314 -0
  209. package/src/runtime/primitives.ts +1 -0
  210. package/src/runtime/types/runtime-api.ts +1 -0
  211. package/src/runtime/workspace-contract.ts +32 -0
  212. package/src/runtime-internal/components/InteractionForm.tsx +1309 -0
  213. package/src/runtime-internal/components/PluginRuntime.tsx +103 -0
  214. package/src/runtime-internal/components/board/target-layer.ts +70 -0
  215. package/src/runtime-internal/context/ClientParamSchemaContext.tsx +44 -0
  216. package/src/runtime-internal/context/InteractionDraftContext.tsx +279 -0
  217. package/src/runtime-internal/context/PluginSessionContext.tsx +47 -0
  218. package/src/runtime-internal/context/PluginStateContext.tsx +262 -0
  219. package/src/runtime-internal/context/RuntimeContext.tsx +96 -0
  220. package/src/runtime-internal/defaults/components.tsx +409 -0
  221. package/src/runtime-internal/defaults/index.ts +11 -0
  222. package/src/runtime-internal/errors/ValidationError.ts +29 -0
  223. package/src/runtime-internal/hooks/useActivePlayers.ts +33 -0
  224. package/src/runtime-internal/hooks/useBoardInteractions.ts +665 -0
  225. package/src/runtime-internal/hooks/useGameSelector.ts +105 -0
  226. package/src/runtime-internal/hooks/useGameView.ts +9 -0
  227. package/src/runtime-internal/hooks/useInteractionByKey.ts +354 -0
  228. package/src/runtime-internal/hooks/useInteractionHandle.ts +438 -0
  229. package/src/runtime-internal/hooks/useIsMyTurn.ts +20 -0
  230. package/src/runtime-internal/hooks/useLobby.ts +76 -0
  231. package/src/runtime-internal/hooks/useMe.ts +48 -0
  232. package/src/runtime-internal/hooks/usePlayerInfo.ts +28 -0
  233. package/src/runtime-internal/hooks/usePlayerTurnOrder.ts +23 -0
  234. package/src/runtime-internal/hooks/usePluginRuntime.ts +147 -0
  235. package/src/runtime-internal/hooks/useSeatInbox.ts +61 -0
  236. package/src/runtime-internal/hooks/useSimultaneousPhase.ts +10 -0
  237. package/src/runtime-internal/index.ts +42 -0
  238. package/src/runtime-internal/internal.ts +43 -0
  239. package/src/runtime-internal/plugin-styles.css +250 -0
  240. package/src/runtime-internal/primitives/board.tsx +459 -0
  241. package/src/runtime-internal/primitives/dialog-lifecycle.ts +58 -0
  242. package/src/runtime-internal/primitives/dice.tsx +79 -0
  243. package/src/runtime-internal/primitives/game-ui-provider.tsx +35 -0
  244. package/src/runtime-internal/primitives/game.tsx +387 -0
  245. package/src/runtime-internal/primitives/hand-intent-adapter.ts +147 -0
  246. package/src/runtime-internal/primitives/hand-surface.tsx +594 -0
  247. package/src/runtime-internal/primitives/index.ts +196 -0
  248. package/src/runtime-internal/primitives/interaction-form-binding.tsx +56 -0
  249. package/src/runtime-internal/primitives/interaction-submit.ts +90 -0
  250. package/src/runtime-internal/primitives/interaction.tsx +987 -0
  251. package/src/runtime-internal/primitives/phase.tsx +43 -0
  252. package/src/runtime-internal/primitives/player-roster.tsx +302 -0
  253. package/src/runtime-internal/primitives/primitive-props.tsx +101 -0
  254. package/src/runtime-internal/primitives/prompt.tsx +255 -0
  255. package/src/runtime-internal/primitives/ui.tsx +60 -0
  256. package/src/runtime-internal/primitives/zone.tsx +791 -0
  257. package/src/runtime-internal/reducer.ts +30 -0
  258. package/src/runtime-internal/runtime/createPluginRuntimeAPI.ts +605 -0
  259. package/src/runtime-internal/types/plugin-state.ts +508 -0
  260. package/src/runtime-internal/types/reducer-state.ts +24 -0
  261. package/src/runtime-internal/types/runtime-api.ts +114 -0
  262. package/src/runtime-internal/ui-contract.ts +519 -0
  263. package/src/runtime-internal/utils/card-intent-adapter.ts +546 -0
  264. package/src/runtime-internal/utils/interaction-inputs.ts +492 -0
  265. package/src/runtime-internal/utils/interaction-labels.ts +23 -0
  266. package/src/runtime-internal/utils/interaction-router.ts +273 -0
  267. package/src/runtime-internal/utils/interaction-status.ts +74 -0
  268. package/src/runtime-internal/workspace-contract.ts +1170 -0
  269. package/src/runtime.ts +34 -0
  270. package/src/testing/create-expect-api.ts +352 -0
  271. package/src/testing/create-test-runtime.ts +381 -0
  272. package/src/testing/definitions.ts +127 -0
  273. package/src/testing/index.ts +3 -0
  274. package/src/testing.ts +1 -0
  275. package/src/type-stubs/manifest-contract.d.ts +42 -0
  276. package/src/type-stubs/manifest-contract.js +72 -0
  277. package/src/type-stubs/ui-contract.d.ts +5 -0
  278. package/src/type-stubs/ui-contract.js +1 -0
  279. package/src/types/authoring-card-properties.type-test.ts +266 -0
  280. package/src/types/authoring.ts +1282 -0
  281. package/src/types/cards.ts +19 -0
  282. package/src/types/contracts.ts +1550 -0
  283. package/src/types/generated-helpers.ts +35 -0
  284. package/src/types/index.ts +147 -0
  285. package/src/types/slots.ts +11 -0
  286. package/src/types.ts +1 -0
  287. package/src/ui/components/ActionButton.tsx +97 -0
  288. package/src/ui/components/ActionPanel.tsx +315 -0
  289. package/src/ui/components/Card.tsx +378 -0
  290. package/src/ui/components/CardDragSurface.tsx +1076 -0
  291. package/src/ui/components/ChromeSuppressionContext.tsx +70 -0
  292. package/src/ui/components/CostDisplay.tsx +145 -0
  293. package/src/ui/components/DiceRoller.tsx +581 -0
  294. package/src/ui/components/Drawer.tsx +180 -0
  295. package/src/ui/components/ErrorBoundary.tsx +275 -0
  296. package/src/ui/components/GameEndDisplay.tsx +398 -0
  297. package/src/ui/components/GameSkeleton.tsx +260 -0
  298. package/src/ui/components/Hand.tsx +468 -0
  299. package/src/ui/components/HandDock.tsx +299 -0
  300. package/src/ui/components/HandView.tsx +441 -0
  301. package/src/ui/components/MobileHandTray.tsx +381 -0
  302. package/src/ui/components/MoreActions.tsx +143 -0
  303. package/src/ui/components/PhaseIndicator.tsx +341 -0
  304. package/src/ui/components/PlayArea.tsx +146 -0
  305. package/src/ui/components/PrimaryActionButton.tsx +336 -0
  306. package/src/ui/components/PrimaryButton.tsx +45 -0
  307. package/src/ui/components/ResourceCounter.tsx +270 -0
  308. package/src/ui/components/StagingZone.tsx +134 -0
  309. package/src/ui/components/ThemedButton.tsx +113 -0
  310. package/src/ui/components/Toast.tsx +264 -0
  311. package/src/ui/components/board/HexGrid.tsx +1294 -0
  312. package/src/ui/components/board/NetworkGraph.tsx +476 -0
  313. package/src/ui/components/board/SlotSystem.tsx +388 -0
  314. package/src/ui/components/board/SquareGrid.tsx +1165 -0
  315. package/src/ui/components/board/TrackBoard.tsx +496 -0
  316. package/src/ui/components/board/ZoneMap.tsx +448 -0
  317. package/src/ui/components/board/hex-board-view.ts +123 -0
  318. package/src/ui/components/board/index.ts +142 -0
  319. package/src/ui/components/board/interaction-accessibility.ts +21 -0
  320. package/src/ui/components/board/target-layer.ts +66 -0
  321. package/src/ui/components/card-render-content.type-test.ts +27 -0
  322. package/src/ui/components/hand-layout-math.ts +163 -0
  323. package/src/ui/components/hand-pointer-engine.ts +413 -0
  324. package/src/ui/components/index.ts +245 -0
  325. package/src/ui/components.ts +1 -0
  326. package/src/ui/defaults/components.tsx +106 -0
  327. package/src/ui/defaults/index.ts +8 -0
  328. package/src/ui/defaults.ts +1 -0
  329. package/src/ui/errors/ValidationError.ts +29 -0
  330. package/src/ui/helpers/cards.ts +19 -0
  331. package/src/ui/helpers/track-board.ts +211 -0
  332. package/src/ui/hooks/useBoardTopology.ts +316 -0
  333. package/src/ui/hooks/useCards.ts +10 -0
  334. package/src/ui/hooks/useHandCardPointer.ts +381 -0
  335. package/src/ui/hooks/useHandLayout.ts +378 -0
  336. package/src/ui/hooks/useHandPresentation.ts +121 -0
  337. package/src/ui/hooks/useHexBoard.ts +74 -0
  338. package/src/ui/hooks/useHexGrid.ts +185 -0
  339. package/src/ui/hooks/useIsMobile.ts +35 -0
  340. package/src/ui/hooks/usePanZoom.ts +278 -0
  341. package/src/ui/hooks/useSquareBoard.ts +124 -0
  342. package/src/ui/hooks/useSquareGrid.ts +328 -0
  343. package/src/ui/index.ts +98 -0
  344. package/src/ui/internal/ui/alert.tsx +51 -0
  345. package/src/ui/internal/ui/button.tsx +58 -0
  346. package/src/ui/internal/ui/dialog.tsx +134 -0
  347. package/src/ui/internal/ui/input.tsx +21 -0
  348. package/src/ui/internal/ui/label.tsx +21 -0
  349. package/src/ui/internal/ui/select.tsx +129 -0
  350. package/src/ui/internal/ui/tooltip.tsx +54 -0
  351. package/src/ui/internal/ui/utils.ts +5 -0
  352. package/src/ui/plugin-styles.css +250 -0
  353. package/src/ui/primitives/dialog-lifecycle.ts +58 -0
  354. package/src/ui/primitives/dice.tsx +79 -0
  355. package/src/ui/primitives/primitive-props.tsx +101 -0
  356. package/src/ui/theme/ThemeProvider.tsx +252 -0
  357. package/src/ui/theme/board.ts +61 -0
  358. package/src/ui/theme/css-vars.ts +105 -0
  359. package/src/ui/theme/derive.ts +240 -0
  360. package/src/ui/theme/index.ts +61 -0
  361. package/src/ui/theme/presets/arcade.ts +261 -0
  362. package/src/ui/theme/presets/studio.ts +261 -0
  363. package/src/ui/theme/presets/tabletop.ts +266 -0
  364. package/src/ui/theme/tokens.ts +392 -0
  365. package/src/ui/types/hex-color.ts +20 -0
  366. package/src/ui/types/player-state.ts +463 -0
  367. package/src/ui/types/tiled-board.ts +785 -0
  368. package/src/ui/types/visual-state.ts +137 -0
  369. package/src/ui.ts +1 -0
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Controlled staging zone — a fixed row of card slots for a many-select
3
+ * collection (e.g. "the cards you are passing"). Filled slots render a
4
+ * caller-provided card and are tappable to remove it; the remaining slots
5
+ * render a themed empty placeholder so the zone is always visible (and always
6
+ * an obvious target) even before anything is staged.
7
+ *
8
+ * Purely presentational: it does not read or mutate any Dreamboard draft. A
9
+ * runtime adapter feeds it the staged cards plus an `onRemove` that toggles the
10
+ * card back out of the collection. In a later slice this same surface becomes
11
+ * the drop target for drag-to-stage.
12
+ */
13
+
14
+ import { clsx } from "clsx";
15
+ import type { ReactNode } from "react";
16
+ import type { ViewCard } from "../../types/index.js";
17
+ import { useTheme } from "../theme/ThemeProvider.js";
18
+
19
+ export interface StagingZoneProps<CardData extends ViewCard = ViewCard> {
20
+ /** Cards currently staged, in order. */
21
+ cards: readonly CardData[];
22
+ /** Total number of slots to render (e.g. the collector's selection max). */
23
+ slotCount: number;
24
+ /** Card size; empty-slot dimensions match the SDK `CardFace` sizes. */
25
+ size?: "sm" | "md" | "lg";
26
+ /** Visual for a staged card (typically a `CardFace`). */
27
+ renderCard: (card: CardData) => ReactNode;
28
+ /** Fires when a staged card is activated — remove it from the collection. */
29
+ onRemove?: (cardId: string) => void;
30
+ /** Custom empty-slot content. Defaults to an empty dashed placeholder. */
31
+ renderEmptySlot?: (index: number) => ReactNode;
32
+ /** Optional heading rendered above the slots. */
33
+ label?: ReactNode;
34
+ /** Accessible label for the region. */
35
+ "aria-label"?: string;
36
+ className?: string;
37
+ }
38
+
39
+ // Match `CardFace`'s `sizeClasses` so empty slots line up with staged cards.
40
+ const SLOT_SIZE_CLASS: Record<"sm" | "md" | "lg", string> = {
41
+ sm: "w-16 h-24 sm:w-20 sm:h-28",
42
+ md: "w-20 h-32 sm:w-24 sm:h-36",
43
+ lg: "w-24 h-36 sm:w-32 sm:h-48",
44
+ };
45
+
46
+ export function StagingZone<CardData extends ViewCard = ViewCard>({
47
+ cards,
48
+ slotCount,
49
+ size = "sm",
50
+ renderCard,
51
+ onRemove,
52
+ renderEmptySlot,
53
+ label,
54
+ "aria-label": ariaLabel = "Staged cards",
55
+ className,
56
+ }: StagingZoneProps<CardData>) {
57
+ const theme = useTheme();
58
+ const total = Math.max(0, slotCount, cards.length);
59
+ const slotClass = SLOT_SIZE_CLASS[size];
60
+ const interactive = Boolean(onRemove);
61
+
62
+ return (
63
+ <div
64
+ data-dreamboard-staging-zone=""
65
+ data-staged-count={cards.length}
66
+ role="group"
67
+ aria-label={ariaLabel}
68
+ className={clsx(
69
+ "flex flex-col items-center gap-2 rounded-2xl px-4 py-3",
70
+ className,
71
+ )}
72
+ style={{
73
+ background: theme.semantic.surface.inset,
74
+ border: `2px solid ${theme.semantic.border.subtle}`,
75
+ }}
76
+ >
77
+ {label != null ? (
78
+ <span
79
+ className="text-[11px] font-bold uppercase tracking-[0.12em]"
80
+ style={{ color: theme.semantic.text.muted }}
81
+ >
82
+ {label}
83
+ </span>
84
+ ) : null}
85
+ <div className="flex items-end justify-center gap-2">
86
+ {Array.from({ length: total }, (_, index) => {
87
+ const card = cards[index];
88
+ if (!card) {
89
+ return (
90
+ <div
91
+ key={`empty-${index}`}
92
+ data-dreamboard-staging-slot="empty"
93
+ aria-hidden
94
+ className={clsx(
95
+ "flex shrink-0 items-center justify-center rounded-xl",
96
+ slotClass,
97
+ )}
98
+ style={{
99
+ border: `2px dashed ${theme.semantic.border.subtle}`,
100
+ color: theme.semantic.text.disabled,
101
+ }}
102
+ >
103
+ {renderEmptySlot ? renderEmptySlot(index) : null}
104
+ </div>
105
+ );
106
+ }
107
+ const cardId = card.id as string;
108
+ return (
109
+ <button
110
+ key={cardId}
111
+ type="button"
112
+ data-dreamboard-staging-slot="filled"
113
+ data-card-id={cardId}
114
+ disabled={!interactive}
115
+ aria-label={
116
+ interactive ? `Remove ${card.name ?? cardId}` : undefined
117
+ }
118
+ onClick={interactive ? () => onRemove?.(cardId) : undefined}
119
+ className={clsx(
120
+ "relative shrink-0 appearance-none border-0 bg-transparent p-0 m-0",
121
+ "transition-transform focus-visible:outline-none",
122
+ interactive
123
+ ? "cursor-pointer hover:-translate-y-1"
124
+ : "cursor-default",
125
+ )}
126
+ >
127
+ {renderCard(card)}
128
+ </button>
129
+ );
130
+ })}
131
+ </div>
132
+ </div>
133
+ );
134
+ }
@@ -0,0 +1,113 @@
1
+ import type { ComponentProps } from "react";
2
+ import { clsx } from "clsx";
3
+ import { Button as ShadcnButton } from "../internal/ui/button.js";
4
+ import {
5
+ buttonStyle,
6
+ type ButtonSize,
7
+ type ButtonVariant,
8
+ } from "../theme/derive.js";
9
+ import { useTheme } from "../theme/ThemeProvider.js";
10
+ import {
11
+ visualStateDataAttributes,
12
+ type InteractionVisualState,
13
+ } from "../types/visual-state.js";
14
+
15
+ type ShadcnButtonProps = ComponentProps<typeof ShadcnButton>;
16
+
17
+ export interface ThemedButtonProps
18
+ extends Omit<ShadcnButtonProps, "variant" | "size">, InteractionVisualState {
19
+ variant?: ButtonVariant;
20
+ size?: ButtonSize;
21
+ /** Renders the pressed/active visual treatment without changing variant. */
22
+ pressed?: boolean;
23
+ /** Render the in-flight loading state and disable activation. */
24
+ loading?: boolean;
25
+ }
26
+
27
+ export function ThemedButton({
28
+ variant = "primary",
29
+ size = "md",
30
+ pressed = false,
31
+ loading = false,
32
+ eligible,
33
+ selected,
34
+ disabled,
35
+ invalid,
36
+ submitted,
37
+ previewing,
38
+ intentProgress,
39
+ className,
40
+ style,
41
+ ...props
42
+ }: ThemedButtonProps) {
43
+ const theme = useTheme();
44
+ const isDisabled = disabled || loading || submitted;
45
+ const dataAttributes = visualStateDataAttributes({
46
+ eligible,
47
+ selected,
48
+ disabled: isDisabled,
49
+ invalid,
50
+ submitted,
51
+ previewing,
52
+ intentProgress,
53
+ });
54
+ return (
55
+ <ShadcnButton
56
+ variant={toShadcnVariant(submitted ? "submitted" : variant)}
57
+ size={toShadcnSize(size)}
58
+ disabled={isDisabled}
59
+ data-dreamboard-button
60
+ data-dreamboard-button-variant={submitted ? "submitted" : variant}
61
+ data-dreamboard-button-size={size}
62
+ data-pressed={pressed ? "true" : undefined}
63
+ data-loading={loading ? "true" : undefined}
64
+ aria-busy={loading || undefined}
65
+ aria-pressed={selected ? true : pressed ? true : undefined}
66
+ aria-invalid={invalid || undefined}
67
+ {...dataAttributes}
68
+ className={clsx("font-sans", className)}
69
+ style={{
70
+ ...buttonStyle(theme, {
71
+ variant: submitted ? "submitted" : variant,
72
+ size,
73
+ disabled: isDisabled,
74
+ pressed,
75
+ }),
76
+ ...style,
77
+ }}
78
+ {...props}
79
+ />
80
+ );
81
+ }
82
+
83
+ function toShadcnVariant(
84
+ variant: ButtonVariant,
85
+ ): NonNullable<ShadcnButtonProps["variant"]> {
86
+ switch (variant) {
87
+ case "danger":
88
+ return "destructive";
89
+ case "ghost":
90
+ return "ghost";
91
+ case "secondary":
92
+ return "secondary";
93
+ case "primary":
94
+ case "submitted":
95
+ case "success":
96
+ case "warning":
97
+ case "info":
98
+ return "default";
99
+ }
100
+ }
101
+
102
+ function toShadcnSize(
103
+ size: ButtonSize,
104
+ ): NonNullable<ShadcnButtonProps["size"]> {
105
+ switch (size) {
106
+ case "sm":
107
+ return "sm";
108
+ case "md":
109
+ return "default";
110
+ case "lg":
111
+ return "lg";
112
+ }
113
+ }
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Plugin-internal toast notification system.
3
+ *
4
+ * `<ToastProvider>` exposes `<Toast.Actions>` for game-specific feedback
5
+ * ("Resource gained", "Card discarded", "Tip: rotate the board with R", …).
6
+ * It is intentionally NOT wired to the host notification stream:
7
+ * `YOUR_TURN`, `PROMPT_OPENED` and `ACTION_REJECTED` events are owned
8
+ * by the product host runtime's `<HostFeedbackToaster>` and must
9
+ * not be mirrored from inside the plugin tree.
10
+ */
11
+
12
+ import { motion, AnimatePresence } from "framer-motion";
13
+ import { X, CheckCircle, AlertCircle, Info, AlertTriangle } from "lucide-react";
14
+ import { Alert, AlertDescription } from "../internal/ui/alert.js";
15
+ import {
16
+ createContext,
17
+ useContext,
18
+ useState,
19
+ useCallback,
20
+ type ReactNode,
21
+ } from "react";
22
+ import { useTheme } from "../theme/ThemeProvider.js";
23
+ import { intentForVariant, type ButtonVariant } from "../theme/derive.js";
24
+ import type { Theme } from "../theme/tokens.js";
25
+ import { ThemedButton } from "./ThemedButton.js";
26
+
27
+ export type ToastType = "success" | "error" | "info" | "warning";
28
+
29
+ export interface ToastNotification {
30
+ id: string;
31
+ type: ToastType;
32
+ message: string;
33
+ duration?: number;
34
+ }
35
+
36
+ interface ToastContextValue {
37
+ toasts: ToastNotification[];
38
+ show: (message: string, type?: ToastType, duration?: number) => void;
39
+ dismiss: (id: string) => void;
40
+ success: (message: string, duration?: number) => void;
41
+ error: (message: string, duration?: number) => void;
42
+ info: (message: string, duration?: number) => void;
43
+ warning: (message: string, duration?: number) => void;
44
+ }
45
+
46
+ const ToastContext = createContext<ToastContextValue | null>(null);
47
+
48
+ export type ToastActionsValue = ToastContextValue;
49
+
50
+ export interface ToastProviderProps {
51
+ children: ReactNode;
52
+ }
53
+
54
+ export function ToastProvider({ children }: ToastProviderProps) {
55
+ const [toasts, setToasts] = useState<ToastNotification[]>([]);
56
+
57
+ const show = useCallback(
58
+ (message: string, type: ToastType = "info", duration = 3000) => {
59
+ const id = `toast-${Date.now()}-${Math.random()}`;
60
+ const toast: ToastNotification = { id, type, message, duration };
61
+
62
+ setToasts((prev) => {
63
+ // Dedup by `(type, message)` so a fast burst of identical
64
+ // toasts collapses to one visible toast instead of stacking
65
+ // and producing the flicker effect (toast-1 dismisses while
66
+ // toast-2 mounts → user sees a flash). Keep the existing
67
+ // entry untouched so its dismiss timer continues.
68
+ if (
69
+ prev.some((item) => item.type === type && item.message === message)
70
+ ) {
71
+ return prev;
72
+ }
73
+ return [...prev, toast];
74
+ });
75
+
76
+ if (duration > 0) {
77
+ setTimeout(() => {
78
+ setToasts((prev) => prev.filter((t) => t.id !== id));
79
+ }, duration);
80
+ }
81
+ },
82
+ [],
83
+ );
84
+
85
+ const dismiss = useCallback((id: string) => {
86
+ setToasts((prev) => prev.filter((t) => t.id !== id));
87
+ }, []);
88
+
89
+ const success = useCallback(
90
+ (message: string, duration?: number) => show(message, "success", duration),
91
+ [show],
92
+ );
93
+ const error = useCallback(
94
+ (message: string, duration?: number) => show(message, "error", duration),
95
+ [show],
96
+ );
97
+ const info = useCallback(
98
+ (message: string, duration?: number) => show(message, "info", duration),
99
+ [show],
100
+ );
101
+ const warning = useCallback(
102
+ (message: string, duration?: number) => show(message, "warning", duration),
103
+ [show],
104
+ );
105
+
106
+ return (
107
+ <ToastContext.Provider
108
+ value={{ toasts, show, dismiss, success, error, info, warning }}
109
+ >
110
+ {children}
111
+ <ToastContainer toasts={toasts} onDismiss={dismiss} />
112
+ </ToastContext.Provider>
113
+ );
114
+ }
115
+
116
+ export function useToast() {
117
+ const context = useContext(ToastContext);
118
+ if (!context) {
119
+ throw new Error("useToast must be used within ToastProvider");
120
+ }
121
+ return context;
122
+ }
123
+
124
+ export interface ToastActionsProps {
125
+ children: (actions: ToastActionsValue) => ReactNode;
126
+ }
127
+
128
+ export function ToastActions({ children }: ToastActionsProps) {
129
+ return <>{children(useToast())}</>;
130
+ }
131
+
132
+ export const Toast = {
133
+ Actions: ToastActions,
134
+ } as const;
135
+
136
+ function ToastContainer({
137
+ toasts,
138
+ onDismiss,
139
+ }: {
140
+ toasts: ToastNotification[];
141
+ onDismiss: (id: string) => void;
142
+ }) {
143
+ return (
144
+ <div
145
+ className="fixed bottom-4 right-4 z-50 flex flex-col gap-2 pointer-events-none"
146
+ role="region"
147
+ aria-live="polite"
148
+ aria-label="Notifications"
149
+ >
150
+ <AnimatePresence>
151
+ {toasts.map((toast) => (
152
+ <ToastItem key={toast.id} toast={toast} onDismiss={onDismiss} />
153
+ ))}
154
+ </AnimatePresence>
155
+ </div>
156
+ );
157
+ }
158
+
159
+ const TOAST_ICONS = {
160
+ success: CheckCircle,
161
+ error: AlertCircle,
162
+ info: Info,
163
+ warning: AlertTriangle,
164
+ } as const satisfies Record<ToastType, unknown>;
165
+
166
+ const TOAST_VARIANT: Record<
167
+ ToastType,
168
+ Exclude<ButtonVariant, "ghost" | "secondary">
169
+ > = {
170
+ success: "success",
171
+ error: "danger",
172
+ info: "info",
173
+ warning: "warning",
174
+ };
175
+
176
+ function toastSurfaceStyle(theme: Theme, type: ToastType): React.CSSProperties {
177
+ const intent = intentForVariant(theme, TOAST_VARIANT[type]);
178
+ return {
179
+ minWidth: 280,
180
+ maxWidth: 400,
181
+ display: "flex",
182
+ alignItems: "flex-start",
183
+ gap: theme.space[3],
184
+ padding: theme.space[4],
185
+ background: intent.soft,
186
+ color: intent.onSoft,
187
+ border: `2px solid ${intent.border}`,
188
+ borderRadius: theme.radius.lg,
189
+ boxShadow: theme.elevation.lifted,
190
+ backdropFilter: "blur(4px)",
191
+ WebkitBackdropFilter: "blur(4px)",
192
+ fontFamily: theme.typography.fontFamily.body,
193
+ };
194
+ }
195
+
196
+ function ToastItem({
197
+ toast,
198
+ onDismiss,
199
+ }: {
200
+ toast: ToastNotification;
201
+ onDismiss: (id: string) => void;
202
+ }) {
203
+ const theme = useTheme();
204
+ const reducedMotion = theme.motion.reducedMotion === "true";
205
+ const Icon = TOAST_ICONS[toast.type];
206
+ const intent = intentForVariant(theme, TOAST_VARIANT[toast.type]);
207
+ const surfaceStyle = toastSurfaceStyle(theme, toast.type);
208
+
209
+ return (
210
+ <motion.div
211
+ style={{ pointerEvents: "auto" }}
212
+ initial={
213
+ reducedMotion ? { opacity: 0 } : { opacity: 0, y: 20, scale: 0.9 }
214
+ }
215
+ animate={reducedMotion ? { opacity: 1 } : { opacity: 1, y: 0, scale: 1 }}
216
+ exit={reducedMotion ? { opacity: 0 } : { opacity: 0, x: 100, scale: 0.9 }}
217
+ transition={{ type: "spring", stiffness: 300, damping: 25 }}
218
+ >
219
+ <Alert
220
+ variant={toast.type === "error" ? "destructive" : "default"}
221
+ style={surfaceStyle}
222
+ >
223
+ <Icon
224
+ size={20}
225
+ style={{
226
+ marginTop: 2,
227
+ flexShrink: 0,
228
+ color: intent.solid,
229
+ }}
230
+ aria-hidden="true"
231
+ />
232
+
233
+ <AlertDescription
234
+ style={{
235
+ flex: 1,
236
+ fontSize: theme.typography.fontSize.sm,
237
+ fontWeight: theme.typography.fontWeight.medium,
238
+ lineHeight: theme.typography.lineHeight.relaxed,
239
+ color: intent.onSoft,
240
+ }}
241
+ >
242
+ {toast.message}
243
+ </AlertDescription>
244
+
245
+ <ThemedButton
246
+ type="button"
247
+ variant="ghost"
248
+ size="sm"
249
+ onClick={() => onDismiss(toast.id)}
250
+ style={{
251
+ height: 28,
252
+ width: 28,
253
+ flexShrink: 0,
254
+ borderRadius: theme.radius.pill,
255
+ color: intent.onSoft,
256
+ }}
257
+ aria-label="Close notification"
258
+ >
259
+ <X size={16} aria-hidden="true" />
260
+ </ThemedButton>
261
+ </Alert>
262
+ </motion.div>
263
+ );
264
+ }