@dreamboard-games/ui-sdk 0.0.41

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 (533) hide show
  1. package/LICENSE +89 -0
  2. package/NOTICE +1 -0
  3. package/README.md +154 -0
  4. package/dist/components/ActionButton.d.ts +13 -0
  5. package/dist/components/ActionButton.d.ts.map +1 -0
  6. package/dist/components/ActionButton.js +14 -0
  7. package/dist/components/ActionPanel.d.ts +33 -0
  8. package/dist/components/ActionPanel.d.ts.map +1 -0
  9. package/dist/components/ActionPanel.js +148 -0
  10. package/dist/components/Card.d.ts +29 -0
  11. package/dist/components/Card.d.ts.map +1 -0
  12. package/dist/components/Card.js +220 -0
  13. package/dist/components/ChromeSuppressionContext.d.ts +7 -0
  14. package/dist/components/ChromeSuppressionContext.d.ts.map +1 -0
  15. package/dist/components/ChromeSuppressionContext.js +34 -0
  16. package/dist/components/CostDisplay.d.ts +22 -0
  17. package/dist/components/CostDisplay.d.ts.map +1 -0
  18. package/dist/components/CostDisplay.js +41 -0
  19. package/dist/components/DiceRoller.d.ts +30 -0
  20. package/dist/components/DiceRoller.d.ts.map +1 -0
  21. package/dist/components/DiceRoller.js +319 -0
  22. package/dist/components/Drawer.d.ts +19 -0
  23. package/dist/components/Drawer.d.ts.map +1 -0
  24. package/dist/components/Drawer.js +55 -0
  25. package/dist/components/ErrorBoundary.d.ts +24 -0
  26. package/dist/components/ErrorBoundary.d.ts.map +1 -0
  27. package/dist/components/ErrorBoundary.js +37 -0
  28. package/dist/components/GameEndDisplay.d.ts +27 -0
  29. package/dist/components/GameEndDisplay.d.ts.map +1 -0
  30. package/dist/components/GameEndDisplay.js +185 -0
  31. package/dist/components/GameSkeleton.d.ts +12 -0
  32. package/dist/components/GameSkeleton.d.ts.map +1 -0
  33. package/dist/components/GameSkeleton.js +54 -0
  34. package/dist/components/Hand.d.ts +99 -0
  35. package/dist/components/Hand.d.ts.map +1 -0
  36. package/dist/components/Hand.js +162 -0
  37. package/dist/components/HandDock.d.ts +35 -0
  38. package/dist/components/HandDock.d.ts.map +1 -0
  39. package/dist/components/HandDock.js +124 -0
  40. package/dist/components/InteractionForm.d.ts +50 -0
  41. package/dist/components/InteractionForm.d.ts.map +1 -0
  42. package/dist/components/InteractionForm.js +402 -0
  43. package/dist/components/MoreActions.d.ts +49 -0
  44. package/dist/components/MoreActions.d.ts.map +1 -0
  45. package/dist/components/MoreActions.js +64 -0
  46. package/dist/components/PhaseIndicator.d.ts +35 -0
  47. package/dist/components/PhaseIndicator.d.ts.map +1 -0
  48. package/dist/components/PhaseIndicator.js +212 -0
  49. package/dist/components/PlayArea.d.ts +28 -0
  50. package/dist/components/PlayArea.d.ts.map +1 -0
  51. package/dist/components/PlayArea.js +48 -0
  52. package/dist/components/PluginRuntime.d.ts +37 -0
  53. package/dist/components/PluginRuntime.d.ts.map +1 -0
  54. package/dist/components/PluginRuntime.js +47 -0
  55. package/dist/components/PrimaryActionButton.d.ts +98 -0
  56. package/dist/components/PrimaryActionButton.d.ts.map +1 -0
  57. package/dist/components/PrimaryActionButton.js +183 -0
  58. package/dist/components/PrimaryButton.d.ts +20 -0
  59. package/dist/components/PrimaryButton.d.ts.map +1 -0
  60. package/dist/components/PrimaryButton.js +5 -0
  61. package/dist/components/PromptDialogHost.d.ts +15 -0
  62. package/dist/components/PromptDialogHost.d.ts.map +1 -0
  63. package/dist/components/PromptDialogHost.js +22 -0
  64. package/dist/components/ResourceCounter.d.ts +38 -0
  65. package/dist/components/ResourceCounter.d.ts.map +1 -0
  66. package/dist/components/ResourceCounter.js +118 -0
  67. package/dist/components/ThemedButton.d.ts +12 -0
  68. package/dist/components/ThemedButton.d.ts.map +1 -0
  69. package/dist/components/ThemedButton.js +38 -0
  70. package/dist/components/Toast.d.ts +35 -0
  71. package/dist/components/Toast.d.ts.map +1 -0
  72. package/dist/components/Toast.js +116 -0
  73. package/dist/components/board/HexGrid.d.ts +344 -0
  74. package/dist/components/board/HexGrid.d.ts.map +1 -0
  75. package/dist/components/board/HexGrid.js +340 -0
  76. package/dist/components/board/NetworkGraph.d.ts +100 -0
  77. package/dist/components/board/NetworkGraph.d.ts.map +1 -0
  78. package/dist/components/board/NetworkGraph.js +123 -0
  79. package/dist/components/board/SlotSystem.d.ts +71 -0
  80. package/dist/components/board/SlotSystem.d.ts.map +1 -0
  81. package/dist/components/board/SlotSystem.js +87 -0
  82. package/dist/components/board/SquareGrid.d.ts +188 -0
  83. package/dist/components/board/SquareGrid.d.ts.map +1 -0
  84. package/dist/components/board/SquareGrid.js +328 -0
  85. package/dist/components/board/TrackBoard.d.ts +113 -0
  86. package/dist/components/board/TrackBoard.d.ts.map +1 -0
  87. package/dist/components/board/TrackBoard.js +135 -0
  88. package/dist/components/board/ZoneMap.d.ts +88 -0
  89. package/dist/components/board/ZoneMap.d.ts.map +1 -0
  90. package/dist/components/board/ZoneMap.js +133 -0
  91. package/dist/components/board/hex-board-view.d.ts +69 -0
  92. package/dist/components/board/hex-board-view.d.ts.map +1 -0
  93. package/dist/components/board/hex-board-view.js +60 -0
  94. package/dist/components/board/index.d.ts +23 -0
  95. package/dist/components/board/index.d.ts.map +1 -0
  96. package/dist/components/board/index.js +40 -0
  97. package/dist/components/board/interaction-accessibility.d.ts +5 -0
  98. package/dist/components/board/interaction-accessibility.d.ts.map +1 -0
  99. package/dist/components/board/interaction-accessibility.js +13 -0
  100. package/dist/components/board/target-layer.d.ts +13 -0
  101. package/dist/components/board/target-layer.d.ts.map +1 -0
  102. package/dist/components/board/target-layer.js +10 -0
  103. package/dist/components/card-render-content.type-test.d.ts +2 -0
  104. package/dist/components/card-render-content.type-test.d.ts.map +1 -0
  105. package/dist/components/card-render-content.type-test.js +1 -0
  106. package/dist/components/index.d.ts +34 -0
  107. package/dist/components/index.d.ts.map +1 -0
  108. package/dist/components/index.js +35 -0
  109. package/dist/components/interaction-dialog-behavior.d.ts +15 -0
  110. package/dist/components/interaction-dialog-behavior.d.ts.map +1 -0
  111. package/dist/components/interaction-dialog-behavior.js +9 -0
  112. package/dist/components/surfaces/BlockerSurface.d.ts +27 -0
  113. package/dist/components/surfaces/BlockerSurface.d.ts.map +1 -0
  114. package/dist/components/surfaces/BlockerSurface.js +38 -0
  115. package/dist/components/surfaces/BoardSurface.d.ts +77 -0
  116. package/dist/components/surfaces/BoardSurface.d.ts.map +1 -0
  117. package/dist/components/surfaces/BoardSurface.js +180 -0
  118. package/dist/components/surfaces/ChromeSurface.d.ts +29 -0
  119. package/dist/components/surfaces/ChromeSurface.d.ts.map +1 -0
  120. package/dist/components/surfaces/ChromeSurface.js +34 -0
  121. package/dist/components/surfaces/ExhaustivenessAudit.d.ts +32 -0
  122. package/dist/components/surfaces/ExhaustivenessAudit.d.ts.map +1 -0
  123. package/dist/components/surfaces/ExhaustivenessAudit.js +65 -0
  124. package/dist/components/surfaces/InboxSurface.d.ts +40 -0
  125. package/dist/components/surfaces/InboxSurface.d.ts.map +1 -0
  126. package/dist/components/surfaces/InboxSurface.js +99 -0
  127. package/dist/components/surfaces/MarketSurface.d.ts +62 -0
  128. package/dist/components/surfaces/MarketSurface.d.ts.map +1 -0
  129. package/dist/components/surfaces/MarketSurface.js +242 -0
  130. package/dist/components/surfaces/PanelSurface.d.ts +111 -0
  131. package/dist/components/surfaces/PanelSurface.d.ts.map +1 -0
  132. package/dist/components/surfaces/PanelSurface.js +180 -0
  133. package/dist/components/surfaces/PlayerCardsSurface.d.ts +104 -0
  134. package/dist/components/surfaces/PlayerCardsSurface.d.ts.map +1 -0
  135. package/dist/components/surfaces/PlayerCardsSurface.js +178 -0
  136. package/dist/components/surfaces/internal/CardZoneFollowUpForm.d.ts +7 -0
  137. package/dist/components/surfaces/internal/CardZoneFollowUpForm.d.ts.map +1 -0
  138. package/dist/components/surfaces/internal/CardZoneFollowUpForm.js +9 -0
  139. package/dist/components/surfaces/internal/DefaultInteractionButton.d.ts +71 -0
  140. package/dist/components/surfaces/internal/DefaultInteractionButton.d.ts.map +1 -0
  141. package/dist/components/surfaces/internal/DefaultInteractionButton.js +82 -0
  142. package/dist/components/surfaces/internal/useCardZoneInteractions.d.ts +21 -0
  143. package/dist/components/surfaces/internal/useCardZoneInteractions.d.ts.map +1 -0
  144. package/dist/components/surfaces/internal/useCardZoneInteractions.js +202 -0
  145. package/dist/components/surfaces/types.d.ts +59 -0
  146. package/dist/components/surfaces/types.d.ts.map +1 -0
  147. package/dist/components/surfaces/types.js +1 -0
  148. package/dist/context/ClientParamSchemaContext.d.ts +21 -0
  149. package/dist/context/ClientParamSchemaContext.d.ts.map +1 -0
  150. package/dist/context/ClientParamSchemaContext.js +12 -0
  151. package/dist/context/InteractionDraftContext.d.ts +69 -0
  152. package/dist/context/InteractionDraftContext.d.ts.map +1 -0
  153. package/dist/context/InteractionDraftContext.js +145 -0
  154. package/dist/context/PluginSessionContext.d.ts +33 -0
  155. package/dist/context/PluginSessionContext.d.ts.map +1 -0
  156. package/dist/context/PluginSessionContext.js +38 -0
  157. package/dist/context/PluginStateContext.d.ts +116 -0
  158. package/dist/context/PluginStateContext.d.ts.map +1 -0
  159. package/dist/context/PluginStateContext.js +186 -0
  160. package/dist/context/RuntimeContext.d.ts +49 -0
  161. package/dist/context/RuntimeContext.d.ts.map +1 -0
  162. package/dist/context/RuntimeContext.js +67 -0
  163. package/dist/defaults/components.d.ts +52 -0
  164. package/dist/defaults/components.d.ts.map +1 -0
  165. package/dist/defaults/components.js +159 -0
  166. package/dist/defaults/index.d.ts +2 -0
  167. package/dist/defaults/index.d.ts.map +1 -0
  168. package/dist/defaults/index.js +1 -0
  169. package/dist/errors/ValidationError.d.ts +10 -0
  170. package/dist/errors/ValidationError.d.ts.map +1 -0
  171. package/dist/errors/ValidationError.js +23 -0
  172. package/dist/helpers/cards.d.ts +3 -0
  173. package/dist/helpers/cards.d.ts.map +1 -0
  174. package/dist/helpers/cards.js +11 -0
  175. package/dist/helpers/track-board.d.ts +79 -0
  176. package/dist/helpers/track-board.d.ts.map +1 -0
  177. package/dist/helpers/track-board.js +56 -0
  178. package/dist/hooks/useActivePlayers.d.ts +16 -0
  179. package/dist/hooks/useActivePlayers.d.ts.map +1 -0
  180. package/dist/hooks/useActivePlayers.js +17 -0
  181. package/dist/hooks/useBoardInteractions.d.ts +110 -0
  182. package/dist/hooks/useBoardInteractions.d.ts.map +1 -0
  183. package/dist/hooks/useBoardInteractions.js +248 -0
  184. package/dist/hooks/useBoardTopology.d.ts +23 -0
  185. package/dist/hooks/useBoardTopology.d.ts.map +1 -0
  186. package/dist/hooks/useBoardTopology.js +128 -0
  187. package/dist/hooks/useCards.d.ts +3 -0
  188. package/dist/hooks/useCards.d.ts.map +1 -0
  189. package/dist/hooks/useCards.js +5 -0
  190. package/dist/hooks/useGameSelector.d.ts +13 -0
  191. package/dist/hooks/useGameSelector.d.ts.map +1 -0
  192. package/dist/hooks/useGameSelector.js +67 -0
  193. package/dist/hooks/useGameView.d.ts +6 -0
  194. package/dist/hooks/useGameView.d.ts.map +1 -0
  195. package/dist/hooks/useGameView.js +7 -0
  196. package/dist/hooks/useHandLayout.d.ts +120 -0
  197. package/dist/hooks/useHandLayout.d.ts.map +1 -0
  198. package/dist/hooks/useHandLayout.js +235 -0
  199. package/dist/hooks/useHexBoard.d.ts +19 -0
  200. package/dist/hooks/useHexBoard.d.ts.map +1 -0
  201. package/dist/hooks/useHexBoard.js +28 -0
  202. package/dist/hooks/useHexGrid.d.ts +56 -0
  203. package/dist/hooks/useHexGrid.d.ts.map +1 -0
  204. package/dist/hooks/useHexGrid.js +112 -0
  205. package/dist/hooks/useInteractionByKey.d.ts +29 -0
  206. package/dist/hooks/useInteractionByKey.d.ts.map +1 -0
  207. package/dist/hooks/useInteractionByKey.js +263 -0
  208. package/dist/hooks/useInteractionHandle.d.ts +103 -0
  209. package/dist/hooks/useInteractionHandle.d.ts.map +1 -0
  210. package/dist/hooks/useInteractionHandle.js +254 -0
  211. package/dist/hooks/useIsMobile.d.ts +7 -0
  212. package/dist/hooks/useIsMobile.d.ts.map +1 -0
  213. package/dist/hooks/useIsMobile.js +29 -0
  214. package/dist/hooks/useIsMyTurn.d.ts +6 -0
  215. package/dist/hooks/useIsMyTurn.d.ts.map +1 -0
  216. package/dist/hooks/useIsMyTurn.js +11 -0
  217. package/dist/hooks/useLobby.d.ts +28 -0
  218. package/dist/hooks/useLobby.d.ts.map +1 -0
  219. package/dist/hooks/useLobby.js +60 -0
  220. package/dist/hooks/useMe.d.ts +11 -0
  221. package/dist/hooks/useMe.d.ts.map +1 -0
  222. package/dist/hooks/useMe.js +32 -0
  223. package/dist/hooks/usePanZoom.d.ts +113 -0
  224. package/dist/hooks/usePanZoom.d.ts.map +1 -0
  225. package/dist/hooks/usePanZoom.js +165 -0
  226. package/dist/hooks/usePlayerInfo.d.ts +4 -0
  227. package/dist/hooks/usePlayerInfo.d.ts.map +1 -0
  228. package/dist/hooks/usePlayerInfo.js +21 -0
  229. package/dist/hooks/usePlayerTurnOrder.d.ts +15 -0
  230. package/dist/hooks/usePlayerTurnOrder.d.ts.map +1 -0
  231. package/dist/hooks/usePlayerTurnOrder.js +22 -0
  232. package/dist/hooks/usePluginRuntime.d.ts +45 -0
  233. package/dist/hooks/usePluginRuntime.d.ts.map +1 -0
  234. package/dist/hooks/usePluginRuntime.js +92 -0
  235. package/dist/hooks/useSeatInbox.d.ts +22 -0
  236. package/dist/hooks/useSeatInbox.d.ts.map +1 -0
  237. package/dist/hooks/useSeatInbox.js +43 -0
  238. package/dist/hooks/useSimultaneousPhase.d.ts +7 -0
  239. package/dist/hooks/useSimultaneousPhase.d.ts.map +1 -0
  240. package/dist/hooks/useSimultaneousPhase.js +8 -0
  241. package/dist/hooks/useSquareBoard.d.ts +21 -0
  242. package/dist/hooks/useSquareBoard.d.ts.map +1 -0
  243. package/dist/hooks/useSquareBoard.js +67 -0
  244. package/dist/hooks/useSquareGrid.d.ts +96 -0
  245. package/dist/hooks/useSquareGrid.d.ts.map +1 -0
  246. package/dist/hooks/useSquareGrid.js +152 -0
  247. package/dist/index.d.ts +30 -0
  248. package/dist/index.d.ts.map +1 -0
  249. package/dist/index.js +20 -0
  250. package/dist/internal/ui/alert.d.ts +8 -0
  251. package/dist/internal/ui/alert.d.ts.map +1 -0
  252. package/dist/internal/ui/alert.js +11 -0
  253. package/dist/internal/ui/button.d.ts +10 -0
  254. package/dist/internal/ui/button.d.ts.map +1 -0
  255. package/dist/internal/ui/button.js +21 -0
  256. package/dist/internal/ui/dialog.d.ts +16 -0
  257. package/dist/internal/ui/dialog.d.ts.map +1 -0
  258. package/dist/internal/ui/dialog.js +35 -0
  259. package/dist/internal/ui/input.d.ts +3 -0
  260. package/dist/internal/ui/input.d.ts.map +1 -0
  261. package/dist/internal/ui/input.js +5 -0
  262. package/dist/internal/ui/label.d.ts +4 -0
  263. package/dist/internal/ui/label.d.ts.map +1 -0
  264. package/dist/internal/ui/label.js +7 -0
  265. package/dist/internal/ui/select.d.ts +9 -0
  266. package/dist/internal/ui/select.d.ts.map +1 -0
  267. package/dist/internal/ui/select.js +23 -0
  268. package/dist/internal/ui/tooltip.d.ts +7 -0
  269. package/dist/internal/ui/tooltip.d.ts.map +1 -0
  270. package/dist/internal/ui/tooltip.js +16 -0
  271. package/dist/internal/ui/utils.d.ts +3 -0
  272. package/dist/internal/ui/utils.d.ts.map +1 -0
  273. package/dist/internal/ui/utils.js +4 -0
  274. package/dist/internal.d.ts +7 -0
  275. package/dist/internal.d.ts.map +1 -0
  276. package/dist/internal.js +4 -0
  277. package/dist/plugin-styles.css +246 -0
  278. package/dist/primitives/board.d.ts +29 -0
  279. package/dist/primitives/board.d.ts.map +1 -0
  280. package/dist/primitives/board.js +163 -0
  281. package/dist/primitives/game-ui-provider.d.ts +12 -0
  282. package/dist/primitives/game-ui-provider.d.ts.map +1 -0
  283. package/dist/primitives/game-ui-provider.js +7 -0
  284. package/dist/primitives/index.d.ts +8 -0
  285. package/dist/primitives/index.d.ts.map +1 -0
  286. package/dist/primitives/index.js +7 -0
  287. package/dist/primitives/interaction.d.ts +52 -0
  288. package/dist/primitives/interaction.d.ts.map +1 -0
  289. package/dist/primitives/interaction.js +250 -0
  290. package/dist/primitives/phase.d.ts +15 -0
  291. package/dist/primitives/phase.d.ts.map +1 -0
  292. package/dist/primitives/phase.js +18 -0
  293. package/dist/primitives/player-roster.d.ts +64 -0
  294. package/dist/primitives/player-roster.d.ts.map +1 -0
  295. package/dist/primitives/player-roster.js +149 -0
  296. package/dist/primitives/primitive-props.d.ts +15 -0
  297. package/dist/primitives/primitive-props.d.ts.map +1 -0
  298. package/dist/primitives/primitive-props.js +39 -0
  299. package/dist/primitives/prompt.d.ts +44 -0
  300. package/dist/primitives/prompt.d.ts.map +1 -0
  301. package/dist/primitives/prompt.js +101 -0
  302. package/dist/primitives/zone.d.ts +31 -0
  303. package/dist/primitives/zone.d.ts.map +1 -0
  304. package/dist/primitives/zone.js +58 -0
  305. package/dist/reducer.d.ts +21 -0
  306. package/dist/reducer.d.ts.map +1 -0
  307. package/dist/reducer.js +14 -0
  308. package/dist/runtime/createPluginRuntimeAPI.d.ts +67 -0
  309. package/dist/runtime/createPluginRuntimeAPI.d.ts.map +1 -0
  310. package/dist/runtime/createPluginRuntimeAPI.js +419 -0
  311. package/dist/theme/ThemeProvider.d.ts +98 -0
  312. package/dist/theme/ThemeProvider.d.ts.map +1 -0
  313. package/dist/theme/ThemeProvider.js +148 -0
  314. package/dist/theme/board.d.ts +42 -0
  315. package/dist/theme/board.d.ts.map +1 -0
  316. package/dist/theme/board.js +34 -0
  317. package/dist/theme/css-vars.d.ts +31 -0
  318. package/dist/theme/css-vars.d.ts.map +1 -0
  319. package/dist/theme/css-vars.js +88 -0
  320. package/dist/theme/derive.d.ts +66 -0
  321. package/dist/theme/derive.d.ts.map +1 -0
  322. package/dist/theme/derive.js +161 -0
  323. package/dist/theme/index.d.ts +22 -0
  324. package/dist/theme/index.d.ts.map +1 -0
  325. package/dist/theme/index.js +20 -0
  326. package/dist/theme/presets/arcade.d.ts +10 -0
  327. package/dist/theme/presets/arcade.d.ts.map +1 -0
  328. package/dist/theme/presets/arcade.js +257 -0
  329. package/dist/theme/presets/studio.d.ts +10 -0
  330. package/dist/theme/presets/studio.d.ts.map +1 -0
  331. package/dist/theme/presets/studio.js +257 -0
  332. package/dist/theme/presets/tabletop.d.ts +15 -0
  333. package/dist/theme/presets/tabletop.d.ts.map +1 -0
  334. package/dist/theme/presets/tabletop.js +262 -0
  335. package/dist/theme/tokens.d.ts +345 -0
  336. package/dist/theme/tokens.d.ts.map +1 -0
  337. package/dist/theme/tokens.js +57 -0
  338. package/dist/types/player-state.d.ts +337 -0
  339. package/dist/types/player-state.d.ts.map +1 -0
  340. package/dist/types/player-state.js +1 -0
  341. package/dist/types/plugin-state.d.ts +324 -0
  342. package/dist/types/plugin-state.d.ts.map +1 -0
  343. package/dist/types/plugin-state.js +1 -0
  344. package/dist/types/reducer-state.d.ts +10 -0
  345. package/dist/types/reducer-state.d.ts.map +1 -0
  346. package/dist/types/reducer-state.js +1 -0
  347. package/dist/types/runtime-api.d.ts +99 -0
  348. package/dist/types/runtime-api.d.ts.map +1 -0
  349. package/dist/types/runtime-api.js +1 -0
  350. package/dist/types/tiled-board.d.ts +187 -0
  351. package/dist/types/tiled-board.d.ts.map +1 -0
  352. package/dist/types/tiled-board.js +226 -0
  353. package/dist/ui-contract.d.ts +78 -0
  354. package/dist/ui-contract.d.ts.map +1 -0
  355. package/dist/ui-contract.js +15 -0
  356. package/dist/ui-sdk.d.ts +3409 -0
  357. package/dist/utils/interaction-inputs.d.ts +22 -0
  358. package/dist/utils/interaction-inputs.d.ts.map +1 -0
  359. package/dist/utils/interaction-inputs.js +219 -0
  360. package/dist/utils/interaction-labels.d.ts +4 -0
  361. package/dist/utils/interaction-labels.d.ts.map +1 -0
  362. package/dist/utils/interaction-labels.js +18 -0
  363. package/dist/utils/interaction-status.d.ts +15 -0
  364. package/dist/utils/interaction-status.d.ts.map +1 -0
  365. package/dist/utils/interaction-status.js +31 -0
  366. package/package.json +101 -0
  367. package/src/components/ActionButton.tsx +48 -0
  368. package/src/components/ActionPanel.tsx +310 -0
  369. package/src/components/Card.tsx +385 -0
  370. package/src/components/ChromeSuppressionContext.tsx +70 -0
  371. package/src/components/CostDisplay.test.tsx +23 -0
  372. package/src/components/CostDisplay.tsx +145 -0
  373. package/src/components/DiceRoller.tsx +601 -0
  374. package/src/components/Drawer.tsx +179 -0
  375. package/src/components/ErrorBoundary.tsx +119 -0
  376. package/src/components/GameEndDisplay.test.tsx +19 -0
  377. package/src/components/GameEndDisplay.tsx +398 -0
  378. package/src/components/GameSkeleton.tsx +260 -0
  379. package/src/components/Hand.tsx +387 -0
  380. package/src/components/HandDock.tsx +257 -0
  381. package/src/components/InteractionForm.test.tsx +303 -0
  382. package/src/components/InteractionForm.tsx +1029 -0
  383. package/src/components/MoreActions.test.tsx +93 -0
  384. package/src/components/MoreActions.tsx +143 -0
  385. package/src/components/PhaseIndicator.tsx +341 -0
  386. package/src/components/PlayArea.tsx +125 -0
  387. package/src/components/PluginRuntime.tsx +92 -0
  388. package/src/components/PrimaryActionButton.test.tsx +138 -0
  389. package/src/components/PrimaryActionButton.tsx +351 -0
  390. package/src/components/PrimaryButton.tsx +44 -0
  391. package/src/components/PromptDialogHost.tsx +92 -0
  392. package/src/components/ResourceCounter.test.tsx +29 -0
  393. package/src/components/ResourceCounter.tsx +275 -0
  394. package/src/components/ThemedButton.tsx +78 -0
  395. package/src/components/Toast.tsx +251 -0
  396. package/src/components/__fixtures__/ActionButton.fixture.tsx +234 -0
  397. package/src/components/__fixtures__/ActionPanel.fixture.tsx +298 -0
  398. package/src/components/__fixtures__/Card.fixture.tsx +185 -0
  399. package/src/components/__fixtures__/CostDisplay.fixture.tsx +156 -0
  400. package/src/components/__fixtures__/DiceRoller.fixture.tsx +435 -0
  401. package/src/components/__fixtures__/Drawer.fixture.tsx +113 -0
  402. package/src/components/__fixtures__/ErrorBoundary.fixture.tsx +82 -0
  403. package/src/components/__fixtures__/GameEndDisplay.fixture.tsx +188 -0
  404. package/src/components/__fixtures__/GameSkeleton.fixture.tsx +46 -0
  405. package/src/components/__fixtures__/Hand.fixture.tsx +522 -0
  406. package/src/components/__fixtures__/HexGrid.fixture.tsx +1181 -0
  407. package/src/components/__fixtures__/NetworkGraph.fixture.tsx +599 -0
  408. package/src/components/__fixtures__/PhaseIndicator.fixture.tsx +181 -0
  409. package/src/components/__fixtures__/PlayArea.fixture.tsx +221 -0
  410. package/src/components/__fixtures__/ResourceCounter.fixture.tsx +227 -0
  411. package/src/components/__fixtures__/SlotSystem.fixture.tsx +824 -0
  412. package/src/components/__fixtures__/SquareGrid.fixture.tsx +764 -0
  413. package/src/components/__fixtures__/Toast.fixture.tsx +97 -0
  414. package/src/components/__fixtures__/TrackBoard.fixture.tsx +685 -0
  415. package/src/components/__fixtures__/ZoneMap.fixture.tsx +754 -0
  416. package/src/components/board/HexGrid.tsx +1294 -0
  417. package/src/components/board/NetworkGraph.tsx +476 -0
  418. package/src/components/board/SlotSystem.tsx +339 -0
  419. package/src/components/board/SquareGrid.tsx +1165 -0
  420. package/src/components/board/TrackBoard.tsx +496 -0
  421. package/src/components/board/ZoneMap.tsx +448 -0
  422. package/src/components/board/hex-board-view.test.tsx +114 -0
  423. package/src/components/board/hex-board-view.ts +123 -0
  424. package/src/components/board/index.ts +142 -0
  425. package/src/components/board/interaction-accessibility.ts +21 -0
  426. package/src/components/board/target-layer-grids.test.tsx +420 -0
  427. package/src/components/board/target-layer.ts +30 -0
  428. package/src/components/card-render-content.type-test.ts +27 -0
  429. package/src/components/index.ts +208 -0
  430. package/src/components/interaction-dialog-behavior.test.ts +23 -0
  431. package/src/components/interaction-dialog-behavior.ts +22 -0
  432. package/src/components/surfaces/BlockerSurface.test.tsx +158 -0
  433. package/src/components/surfaces/BlockerSurface.tsx +127 -0
  434. package/src/components/surfaces/BoardSurface.tsx +340 -0
  435. package/src/components/surfaces/ChromeSurface.tsx +123 -0
  436. package/src/components/surfaces/ExhaustivenessAudit.tsx +91 -0
  437. package/src/components/surfaces/InboxSurface.test.tsx +149 -0
  438. package/src/components/surfaces/InboxSurface.tsx +245 -0
  439. package/src/components/surfaces/MarketSurface.tsx +544 -0
  440. package/src/components/surfaces/PanelSurface.test.tsx +496 -0
  441. package/src/components/surfaces/PanelSurface.tsx +458 -0
  442. package/src/components/surfaces/PlayerCardsSurface.tsx +525 -0
  443. package/src/components/surfaces/internal/CardZoneFollowUpForm.tsx +35 -0
  444. package/src/components/surfaces/internal/DefaultInteractionButton.tsx +219 -0
  445. package/src/components/surfaces/internal/useCardZoneInteractions.ts +311 -0
  446. package/src/components/surfaces/types.ts +100 -0
  447. package/src/context/ClientParamSchemaContext.tsx +44 -0
  448. package/src/context/InteractionDraftContext.tsx +204 -0
  449. package/src/context/PluginSessionContext.tsx +47 -0
  450. package/src/context/PluginStateContext.tsx +254 -0
  451. package/src/context/RuntimeContext.tsx +96 -0
  452. package/src/defaults/components.tsx +442 -0
  453. package/src/defaults/defaults.test.tsx +230 -0
  454. package/src/defaults/index.ts +1 -0
  455. package/src/errors/ValidationError.ts +29 -0
  456. package/src/helpers/cards.ts +19 -0
  457. package/src/helpers/track-board.ts +211 -0
  458. package/src/hooks/useActivePlayers.ts +19 -0
  459. package/src/hooks/useBoardInteractions.test.tsx +622 -0
  460. package/src/hooks/useBoardInteractions.ts +434 -0
  461. package/src/hooks/useBoardTopology.ts +316 -0
  462. package/src/hooks/useCards.test.tsx +129 -0
  463. package/src/hooks/useCards.ts +10 -0
  464. package/src/hooks/useGameSelector.ts +105 -0
  465. package/src/hooks/useGameView.ts +9 -0
  466. package/src/hooks/useHandLayout.ts +349 -0
  467. package/src/hooks/useHexBoard.ts +74 -0
  468. package/src/hooks/useHexGrid.ts +185 -0
  469. package/src/hooks/useInteractionByKey.ts +349 -0
  470. package/src/hooks/useInteractionHandle.ts +437 -0
  471. package/src/hooks/useIsMobile.ts +35 -0
  472. package/src/hooks/useIsMyTurn.test.tsx +99 -0
  473. package/src/hooks/useIsMyTurn.ts +15 -0
  474. package/src/hooks/useLobby.ts +76 -0
  475. package/src/hooks/useMe.ts +48 -0
  476. package/src/hooks/usePanZoom.ts +278 -0
  477. package/src/hooks/usePlayerInfo.ts +28 -0
  478. package/src/hooks/usePlayerTurnOrder.ts +23 -0
  479. package/src/hooks/usePluginRuntime.test.tsx +102 -0
  480. package/src/hooks/usePluginRuntime.ts +130 -0
  481. package/src/hooks/useSeatInbox.ts +61 -0
  482. package/src/hooks/useSimultaneousPhase.ts +10 -0
  483. package/src/hooks/useSquareBoard.ts +124 -0
  484. package/src/hooks/useSquareGrid.ts +328 -0
  485. package/src/index.test.ts +474 -0
  486. package/src/index.ts +148 -0
  487. package/src/internal/ui/alert.tsx +51 -0
  488. package/src/internal/ui/button.tsx +58 -0
  489. package/src/internal/ui/dialog.tsx +134 -0
  490. package/src/internal/ui/input.tsx +21 -0
  491. package/src/internal/ui/label.tsx +21 -0
  492. package/src/internal/ui/select.tsx +129 -0
  493. package/src/internal/ui/tooltip.tsx +54 -0
  494. package/src/internal/ui/utils.ts +5 -0
  495. package/src/internal.ts +18 -0
  496. package/src/plugin-styles.css +246 -0
  497. package/src/primitives/board.test.tsx +139 -0
  498. package/src/primitives/board.tsx +267 -0
  499. package/src/primitives/game-ui-provider.tsx +35 -0
  500. package/src/primitives/index.ts +83 -0
  501. package/src/primitives/interaction.test.tsx +420 -0
  502. package/src/primitives/interaction.tsx +405 -0
  503. package/src/primitives/phase.test.tsx +82 -0
  504. package/src/primitives/phase.tsx +43 -0
  505. package/src/primitives/player-roster.test.tsx +168 -0
  506. package/src/primitives/player-roster.tsx +301 -0
  507. package/src/primitives/primitive-props.tsx +82 -0
  508. package/src/primitives/prompt.test.tsx +159 -0
  509. package/src/primitives/prompt.tsx +203 -0
  510. package/src/primitives/zone.tsx +113 -0
  511. package/src/reducer.ts +42 -0
  512. package/src/runtime/createPluginRuntimeAPI.ts +605 -0
  513. package/src/theme/ThemeProvider.test.tsx +36 -0
  514. package/src/theme/ThemeProvider.tsx +252 -0
  515. package/src/theme/board.ts +61 -0
  516. package/src/theme/css-vars.ts +105 -0
  517. package/src/theme/derive.ts +240 -0
  518. package/src/theme/index.ts +61 -0
  519. package/src/theme/presets/arcade.ts +261 -0
  520. package/src/theme/presets/studio.ts +261 -0
  521. package/src/theme/presets/tabletop.ts +266 -0
  522. package/src/theme/theme.test.ts +258 -0
  523. package/src/theme/tokens.ts +392 -0
  524. package/src/types/player-state.ts +445 -0
  525. package/src/types/plugin-state.ts +407 -0
  526. package/src/types/reducer-state.ts +24 -0
  527. package/src/types/runtime-api.ts +114 -0
  528. package/src/types/tiled-board.ts +785 -0
  529. package/src/ui-contract.ts +168 -0
  530. package/src/utils/interaction-inputs.test.ts +109 -0
  531. package/src/utils/interaction-inputs.ts +331 -0
  532. package/src/utils/interaction-labels.ts +23 -0
  533. package/src/utils/interaction-status.ts +59 -0
@@ -0,0 +1,32 @@
1
+ import type { SurfaceRenderMap } from "./types.js";
2
+ /**
3
+ * Per-surface renderer maps the shell is currently using. `undefined`
4
+ * values are treated as "use the surface's default renderer".
5
+ */
6
+ export interface ExhaustivenessAuditProps {
7
+ panel?: SurfaceRenderMap<string>;
8
+ handledInteractionKeys?: readonly string[];
9
+ inbox?: SurfaceRenderMap<string>;
10
+ chrome?: SurfaceRenderMap<string>;
11
+ blocker?: SurfaceRenderMap<string>;
12
+ board?: SurfaceRenderMap<string>;
13
+ }
14
+ /**
15
+ * Development-only runtime audit that logs a single grouped warning per
16
+ * mount describing which interaction ids are currently projected onto the
17
+ * seat's inbox but do not have an explicit renderer override in the
18
+ * supplied render maps. Useful for catching "oops, I wired a new
19
+ * interaction but forgot to render it" regressions before CI notices.
20
+ *
21
+ * In production builds (`process.env.NODE_ENV === "production"`) this
22
+ * component is a no-op.
23
+ *
24
+ * ```tsx
25
+ * <ExhaustivenessAudit
26
+ * panel={panelRenderers}
27
+ * inbox={inboxRenderers}
28
+ * />
29
+ * ```
30
+ */
31
+ export declare function ExhaustivenessAudit(props: ExhaustivenessAuditProps): null;
32
+ //# sourceMappingURL=ExhaustivenessAudit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExhaustivenessAudit.d.ts","sourceRoot":"","sources":["../../../src/components/surfaces/ExhaustivenessAudit.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACjC,sBAAsB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,KAAK,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;CAClC;AAQD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,QAkDlE"}
@@ -0,0 +1,65 @@
1
+ import { useEffect } from "react";
2
+ import { useSeatInbox } from "../../hooks/useSeatInbox.js";
3
+ const AUDITED_BUCKETS = ["panel", "inbox", "chrome", "blocker", "board"];
4
+ /**
5
+ * Development-only runtime audit that logs a single grouped warning per
6
+ * mount describing which interaction ids are currently projected onto the
7
+ * seat's inbox but do not have an explicit renderer override in the
8
+ * supplied render maps. Useful for catching "oops, I wired a new
9
+ * interaction but forgot to render it" regressions before CI notices.
10
+ *
11
+ * In production builds (`process.env.NODE_ENV === "production"`) this
12
+ * component is a no-op.
13
+ *
14
+ * ```tsx
15
+ * <ExhaustivenessAudit
16
+ * panel={panelRenderers}
17
+ * inbox={inboxRenderers}
18
+ * />
19
+ * ```
20
+ */
21
+ export function ExhaustivenessAudit(props) {
22
+ const inbox = useSeatInbox();
23
+ useEffect(() => {
24
+ const proc = globalThis
25
+ .process;
26
+ if (!proc)
27
+ return;
28
+ if (proc.env?.NODE_ENV === "production")
29
+ return;
30
+ const unhandled = [];
31
+ const handledInteractionKeys = new Set(props.handledInteractionKeys ?? []);
32
+ for (const bucket of AUDITED_BUCKETS) {
33
+ const bySurface = bucket === "board"
34
+ ? [
35
+ ...(inbox.bySurface["board-vertex"] ?? []),
36
+ ...(inbox.bySurface["board-edge"] ?? []),
37
+ ...(inbox.bySurface["board-tile"] ?? []),
38
+ ...(inbox.bySurface["board-space"] ?? []),
39
+ ]
40
+ : (inbox.bySurface[bucket] ?? []);
41
+ const map = props[bucket];
42
+ for (const descriptor of bySurface) {
43
+ if (handledInteractionKeys.has(descriptor.interactionKey))
44
+ continue;
45
+ if (!map || !(descriptor.interactionKey in map)) {
46
+ unhandled.push({
47
+ surface: bucket,
48
+ interactionId: descriptor.interactionId,
49
+ });
50
+ }
51
+ }
52
+ }
53
+ if (unhandled.length === 0)
54
+ return;
55
+ // eslint-disable-next-line no-console -- dev-only audit
56
+ console.groupCollapsed(`[dreamboard/ui-sdk] ExhaustivenessAudit: ${unhandled.length} interaction(s) fell through to the default renderer`);
57
+ for (const entry of unhandled) {
58
+ // eslint-disable-next-line no-console -- dev-only audit
59
+ console.warn(`${entry.surface} · ${entry.interactionId}`);
60
+ }
61
+ // eslint-disable-next-line no-console -- dev-only audit
62
+ console.groupEnd();
63
+ }, [inbox, props]);
64
+ return null;
65
+ }
@@ -0,0 +1,40 @@
1
+ import { type ReactNode } from "react";
2
+ import { type InteractionHandle } from "../../hooks/useInteractionHandle.js";
3
+ import type { InteractionDescriptor } from "../../types/plugin-state.js";
4
+ import type { InteractionDefaultedKeysOf, InteractionParamsByKeyShape, InteractionParamsOf, SurfaceRenderMap } from "./types.js";
5
+ export interface InboxSurfaceProps<I extends string = never, ParamsByKey extends Partial<InteractionParamsByKeyShape> = {}> {
6
+ /**
7
+ * Optional per-interaction overrides. Most prompt-kind interactions do not
8
+ * need this: if the authored spec declares `options`, the default renderer
9
+ * draws one button per option and auto-submits on click. Provide a
10
+ * renderer here to fully replace the default UI for a specific prompt id.
11
+ */
12
+ render?: SurfaceRenderMap<I, ParamsByKey>;
13
+ /**
14
+ * Fallback renderer for inbox items without an entry in `render`. Called
15
+ * whenever the default option-button layout doesn't fit — e.g., when a
16
+ * prompt has no `context.options`. Defaults to the standard
17
+ * `DefaultInteractionButton` which surfaces `label`, `icon`, `emphasis`,
18
+ * and `unavailableReason`.
19
+ */
20
+ renderItem?: (descriptor: InteractionDescriptor<I>, handle: InteractionHandle<InteractionParamsOf<ParamsByKey, I>, InteractionDefaultedKeysOf<ParamsByKey, I>>) => ReactNode;
21
+ /** Shown when no inbox items are addressed to the controlling seat. */
22
+ empty?: ReactNode;
23
+ /** Interaction keys intentionally rendered elsewhere, such as dialog groups. */
24
+ excludeInteractionKeys?: readonly string[];
25
+ }
26
+ /**
27
+ * Default renderer for `surface: "inbox"` interactions and prompt-kind
28
+ * interactions addressed to the controlling seat.
29
+ *
30
+ * Prompt-kind interactions with an authored `options` list are rendered
31
+ * as a titled group of buttons; clicking a button submits the
32
+ * interaction with `{ [firstInputKey]: option.id }`. Action-kind inbox
33
+ * items fall back to the default button. Provide `render` to override
34
+ * rendering for a specific interaction id.
35
+ *
36
+ * Visual styling is sourced entirely from the active {@link useTheme}
37
+ * — there is no per-call style override.
38
+ */
39
+ export declare function InboxSurface<I extends string = never, ParamsByKey extends Partial<InteractionParamsByKeyShape> = {}>({ render, renderItem, empty, excludeInteractionKeys, }: InboxSurfaceProps<I, ParamsByKey>): import("react/jsx-runtime").JSX.Element;
40
+ //# sourceMappingURL=InboxSurface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InboxSurface.d.ts","sourceRoot":"","sources":["../../../src/components/surfaces/InboxSurface.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEjD,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,qCAAqC,CAAC;AAG7C,OAAO,KAAK,EAEV,qBAAqB,EACtB,MAAM,6BAA6B,CAAC;AAKrC,OAAO,KAAK,EACV,0BAA0B,EAC1B,2BAA2B,EAC3B,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,iBAAiB,CAChC,CAAC,SAAS,MAAM,GAAG,KAAK,EACxB,WAAW,SAAS,OAAO,CAAC,2BAA2B,CAAC,GAAG,EAAE;IAE7D;;;;;OAKG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IAC1C;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,CACX,UAAU,EAAE,qBAAqB,CAAC,CAAC,CAAC,EACpC,MAAM,EAAE,iBAAiB,CACvB,mBAAmB,CAAC,WAAW,EAAE,CAAC,CAAC,EACnC,0BAA0B,CAAC,WAAW,EAAE,CAAC,CAAC,CAC3C,KACE,SAAS,CAAC;IACf,uEAAuE;IACvE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,gFAAgF;IAChF,sBAAsB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,CAAC,SAAS,MAAM,GAAG,KAAK,EACxB,WAAW,SAAS,OAAO,CAAC,2BAA2B,CAAC,GAAG,EAAE,EAC7D,EACA,MAAM,EACN,UAAU,EACV,KAAY,EACZ,sBAAsB,GACvB,EAAE,iBAAiB,CAAC,CAAC,EAAE,WAAW,CAAC,2CA4BnC"}
@@ -0,0 +1,99 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { useSeatInbox } from "../../hooks/useSeatInbox.js";
4
+ import { useInteractionHandle, } from "../../hooks/useInteractionHandle.js";
5
+ import { surfaceStyle } from "../../theme/derive.js";
6
+ import { useTheme } from "../../theme/ThemeProvider.js";
7
+ import { interactionInputKeys } from "../../utils/interaction-inputs.js";
8
+ import { interactionLabel } from "../../utils/interaction-labels.js";
9
+ import { DefaultInteractionButton } from "./internal/DefaultInteractionButton.js";
10
+ import { ThemedButton } from "../ThemedButton.js";
11
+ /**
12
+ * Default renderer for `surface: "inbox"` interactions and prompt-kind
13
+ * interactions addressed to the controlling seat.
14
+ *
15
+ * Prompt-kind interactions with an authored `options` list are rendered
16
+ * as a titled group of buttons; clicking a button submits the
17
+ * interaction with `{ [firstInputKey]: option.id }`. Action-kind inbox
18
+ * items fall back to the default button. Provide `render` to override
19
+ * rendering for a specific interaction id.
20
+ *
21
+ * Visual styling is sourced entirely from the active {@link useTheme}
22
+ * — there is no per-call style override.
23
+ */
24
+ export function InboxSurface({ render, renderItem, empty = null, excludeInteractionKeys, }) {
25
+ const inbox = useSeatInbox();
26
+ const excluded = new Set(excludeInteractionKeys ?? []);
27
+ // Prompt-kind descriptors always carry `surface: "inbox"` (enforced by
28
+ // the trusted bundle), so `bySurface.inbox` is the unified list of
29
+ // inbox interactions regardless of origin. Rendering off this single
30
+ // bucket keeps action-kind and prompt-kind inbox items on equal
31
+ // footing — the old "prompts first, action-kind fallback" branch
32
+ // silently dropped action-kind items whenever any prompt was active.
33
+ const items = (inbox.bySurface.inbox ?? []);
34
+ const visibleItems = items.filter((descriptor) => !excluded.has(descriptor.interactionKey));
35
+ if (visibleItems.length === 0)
36
+ return _jsx(_Fragment, { children: empty });
37
+ return (_jsx(_Fragment, { children: visibleItems.map((descriptor) => (_jsx(InboxItem, { descriptor: descriptor, render: render, renderItem: renderItem }, descriptor.interactionKey))) }));
38
+ }
39
+ function InboxItem({ descriptor, render, renderItem, }) {
40
+ const handle = useInteractionHandle(descriptor);
41
+ const override = render?.[descriptor.interactionKey];
42
+ if (override)
43
+ return _jsx(_Fragment, { children: override(descriptor, handle) });
44
+ const options = descriptor.context?.options;
45
+ if (descriptor.kind === "prompt" && options && options.length > 0) {
46
+ return (_jsx(PromptOptionsCard, { descriptor: descriptor, handle: handle, options: options }));
47
+ }
48
+ if (renderItem)
49
+ return _jsx(_Fragment, { children: renderItem(descriptor, handle) });
50
+ return _jsx(DefaultInteractionButton, { descriptor: descriptor, handle: handle });
51
+ }
52
+ function PromptOptionsCard({ descriptor, handle, options, }) {
53
+ const theme = useTheme();
54
+ const [pendingOptionId, setPendingOptionId] = useState(null);
55
+ // Option submission flows into the interaction's single declared input key
56
+ // by convention. Authors who need multi-input prompts should provide a
57
+ // custom renderer via `render` rather than relying on this default layout.
58
+ const inputKey = interactionInputKeys(descriptor)[0];
59
+ const title = descriptor.context?.title ?? interactionLabel(descriptor);
60
+ const containerStyle = {
61
+ ...surfaceStyle(theme, { tone: "card" }),
62
+ display: "flex",
63
+ flexDirection: "column",
64
+ gap: theme.space[3],
65
+ padding: theme.space[4],
66
+ };
67
+ return (_jsxs("div", { role: "group", "aria-label": title, "data-interaction-id": descriptor.interactionId, "data-surface": "inbox", style: containerStyle, children: [_jsx("div", { style: {
68
+ fontFamily: theme.typography.fontFamily.display,
69
+ fontSize: theme.typography.fontSize.lg,
70
+ fontWeight: theme.typography.fontWeight.bold,
71
+ color: theme.semantic.text.primary,
72
+ lineHeight: theme.typography.lineHeight.tight,
73
+ }, children: title }), _jsx("div", { style: {
74
+ display: "flex",
75
+ flexDirection: "row",
76
+ flexWrap: "wrap",
77
+ gap: theme.space[2],
78
+ }, children: options.map((option) => {
79
+ const isPending = pendingOptionId === option.id;
80
+ const disabled = isPending || !descriptor.available || inputKey === undefined;
81
+ return (_jsx(ThemedButton, { type: "button", variant: "secondary", size: "md", pressed: isPending, "data-option-id": option.id, disabled: disabled, "aria-label": option.label ?? option.id, onClick: async (event) => {
82
+ event.preventDefault();
83
+ if (disabled || !inputKey)
84
+ return;
85
+ setPendingOptionId(option.id);
86
+ try {
87
+ await handle.submit({ [inputKey]: option.id });
88
+ }
89
+ catch {
90
+ // Submission errors flow through the runtime's
91
+ // notification channel; we swallow here so the option
92
+ // buttons re-enable on failure.
93
+ }
94
+ finally {
95
+ setPendingOptionId(null);
96
+ }
97
+ }, children: option.label ?? option.id }, option.id));
98
+ }) })] }));
99
+ }
@@ -0,0 +1,62 @@
1
+ import { type ReactNode } from "react";
2
+ import type { InteractionDescriptor } from "../../types/plugin-state.js";
3
+ import type { InteractionActionState, InteractionDisabledReason } from "../../utils/interaction-status.js";
4
+ import type { ViewCard } from "@dreamboard/sdk-types";
5
+ import { type CardZoneInteractionContext } from "./internal/useCardZoneInteractions.js";
6
+ export interface MarketPile<I extends string = string> {
7
+ zoneId: string;
8
+ cards: readonly ViewCard[];
9
+ topCard: ViewCard | null;
10
+ count: number;
11
+ interactions: ReadonlyArray<InteractionDescriptor<I>>;
12
+ primaryInteraction: InteractionDescriptor<I> | null;
13
+ disabled: boolean;
14
+ disabledReason?: InteractionDisabledReason;
15
+ actionState: InteractionActionState;
16
+ play: (() => Promise<void>) | null;
17
+ }
18
+ export interface MarketGroup<I extends string = string> {
19
+ id: string;
20
+ label: string;
21
+ showLabel: boolean;
22
+ chrome: MarketGroupChrome;
23
+ tone: MarketGroupTone;
24
+ piles: ReadonlyArray<MarketPile<I>>;
25
+ }
26
+ export interface MarketSurfaceContext<I extends string = string> {
27
+ groups: ReadonlyArray<MarketGroup<I>>;
28
+ }
29
+ export type MarketGroupChrome = "auto" | "panel" | "plain";
30
+ export type MarketGroupTone = "default" | "subtle" | "accent";
31
+ export type MarketGroupPriority = "primary" | "supporting";
32
+ export interface MarketGroupRenderContext<I extends string = string> {
33
+ market: MarketSurfaceContext<I>;
34
+ priority: MarketGroupPriority;
35
+ renderPile: (pile: MarketPile<I>) => ReactNode;
36
+ renderPiles: () => ReactNode;
37
+ }
38
+ export interface MarketGroupConfig<ZoneId extends string = string, GroupId extends string = string> {
39
+ id: GroupId;
40
+ label?: string | false;
41
+ zones: readonly ZoneId[];
42
+ chrome?: MarketGroupChrome;
43
+ tone?: MarketGroupTone;
44
+ }
45
+ export interface MarketLayoutConfig<GroupId extends string = string> {
46
+ primary?: readonly GroupId[];
47
+ supporting?: readonly GroupId[];
48
+ }
49
+ export interface MarketSurfaceConfig<I extends string, ZoneId extends string = string, GroupId extends string = string> {
50
+ groups?: ReadonlyArray<MarketGroupConfig<ZoneId, GroupId>>;
51
+ layout?: MarketLayoutConfig<GroupId>;
52
+ renderCardContent?: (card: ViewCard, ctx: CardZoneInteractionContext<I>) => ReactNode;
53
+ renderPile?: (pile: MarketPile<I>, ctx: MarketSurfaceContext<I>) => ReactNode;
54
+ renderGroup?: (group: MarketGroup<I>, ctx: MarketGroupRenderContext<I>) => ReactNode;
55
+ render?: (market: MarketSurfaceContext<I>) => ReactNode;
56
+ }
57
+ export interface MarketSurfaceProps<I extends string = never, ZoneId extends string = string, GroupId extends string = string> extends MarketSurfaceConfig<I, ZoneId, GroupId> {
58
+ empty?: ReactNode;
59
+ }
60
+ export declare function defineMarketSurface<const Config extends MarketSurfaceConfig<string, string, string>>(config: Config): Config;
61
+ export declare function MarketSurface<I extends string = never, ZoneId extends string = string, GroupId extends string = string>({ groups, layout, renderCardContent, renderPile, renderGroup, render, empty, }: MarketSurfaceProps<I, ZoneId, GroupId>): import("react/jsx-runtime").JSX.Element;
62
+ //# sourceMappingURL=MarketSurface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarketSurface.d.ts","sourceRoot":"","sources":["../../../src/components/surfaces/MarketSurface.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,242 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Fragment, useMemo } from "react";
3
+ import { usePluginState } from "../../context/PluginStateContext.js";
4
+ import { surfaceStyle } from "../../theme/derive.js";
5
+ import { useTheme } from "../../theme/ThemeProvider.js";
6
+ import { Card } from "../Card.js";
7
+ import { useCardZoneInteractions, } from "./internal/useCardZoneInteractions.js";
8
+ export function defineMarketSurface(config) {
9
+ return config;
10
+ }
11
+ export function MarketSurface({ groups, layout, renderCardContent, renderPile, renderGroup, render, empty = null, }) {
12
+ const gameplayZones = usePluginState((s) => s.gameplay.zones);
13
+ const discoveredZoneIds = useMemo(() => discoverMarketZoneIds(gameplayZones), [gameplayZones]);
14
+ const authoredZoneIds = new Set(groups?.flatMap((group) => [...group.zones].map(String)) ?? []);
15
+ const omittedZoneIds = discoveredZoneIds.filter((zoneId) => !authoredZoneIds.has(zoneId));
16
+ const resolvedGroups = groups?.length
17
+ ? [
18
+ ...groups.map((group) => ({
19
+ id: String(group.id),
20
+ ...resolveGroupLabel(String(group.id), group.label),
21
+ chrome: group.chrome ?? "auto",
22
+ tone: group.tone ?? "default",
23
+ zoneIds: group.zones.map(String),
24
+ })),
25
+ ...(omittedZoneIds.length
26
+ ? [
27
+ {
28
+ id: "other",
29
+ label: "Other",
30
+ showLabel: true,
31
+ chrome: "auto",
32
+ tone: "subtle",
33
+ zoneIds: omittedZoneIds,
34
+ },
35
+ ]
36
+ : []),
37
+ ]
38
+ : discoveredZoneIds.length
39
+ ? [
40
+ {
41
+ id: "market",
42
+ label: "Market",
43
+ showLabel: true,
44
+ chrome: "auto",
45
+ tone: "default",
46
+ zoneIds: discoveredZoneIds,
47
+ },
48
+ ]
49
+ : [];
50
+ if (resolvedGroups.length === 0)
51
+ return _jsx(_Fragment, { children: empty });
52
+ return (_jsx(MarketSurfaceBody, { groupSpecs: resolvedGroups, layout: layout, renderCardContent: renderCardContent, renderPile: renderPile, renderGroup: renderGroup, render: render, omittedZoneIds: omittedZoneIds }));
53
+ }
54
+ function MarketSurfaceBody({ groupSpecs, layout, renderCardContent, renderPile, renderGroup, render, omittedZoneIds, }) {
55
+ const pileData = groupSpecs
56
+ .map((group) => ({
57
+ id: group.id,
58
+ label: group.label,
59
+ showLabel: group.showLabel,
60
+ chrome: group.chrome,
61
+ tone: group.tone,
62
+ piles: group.zoneIds
63
+ .map((zoneId) => useMarketPile(zoneId))
64
+ .filter((pile) => pile.count > 0 || pile.interactions.length > 0),
65
+ }))
66
+ .filter((group) => group.piles.length > 0);
67
+ const market = { groups: pileData };
68
+ const nodeEnv = globalThis
69
+ .process?.env?.NODE_ENV;
70
+ if (omittedZoneIds.length && nodeEnv !== "production") {
71
+ console.warn(`MarketSurface: appended omitted market zones to Other: ${omittedZoneIds.join(", ")}`);
72
+ }
73
+ if (render)
74
+ return _jsx(_Fragment, { children: render(market) });
75
+ const orderedGroups = orderGroups(pileData, layout);
76
+ const groupCount = orderedGroups.length;
77
+ const renderPileNode = (pile) => (_jsx("div", { "data-market-pile": pile.zoneId, "data-disabled": pile.disabled ? "true" : undefined, children: renderPile ? (renderPile(pile, market)) : (_jsx(DefaultMarketPile, { pile: pile, renderCardContent: renderCardContent })) }, pile.zoneId));
78
+ return (_jsx("div", { "data-market-surface": true, style: {
79
+ display: "flex",
80
+ flexDirection: "column",
81
+ gap: 12,
82
+ width: "100%",
83
+ }, children: orderedGroups.map(({ group, priority }) => {
84
+ const renderPiles = () => group.piles.map(renderPileNode);
85
+ if (renderGroup) {
86
+ return (_jsx(Fragment, { children: renderGroup(group, {
87
+ market,
88
+ priority,
89
+ renderPile: renderPileNode,
90
+ renderPiles,
91
+ }) }, group.id));
92
+ }
93
+ return (_jsx(DefaultMarketGroup, { group: group, groupCount: groupCount, priority: priority, children: renderPiles() }, group.id));
94
+ }) }));
95
+ }
96
+ function DefaultMarketGroup({ group, groupCount, priority, children, }) {
97
+ const theme = useTheme();
98
+ const resolvedChrome = resolveGroupChrome(group.chrome, groupCount);
99
+ const density = priority === "supporting" ? "compact" : "comfortable";
100
+ const sectionStyle = groupSectionStyle(theme, resolvedChrome, group.tone, density);
101
+ return (_jsxs("section", { "data-market-group": group.id, "data-market-layout": priority, "data-market-chrome": resolvedChrome, "data-market-tone": group.tone, "data-market-density": density, "aria-label": group.label, style: sectionStyle, children: [group.showLabel ? (_jsx("h3", { "data-market-group-title": group.id, style: {
102
+ margin: `0 0 ${theme.space[2]}`,
103
+ color: group.tone === "accent"
104
+ ? theme.semantic.intent.info.onSoft
105
+ : theme.semantic.text.muted,
106
+ fontFamily: theme.typography.fontFamily.display,
107
+ fontSize: theme.typography.fontSize.sm,
108
+ fontWeight: theme.typography.fontWeight.bold,
109
+ letterSpacing: theme.typography.letterSpacing.caps,
110
+ lineHeight: theme.typography.lineHeight.tight,
111
+ textTransform: "uppercase",
112
+ }, children: group.label })) : null, _jsx("div", { style: {
113
+ display: "flex",
114
+ flexWrap: "wrap",
115
+ gap: density === "compact" ? theme.space[2] : theme.space[3],
116
+ }, children: children })] }));
117
+ }
118
+ function resolveGroupLabel(id, label) {
119
+ const fallback = humanizeGroupId(id);
120
+ return label === false
121
+ ? { label: fallback, showLabel: false }
122
+ : { label: label ?? fallback, showLabel: true };
123
+ }
124
+ function humanizeGroupId(id) {
125
+ return id
126
+ .replace(/[-_]+/g, " ")
127
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
128
+ .replace(/\s+/g, " ")
129
+ .trim()
130
+ .replace(/\b\w/g, (char) => char.toUpperCase());
131
+ }
132
+ function resolveGroupChrome(chrome, groupCount) {
133
+ if (chrome !== "auto")
134
+ return chrome;
135
+ return groupCount > 1 ? "panel" : "plain";
136
+ }
137
+ function groupSectionStyle(theme, chrome, tone, density) {
138
+ if (chrome === "plain") {
139
+ return {
140
+ minWidth: 0,
141
+ };
142
+ }
143
+ const padding = density === "compact"
144
+ ? `${theme.space[2]} ${theme.space[3]}`
145
+ : `${theme.space[3]} ${theme.space[4]}`;
146
+ const style = surfaceStyle(theme, {
147
+ tone: tone === "subtle" ? "inset" : "card",
148
+ radius: "hud",
149
+ });
150
+ if (tone === "accent") {
151
+ return {
152
+ ...style,
153
+ padding,
154
+ background: theme.semantic.intent.info.soft,
155
+ border: `1px solid ${theme.semantic.intent.info.border}`,
156
+ boxShadow: theme.elevation.rest,
157
+ };
158
+ }
159
+ return {
160
+ ...style,
161
+ padding,
162
+ boxShadow: tone === "subtle" ? theme.elevation.inset : theme.elevation.rest,
163
+ };
164
+ }
165
+ function useMarketPile(zoneId) {
166
+ const { cards, contexts } = useCardZoneInteractions(zoneId, {
167
+ surface: "market",
168
+ });
169
+ const topCard = cards[0] ?? null;
170
+ const ctx = topCard
171
+ ? contexts.find((item) => item.card.id === topCard.id)
172
+ : undefined;
173
+ const available = (ctx?.interactions ?? []).filter((descriptor) => descriptor.available !== false);
174
+ return {
175
+ zoneId,
176
+ cards,
177
+ topCard,
178
+ count: cards.length,
179
+ interactions: ctx?.interactions ?? [],
180
+ primaryInteraction: available.length === 1 ? (available[0] ?? null) : null,
181
+ disabled: ctx?.disabled ?? true,
182
+ disabledReason: ctx?.disabledReason,
183
+ actionState: ctx?.actionState ?? "unavailable",
184
+ play: ctx?.play ? async () => ctx.play?.() : null,
185
+ };
186
+ }
187
+ function DefaultMarketPile({ pile, renderCardContent, }) {
188
+ if (!pile.topCard)
189
+ return null;
190
+ return (_jsxs("div", { style: { position: "relative" }, children: [_jsx(Card, { card: pile.topCard, disabled: pile.disabled, size: "sm", onCardClick: pile.disabled || !pile.play ? undefined : () => void pile.play?.(), renderContent: renderCardContent
191
+ ? (card) => renderCardContent(card, {
192
+ card,
193
+ interactions: pile.interactions,
194
+ play: pile.play,
195
+ disabled: pile.disabled,
196
+ disabledReason: pile.disabledReason,
197
+ actionState: pile.actionState,
198
+ selected: false,
199
+ })
200
+ : undefined }), _jsx("span", { "data-market-pile-count": true, style: {
201
+ position: "absolute",
202
+ right: -6,
203
+ bottom: -6,
204
+ borderRadius: 999,
205
+ padding: "2px 6px",
206
+ background: "#111",
207
+ color: "#fff",
208
+ fontSize: 12,
209
+ }, children: pile.count })] }));
210
+ }
211
+ function discoverMarketZoneIds(gameplayZones) {
212
+ const ids = [];
213
+ for (const [zoneId, zone] of Object.entries(gameplayZones)) {
214
+ if (zone.cardIds.some((cardId) => (zone.playableByCardId[cardId] ?? []).length > 0))
215
+ ids.push(zoneId);
216
+ }
217
+ return ids;
218
+ }
219
+ function orderGroups(groups, layout) {
220
+ const byId = new Map(groups.map((group) => [group.id, group]));
221
+ const seen = new Set();
222
+ const supportingIds = new Set(layout?.supporting ?? []);
223
+ const take = (ids, priority) => (ids ?? []).flatMap((id) => {
224
+ const group = byId.get(id);
225
+ if (!group || seen.has(id))
226
+ return [];
227
+ seen.add(id);
228
+ return [{ group, priority }];
229
+ });
230
+ return [
231
+ ...take(layout?.primary, "primary"),
232
+ ...groups
233
+ .filter((group) => !seen.has(group.id) &&
234
+ group.id !== "other" &&
235
+ !supportingIds.has(group.id))
236
+ .map((group) => ({ group, priority: "primary" })),
237
+ ...take(layout?.supporting, "supporting"),
238
+ ...groups
239
+ .filter((group) => group.id === "other" && !seen.has(group.id))
240
+ .map((group) => ({ group, priority: "supporting" })),
241
+ ];
242
+ }