@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,183 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Theme-aware primary CTA button — the dominant call-to-action on
4
+ * the screen at any given moment ("Roll dice", "End turn", "Confirm
5
+ * trade", "Place settlement").
6
+ *
7
+ * The shell's `chrome.primaryAction` slot accepts either a
8
+ * pre-rendered React node *or* an {@link InteractionHandle}. When a
9
+ * handle is supplied, the shell wraps it in this component so the
10
+ * call site collapses from ~10 lines to one. Authors who need a
11
+ * fully bespoke CTA can still pass any node.
12
+ *
13
+ * Visual contract (Laws of UX cross-references):
14
+ *
15
+ * - **Fitts** — defaults to `lg` size (min 56px tall, generous
16
+ * horizontal padding) so the dock target is easy to land on.
17
+ * Authors can opt down to `md`.
18
+ * - **Von Restorff (isolation)** — uses `intent.primary.solid` with
19
+ * `elevation.lifted` and an animated halo when `attention="auto"`
20
+ * and the descriptor is available, so the button outranks every
21
+ * other element in its peripheral neighbourhood.
22
+ * - **Peak-end** — when the action becomes available (handle flips
23
+ * from disabled → enabled), the halo pulses for one breath cycle
24
+ * so the eye finds the change without re-scanning the screen.
25
+ * - **Doherty / responsiveness** — clicks set an internal `pending`
26
+ * flag the moment submit fires so the button visibly absorbs the
27
+ * tap, even on slow networks. Throwing submitters are swallowed
28
+ * here for the same reason `<DefaultInteractionButton>` does:
29
+ * descriptor availability is authoritative.
30
+ * - **Accessibility** — minimum 56×56 hit area satisfies WCAG 2.5.5.
31
+ * `prefers-reduced-motion` zeroes out the halo and press
32
+ * transitions through the theme's `motion.reducedMotion` token.
33
+ */
34
+ import { useEffect, useRef, useState, } from "react";
35
+ import { motion } from "framer-motion";
36
+ import { useTheme } from "../theme/ThemeProvider.js";
37
+ import { intentForVariant, } from "../theme/derive.js";
38
+ import { interactionLabel } from "../utils/interaction-labels.js";
39
+ import { ThemedButton } from "./ThemedButton.js";
40
+ /**
41
+ * @see PrimaryActionButtonProps
42
+ */
43
+ export function PrimaryActionButton({ handle, variant = "primary", size = "lg", label, ready = true, whenSubmitted, icon, params, attention = "auto", style, className, }) {
44
+ const theme = useTheme();
45
+ const reducedMotion = theme.motion.reducedMotion === "true";
46
+ const [pending, setPending] = useState(false);
47
+ const descriptor = handle.descriptor;
48
+ const submitted = handle.status === "submitted";
49
+ const submitting = handle.status === "submitting" || pending;
50
+ const available = descriptor.available && ready && !submitted && !submitting;
51
+ const resolvedVariant = submitted
52
+ ? (whenSubmitted?.variant ?? "submitted")
53
+ : variant;
54
+ const disabled = !available;
55
+ const intent = intentForVariant(theme, resolvedVariant);
56
+ // Pulse the halo for one breath when availability flips on. After
57
+ // the breath we settle into the ambient cadence (or stop, when
58
+ // `attention` is `off`). Tracking the previous availability lets
59
+ // us catch the transition without re-mounting the component.
60
+ const previouslyAvailableRef = useRef(available);
61
+ const [pulseKey, setPulseKey] = useState(0);
62
+ useEffect(() => {
63
+ if (!previouslyAvailableRef.current && available) {
64
+ setPulseKey((n) => n + 1);
65
+ }
66
+ previouslyAvailableRef.current = available;
67
+ }, [available]);
68
+ const haloEnabled = !reducedMotion && available && attention !== "off" && !submitted;
69
+ const fallbackLabel = interactionLabel(descriptor);
70
+ const tooltip = available
71
+ ? undefined
72
+ : formatUnavailableReason(descriptor.unavailableReason);
73
+ const resolvedLabel = submitted
74
+ ? (whenSubmitted?.label ?? label ?? fallbackLabel)
75
+ : (label ?? fallbackLabel);
76
+ const resolvedIcon = submitted && whenSubmitted?.icon ? (_jsx("span", { "aria-hidden": true, style: { fontSize: "1.15em" }, children: whenSubmitted.icon })) : ((icon ?? null));
77
+ return (_jsxs("span", { "data-dreamboard-primary-action": true, "data-available": available ? "true" : "false", "data-pending": submitting ? "true" : undefined, "data-action-state": submitted
78
+ ? "submitted"
79
+ : submitting
80
+ ? "submitting"
81
+ : available
82
+ ? "available"
83
+ : "unavailable", style: {
84
+ position: "relative",
85
+ display: "inline-flex",
86
+ alignItems: "center",
87
+ justifyContent: "center",
88
+ // The halo overflows the button bounds; the wrapper reserves
89
+ // a transparent buffer so it doesn't get clipped by the
90
+ // dock's safe-area frame.
91
+ padding: theme.space[1],
92
+ }, children: [haloEnabled ? (_jsxs(_Fragment, { children: [_jsx(motion.span, { "aria-hidden": true, style: {
93
+ position: "absolute",
94
+ inset: 0,
95
+ borderRadius: theme.radius.md,
96
+ background: intent.soft,
97
+ opacity: 0.55,
98
+ pointerEvents: "none",
99
+ }, animate: {
100
+ scale: [1, 1.06, 1],
101
+ opacity: [0.45, 0.18, 0.45],
102
+ }, transition: {
103
+ repeat: Infinity,
104
+ duration: 2.4,
105
+ ease: "easeInOut",
106
+ } }), _jsx(motion.span, { "aria-hidden": true, style: {
107
+ position: "absolute",
108
+ inset: 0,
109
+ borderRadius: theme.radius.md,
110
+ boxShadow: `0 0 0 0 ${intent.solid}`,
111
+ pointerEvents: "none",
112
+ }, initial: { opacity: 0.7 }, animate: {
113
+ boxShadow: [
114
+ `0 0 0 0 ${withAlpha(intent.solid, 0.55)}`,
115
+ `0 0 0 14px ${withAlpha(intent.solid, 0)}`,
116
+ ],
117
+ opacity: [0.7, 0],
118
+ }, transition: { duration: 0.9, ease: "easeOut" } }, pulseKey)] })) : null, _jsxs(ThemedButton, { type: "button", variant: resolvedVariant, size: size, pressed: submitting, className: className, "aria-label": typeof resolvedLabel === "string" ? resolvedLabel : fallbackLabel, "aria-disabled": disabled || undefined, "data-interaction-id": descriptor.interactionId, "data-emphasis": "primary", title: tooltip, disabled: disabled, style: {
119
+ // Sit above the halo so clicks land on the button.
120
+ position: "relative",
121
+ zIndex: 1,
122
+ boxShadow: disabled || submitted ? undefined : theme.elevation.lifted,
123
+ ...style,
124
+ }, onClick: async (event) => {
125
+ event.preventDefault();
126
+ if (disabled)
127
+ return;
128
+ setPending(true);
129
+ try {
130
+ if (params !== undefined) {
131
+ await handle.submit(params);
132
+ }
133
+ else {
134
+ await handle.submitDraft();
135
+ }
136
+ }
137
+ catch {
138
+ // Descriptor availability is authoritative; submit errors
139
+ // surface via the runtime's error channel.
140
+ }
141
+ finally {
142
+ setPending(false);
143
+ }
144
+ }, children: [resolvedIcon, _jsx("span", { children: resolvedLabel })] })] }));
145
+ }
146
+ function formatUnavailableReason(reason) {
147
+ if (reason === "INSUFFICIENT_RESOURCES") {
148
+ return "Insufficient resources";
149
+ }
150
+ return reason;
151
+ }
152
+ /**
153
+ * Add an alpha channel to a CSS colour string. Supports `#rgb`,
154
+ * `#rrggbb`, and any colour the browser can paint via a fallback to
155
+ * `color-mix` (modern Safari/Chrome/Firefox all support this; older
156
+ * runtimes get the original colour without alpha which is still
157
+ * visible — the halo is decorative).
158
+ */
159
+ function withAlpha(color, alpha) {
160
+ const trimmed = color.trim();
161
+ if (trimmed.startsWith("#")) {
162
+ const hex = trimmed.slice(1);
163
+ if (hex.length === 3) {
164
+ // `String.prototype.slice` always returns a string (possibly
165
+ // empty) — never `undefined` — so duplicating each digit is
166
+ // safe to feed to `parseInt` without further narrowing.
167
+ const r = parseInt(hex.slice(0, 1).repeat(2), 16);
168
+ const g = parseInt(hex.slice(1, 2).repeat(2), 16);
169
+ const b = parseInt(hex.slice(2, 3).repeat(2), 16);
170
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
171
+ }
172
+ if (hex.length === 6) {
173
+ const r = parseInt(hex.slice(0, 2), 16);
174
+ const g = parseInt(hex.slice(2, 4), 16);
175
+ const b = parseInt(hex.slice(4, 6), 16);
176
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
177
+ }
178
+ }
179
+ // Best-effort fallback for non-hex colours (rgb/hsl/named): use
180
+ // `color-mix` with transparent. Safe to land in inline style — the
181
+ // halo is purely decorative and will gracefully degrade.
182
+ return `color-mix(in srgb, ${trimmed} ${Math.round(alpha * 100)}%, transparent)`;
183
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Minimally-styled primary action button.
3
+ *
4
+ * Visual styling now flows through {@link buttonStyle}: the background,
5
+ * border, foreground, radius, typography and elevation all derive from
6
+ * the active {@link useTheme}'s `intent.primary` slot. Override the
7
+ * variant when a non-primary call site needs a different emphasis (the
8
+ * underlying `<DefaultInteractionButton>` is the canonical button for
9
+ * interaction-bound submission).
10
+ */
11
+ import type { ButtonHTMLAttributes } from "react";
12
+ import type { ButtonSize, ButtonVariant } from "../theme/derive.js";
13
+ export interface PrimaryButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
14
+ /** Intent slot — defaults to `primary`. */
15
+ variant?: ButtonVariant;
16
+ /** Sizing token — defaults to `md`. */
17
+ size?: ButtonSize;
18
+ }
19
+ export declare function PrimaryButton({ children, disabled, style, variant, size, ...rest }: PrimaryButtonProps): import("react/jsx-runtime").JSX.Element;
20
+ //# sourceMappingURL=PrimaryButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PrimaryButton.d.ts","sourceRoot":"","sources":["../../src/components/PrimaryButton.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGpE,MAAM,WAAW,kBACf,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC;IAC/C,2CAA2C;IAC3C,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,uCAAuC;IACvC,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,OAAmB,EACnB,IAAW,EACX,GAAG,IAAI,EACR,EAAE,kBAAkB,2CAapB"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { ThemedButton } from "./ThemedButton.js";
3
+ export function PrimaryButton({ children, disabled, style, variant = "primary", size = "md", ...rest }) {
4
+ return (_jsx(ThemedButton, { type: "button", disabled: disabled, variant: variant, size: size, style: style, ...rest, children: children }));
5
+ }
@@ -0,0 +1,15 @@
1
+ import { type ReactNode } from "react";
2
+ import type { InteractionContextOption, InteractionDescriptor } from "../types/plugin-state.js";
3
+ export interface PromptDialogHostProps {
4
+ contentClassName?: string;
5
+ messageClassName?: string;
6
+ optionClassName?: string;
7
+ optionsClassName?: string;
8
+ overlayClassName?: string;
9
+ titleClassName?: string;
10
+ renderBody?: (prompt: InteractionDescriptor) => ReactNode;
11
+ renderOptionLabel?: (option: InteractionContextOption, prompt: InteractionDescriptor) => ReactNode;
12
+ onSubmitError?: (error: unknown, prompt: InteractionDescriptor, option: InteractionContextOption) => void;
13
+ }
14
+ export declare function PromptDialogHost(props: PromptDialogHostProps): import("react/jsx-runtime").JSX.Element | null;
15
+ //# sourceMappingURL=PromptDialogHost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PromptDialogHost.d.ts","sourceRoot":"","sources":["../../src/components/PromptDialogHost.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAK5D,OAAO,KAAK,EACV,wBAAwB,EACxB,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,SAAS,CAAC;IAC1D,iBAAiB,CAAC,EAAE,CAClB,MAAM,EAAE,wBAAwB,EAChC,MAAM,EAAE,qBAAqB,KAC1B,SAAS,CAAC;IACf,aAAa,CAAC,EAAE,CACd,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,qBAAqB,EAC7B,MAAM,EAAE,wBAAwB,KAC7B,IAAI,CAAC;CACX;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,kDAO5D"}
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { clsx } from "clsx";
4
+ import { Dialog, DialogContent, DialogTitle } from "../internal/ui/dialog.js";
5
+ import { useSeatInbox } from "../hooks/useSeatInbox.js";
6
+ import { Prompt } from "../primitives/prompt.js";
7
+ export function PromptDialogHost(props) {
8
+ const { prompts } = useSeatInbox();
9
+ const prompt = prompts[0];
10
+ if (!prompt)
11
+ return null;
12
+ return (_jsx(PromptDialog, { prompt: prompt, ...props }, prompt.interactionKey));
13
+ }
14
+ function PromptDialog({ contentClassName, messageClassName, optionClassName, optionsClassName, overlayClassName, prompt, renderBody, renderOptionLabel, titleClassName, onSubmitError, }) {
15
+ const [open, setOpen] = useState(true);
16
+ useEffect(() => {
17
+ setOpen(true);
18
+ }, [prompt.interactionKey]);
19
+ return (_jsx(Dialog, { open: open, onOpenChange: setOpen, children: _jsx(DialogContent, { className: contentClassName, overlayClassName: overlayClassName, children: _jsxs(Prompt.Root, { interaction: prompt.interactionKey, children: [_jsx(DialogTitle, { className: titleClassName, children: _jsx(Prompt.Title, {}) }), _jsx(Prompt.Message, { className: messageClassName }), renderBody?.(prompt), _jsx("div", { className: clsx("flex flex-wrap gap-2", optionsClassName), children: (prompt.context?.options ?? []).map((option) => (_jsx(Prompt.Option, { className: optionClassName, value: option.id, onSubmitSuccess: () => setOpen(false), onSubmitError: (error) => onSubmitError?.(error, prompt, option), children: renderOptionLabel?.(option, prompt) ??
20
+ option.label ??
21
+ option.id }, option.id))) })] }) }) }));
22
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Displays resource counts with icons and animated updates.
3
+ *
4
+ * The chip frame (border, fill, shadow, padding, gap) is sourced from
5
+ * the active {@link useTheme}. Authors can still override per-chip
6
+ * colours via {@link ResourceDisplayConfig.bgColor} /
7
+ * {@link ResourceDisplayConfig.iconColor} / {@link ResourceDisplayConfig.textColor}
8
+ * (Tailwind class names) — those win over the theme defaults so existing
9
+ * callers that pass game-specific palettes (Catan: wheat/wood/brick…)
10
+ * keep their look.
11
+ */
12
+ import { type ComponentType, type ReactNode } from "react";
13
+ import type { ResourceId } from "@dreamboard/manifest-contract";
14
+ export interface ResourceDisplayConfig {
15
+ type: ResourceId;
16
+ label: string;
17
+ icon: ReactNode | ComponentType<{
18
+ className?: string;
19
+ strokeWidth?: number;
20
+ "aria-hidden"?: string;
21
+ }>;
22
+ iconColor?: string;
23
+ bgColor?: string;
24
+ textColor?: string;
25
+ }
26
+ export interface ResourceCounterProps {
27
+ resources: ResourceDisplayConfig[];
28
+ counts: Record<ResourceId, number>;
29
+ layout?: "row" | "grid" | "compact";
30
+ /** Number of columns for grid layout */
31
+ columns?: number;
32
+ showZero?: boolean;
33
+ size?: "sm" | "md" | "lg";
34
+ onResourceClick?: (resourceType: ResourceId) => void;
35
+ className?: string;
36
+ }
37
+ export declare function ResourceCounter({ resources, counts, layout, columns, showZero, size, onResourceClick, className, }: ResourceCounterProps): import("react/jsx-runtime").JSX.Element;
38
+ //# sourceMappingURL=ResourceCounter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourceCounter.d.ts","sourceRoot":"","sources":["../../src/components/ResourceCounter.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAiB,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAahE,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EACA,SAAS,GACT,aAAa,CAAC;QACZ,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC,CAAC;IACP,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,qBAAqB,EAAE,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;IACpC,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,eAAe,CAAC,EAAE,CAAC,YAAY,EAAE,UAAU,KAAK,IAAI,CAAC;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,MAAM,EACN,MAAc,EACd,OAAW,EACX,QAAe,EACf,IAAW,EACX,eAAe,EACf,SAAS,GACV,EAAE,oBAAoB,2CAkNtB"}
@@ -0,0 +1,118 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Displays resource counts with icons and animated updates.
4
+ *
5
+ * The chip frame (border, fill, shadow, padding, gap) is sourced from
6
+ * the active {@link useTheme}. Authors can still override per-chip
7
+ * colours via {@link ResourceDisplayConfig.bgColor} /
8
+ * {@link ResourceDisplayConfig.iconColor} / {@link ResourceDisplayConfig.textColor}
9
+ * (Tailwind class names) — those win over the theme defaults so existing
10
+ * callers that pass game-specific palettes (Catan: wheat/wood/brick…)
11
+ * keep their look.
12
+ */
13
+ import { motion, AnimatePresence } from "framer-motion";
14
+ import { clsx } from "clsx";
15
+ import { createElement } from "react";
16
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../internal/ui/tooltip.js";
17
+ import { useTheme } from "../theme/ThemeProvider.js";
18
+ export function ResourceCounter({ resources, counts, layout = "row", columns = 5, showZero = true, size = "md", onResourceClick, className, }) {
19
+ const theme = useTheme();
20
+ const reducedMotion = theme.motion.reducedMotion === "true";
21
+ const sizeConfig = {
22
+ sm: {
23
+ icon: "w-4 h-4",
24
+ fontSize: theme.typography.fontSize.sm,
25
+ paddingBlock: theme.space[1],
26
+ paddingInline: theme.space[2],
27
+ gap: theme.space[1],
28
+ },
29
+ md: {
30
+ icon: "w-5 h-5",
31
+ fontSize: theme.typography.fontSize.md,
32
+ paddingBlock: theme.space[1.5],
33
+ paddingInline: theme.space[3],
34
+ gap: theme.space[1.5],
35
+ },
36
+ lg: {
37
+ icon: "w-6 h-6",
38
+ fontSize: theme.typography.fontSize.lg,
39
+ paddingBlock: theme.space[2],
40
+ paddingInline: theme.space[4],
41
+ gap: theme.space[2],
42
+ },
43
+ };
44
+ const styles = sizeConfig[size];
45
+ const filteredResources = showZero
46
+ ? resources
47
+ : resources.filter((r) => (counts[r.type] ?? 0) > 0);
48
+ // Base chip styling pulled from the theme. Caller-supplied
49
+ // `bgColor`/`textColor` (Tailwind classes) override these inline
50
+ // defaults via the `style` cascade — when a Tailwind class sets
51
+ // `background-color`, it wins because we don't pass `background`
52
+ // when the caller provided a `bgColor` class.
53
+ const baseChipStyle = (bgColorClass) => ({
54
+ display: "inline-flex",
55
+ alignItems: "center",
56
+ gap: styles.gap,
57
+ paddingBlock: styles.paddingBlock,
58
+ paddingInline: styles.paddingInline,
59
+ borderRadius: theme.radius.md,
60
+ border: `2px solid ${theme.semantic.border.default}`,
61
+ background: bgColorClass ? undefined : theme.semantic.surface.card,
62
+ boxShadow: theme.elevation.rest,
63
+ fontFamily: theme.typography.fontFamily.body,
64
+ transition: `transform ${theme.motion.duration.fast} ${theme.motion.easing.out}, box-shadow ${theme.motion.duration.normal} ${theme.motion.easing.out}`,
65
+ });
66
+ return (_jsx("div", { className: clsx(layout === "grid" && "grid", layout === "row" && "flex flex-wrap", layout === "compact" && "flex flex-wrap", layout === "row" && "gap-3 sm:gap-4", layout === "compact" && "gap-2", layout === "grid" && "gap-3 sm:gap-4", className), style: layout === "grid"
67
+ ? {
68
+ gridTemplateColumns: `repeat(${columns}, 1fr)`,
69
+ fontFamily: theme.typography.fontFamily.body,
70
+ }
71
+ : { fontFamily: theme.typography.fontFamily.body }, role: "list", "aria-label": "Resource counts", children: _jsx(TooltipProvider, { delayDuration: 200, children: _jsx(AnimatePresence, { mode: "popLayout", children: filteredResources.map(({ type, label, icon, iconColor, bgColor, textColor }) => {
72
+ const count = counts[type] ?? 0;
73
+ const iconNode = typeof icon === "function" ? (createElement(icon, {
74
+ className: clsx(styles.icon, iconColor),
75
+ strokeWidth: 2.5,
76
+ "aria-hidden": "true",
77
+ })) : (_jsx("span", { className: clsx(styles.icon, iconColor), "aria-hidden": "true", style: {
78
+ display: "inline-flex",
79
+ alignItems: "center",
80
+ justifyContent: "center",
81
+ fontSize: "1.1em",
82
+ }, children: icon }));
83
+ const content = (_jsxs(_Fragment, { children: [iconNode, _jsx(motion.span, { initial: reducedMotion ? { scale: 1 } : { scale: 1.5 }, animate: { scale: 1 }, className: clsx("font-bold", textColor), style: {
84
+ fontSize: styles.fontSize,
85
+ fontFamily: theme.typography.fontFamily.tabular,
86
+ fontWeight: theme.typography.fontWeight.bold,
87
+ color: textColor
88
+ ? undefined
89
+ : theme.semantic.text.primary,
90
+ }, children: count }, count)] }));
91
+ const sharedClassName = clsx("flex items-center focus-visible:outline-none", bgColor, onResourceClick
92
+ ? "cursor-pointer focus-visible:ring-2 focus-visible:ring-offset-2"
93
+ : "cursor-help");
94
+ const sharedStyle = {
95
+ ...baseChipStyle(bgColor),
96
+ color: textColor ? undefined : theme.semantic.text.primary,
97
+ };
98
+ const focusVisibleStyle = onResourceClick
99
+ ? {
100
+ // Theming the focus ring requires a CSS variable hop
101
+ // because Tailwind's focus-visible:ring-offset uses
102
+ // `--tw-ring-offset-color`. We expose the theme
103
+ // border.focus token here so consumers without our
104
+ // Tailwind preset still get a visible ring.
105
+ "--tw-ring-color": theme.semantic.border.focus,
106
+ "--tw-ring-offset-color": theme.semantic.surface.app,
107
+ }
108
+ : {};
109
+ const chip = onResourceClick ? (_jsx("button", { type: "button", onClick: () => onResourceClick(type), className: sharedClassName, style: { ...sharedStyle, ...focusVisibleStyle }, "aria-label": `${label}: ${count}`, children: content })) : (_jsx("div", { className: sharedClassName, style: sharedStyle, "aria-label": `${label}: ${count}`, children: content }));
110
+ return (_jsx(motion.div, { layout: !reducedMotion, initial: reducedMotion
111
+ ? { opacity: 0, scale: 1 }
112
+ : { opacity: 0, scale: 0.8 }, animate: { opacity: 1, scale: 1 }, exit: { opacity: 0, scale: 0.8 }, whileHover: onResourceClick && !reducedMotion
113
+ ? { scale: 1.05 }
114
+ : undefined, whileTap: onResourceClick && !reducedMotion
115
+ ? { scale: 0.95 }
116
+ : undefined, role: "listitem", children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: chip }), _jsxs(TooltipContent, { side: "top", sideOffset: 6, children: [_jsx("p", { className: "font-sans text-sm font-bold", children: label }), _jsxs("p", { className: "font-sans text-xs font-normal opacity-90", children: ["Quantity: ", count] })] })] }) }, type));
117
+ }) }) }) }));
118
+ }
@@ -0,0 +1,12 @@
1
+ import type { ComponentProps } from "react";
2
+ import { Button as ShadcnButton } from "../internal/ui/button.js";
3
+ import { type ButtonSize, type ButtonVariant } from "../theme/derive.js";
4
+ type ShadcnButtonProps = ComponentProps<typeof ShadcnButton>;
5
+ export interface ThemedButtonProps extends Omit<ShadcnButtonProps, "variant" | "size"> {
6
+ variant?: ButtonVariant;
7
+ size?: ButtonSize;
8
+ pressed?: boolean;
9
+ }
10
+ export declare function ThemedButton({ variant, size, pressed, disabled, className, style, ...props }: ThemedButtonProps): import("react/jsx-runtime").JSX.Element;
11
+ export {};
12
+ //# sourceMappingURL=ThemedButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemedButton.d.ts","sourceRoot":"","sources":["../../src/components/ThemedButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAG5B,KAAK,iBAAiB,GAAG,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC;AAE7D,MAAM,WAAW,iBACf,SAAQ,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,MAAM,CAAC;IACnD,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,YAAY,CAAC,EAC3B,OAAmB,EACnB,IAAW,EACX,OAAe,EACf,QAAQ,EACR,SAAS,EACT,KAAK,EACL,GAAG,KAAK,EACT,EAAE,iBAAiB,2CAkBnB"}
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { clsx } from "clsx";
3
+ import { Button as ShadcnButton } from "../internal/ui/button.js";
4
+ import { buttonStyle, } from "../theme/derive.js";
5
+ import { useTheme } from "../theme/ThemeProvider.js";
6
+ export function ThemedButton({ variant = "primary", size = "md", pressed = false, disabled, className, style, ...props }) {
7
+ const theme = useTheme();
8
+ return (_jsx(ShadcnButton, { variant: toShadcnVariant(variant), size: toShadcnSize(size), disabled: disabled, "data-dreamboard-button": true, "data-dreamboard-button-variant": variant, "data-dreamboard-button-size": size, className: clsx("font-sans", className), style: {
9
+ ...buttonStyle(theme, { variant, size, disabled, pressed }),
10
+ ...style,
11
+ }, ...props }));
12
+ }
13
+ function toShadcnVariant(variant) {
14
+ switch (variant) {
15
+ case "danger":
16
+ return "destructive";
17
+ case "ghost":
18
+ return "ghost";
19
+ case "secondary":
20
+ return "secondary";
21
+ case "primary":
22
+ case "submitted":
23
+ case "success":
24
+ case "warning":
25
+ case "info":
26
+ return "default";
27
+ }
28
+ }
29
+ function toShadcnSize(size) {
30
+ switch (size) {
31
+ case "sm":
32
+ return "sm";
33
+ case "md":
34
+ return "default";
35
+ case "lg":
36
+ return "lg";
37
+ }
38
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Plugin-internal toast notification system.
3
+ *
4
+ * `<ToastProvider>` exposes a `useToast()` API that game authors call
5
+ * imperatively to surface their own game-specific feedback ("Resource
6
+ * gained", "Card discarded", "Tip: rotate the board with R", …). It
7
+ * is intentionally NOT wired to the host notification stream:
8
+ * `YOUR_TURN`, `PROMPT_OPENED` and `ACTION_REJECTED` events are owned
9
+ * by `@dreamboard/ui-host-runtime`'s `<HostFeedbackToaster>` and must
10
+ * not be mirrored from inside the plugin tree.
11
+ */
12
+ import { type ReactNode } from "react";
13
+ export type ToastType = "success" | "error" | "info" | "warning";
14
+ export interface Toast {
15
+ id: string;
16
+ type: ToastType;
17
+ message: string;
18
+ duration?: number;
19
+ }
20
+ interface ToastContextValue {
21
+ toasts: Toast[];
22
+ show: (message: string, type?: ToastType, duration?: number) => void;
23
+ dismiss: (id: string) => void;
24
+ success: (message: string, duration?: number) => void;
25
+ error: (message: string, duration?: number) => void;
26
+ info: (message: string, duration?: number) => void;
27
+ warning: (message: string, duration?: number) => void;
28
+ }
29
+ export interface ToastProviderProps {
30
+ children: ReactNode;
31
+ }
32
+ export declare function ToastProvider({ children }: ToastProviderProps): import("react/jsx-runtime").JSX.Element;
33
+ export declare function useToast(): ToastContextValue;
34
+ export {};
35
+ //# sourceMappingURL=Toast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../src/components/Toast.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAMf,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAEjE,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,iBAAiB;IACzB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD;AAID,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE,kBAAkB,2CA4D7D;AAED,wBAAgB,QAAQ,sBAMvB"}
@@ -0,0 +1,116 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Plugin-internal toast notification system.
4
+ *
5
+ * `<ToastProvider>` exposes a `useToast()` API that game authors call
6
+ * imperatively to surface their own game-specific feedback ("Resource
7
+ * gained", "Card discarded", "Tip: rotate the board with R", …). It
8
+ * is intentionally NOT wired to the host notification stream:
9
+ * `YOUR_TURN`, `PROMPT_OPENED` and `ACTION_REJECTED` events are owned
10
+ * by `@dreamboard/ui-host-runtime`'s `<HostFeedbackToaster>` and must
11
+ * not be mirrored from inside the plugin tree.
12
+ */
13
+ import { motion, AnimatePresence } from "framer-motion";
14
+ import { X, CheckCircle, AlertCircle, Info, AlertTriangle } from "lucide-react";
15
+ import { Alert, AlertDescription } from "../internal/ui/alert.js";
16
+ import { createContext, useContext, useState, useCallback, } from "react";
17
+ import { useTheme } from "../theme/ThemeProvider.js";
18
+ import { intentForVariant } from "../theme/derive.js";
19
+ import { ThemedButton } from "./ThemedButton.js";
20
+ const ToastContext = createContext(null);
21
+ export function ToastProvider({ children }) {
22
+ const [toasts, setToasts] = useState([]);
23
+ const show = useCallback((message, type = "info", duration = 3000) => {
24
+ const id = `toast-${Date.now()}-${Math.random()}`;
25
+ const toast = { id, type, message, duration };
26
+ setToasts((prev) => {
27
+ // Dedup by `(type, message)` so a fast burst of identical
28
+ // toasts collapses to one visible toast instead of stacking
29
+ // and producing the flicker effect (toast-1 dismisses while
30
+ // toast-2 mounts → user sees a flash). Keep the existing
31
+ // entry untouched so its dismiss timer continues.
32
+ if (prev.some((item) => item.type === type && item.message === message)) {
33
+ return prev;
34
+ }
35
+ return [...prev, toast];
36
+ });
37
+ if (duration > 0) {
38
+ setTimeout(() => {
39
+ setToasts((prev) => prev.filter((t) => t.id !== id));
40
+ }, duration);
41
+ }
42
+ }, []);
43
+ const dismiss = useCallback((id) => {
44
+ setToasts((prev) => prev.filter((t) => t.id !== id));
45
+ }, []);
46
+ const success = useCallback((message, duration) => show(message, "success", duration), [show]);
47
+ const error = useCallback((message, duration) => show(message, "error", duration), [show]);
48
+ const info = useCallback((message, duration) => show(message, "info", duration), [show]);
49
+ const warning = useCallback((message, duration) => show(message, "warning", duration), [show]);
50
+ return (_jsxs(ToastContext.Provider, { value: { toasts, show, dismiss, success, error, info, warning }, children: [children, _jsx(ToastContainer, { toasts: toasts, onDismiss: dismiss })] }));
51
+ }
52
+ export function useToast() {
53
+ const context = useContext(ToastContext);
54
+ if (!context) {
55
+ throw new Error("useToast must be used within ToastProvider");
56
+ }
57
+ return context;
58
+ }
59
+ function ToastContainer({ toasts, onDismiss, }) {
60
+ return (_jsx("div", { className: "fixed bottom-4 right-4 z-50 flex flex-col gap-2 pointer-events-none", role: "region", "aria-live": "polite", "aria-label": "Notifications", children: _jsx(AnimatePresence, { children: toasts.map((toast) => (_jsx(ToastItem, { toast: toast, onDismiss: onDismiss }, toast.id))) }) }));
61
+ }
62
+ const TOAST_ICONS = {
63
+ success: CheckCircle,
64
+ error: AlertCircle,
65
+ info: Info,
66
+ warning: AlertTriangle,
67
+ };
68
+ const TOAST_VARIANT = {
69
+ success: "success",
70
+ error: "danger",
71
+ info: "info",
72
+ warning: "warning",
73
+ };
74
+ function toastSurfaceStyle(theme, type) {
75
+ const intent = intentForVariant(theme, TOAST_VARIANT[type]);
76
+ return {
77
+ minWidth: 280,
78
+ maxWidth: 400,
79
+ display: "flex",
80
+ alignItems: "flex-start",
81
+ gap: theme.space[3],
82
+ padding: theme.space[4],
83
+ background: intent.soft,
84
+ color: intent.onSoft,
85
+ border: `2px solid ${intent.border}`,
86
+ borderRadius: theme.radius.lg,
87
+ boxShadow: theme.elevation.lifted,
88
+ backdropFilter: "blur(4px)",
89
+ WebkitBackdropFilter: "blur(4px)",
90
+ fontFamily: theme.typography.fontFamily.body,
91
+ };
92
+ }
93
+ function ToastItem({ toast, onDismiss, }) {
94
+ const theme = useTheme();
95
+ const reducedMotion = theme.motion.reducedMotion === "true";
96
+ const Icon = TOAST_ICONS[toast.type];
97
+ const intent = intentForVariant(theme, TOAST_VARIANT[toast.type]);
98
+ const surfaceStyle = toastSurfaceStyle(theme, toast.type);
99
+ return (_jsx(motion.div, { style: { pointerEvents: "auto" }, initial: reducedMotion ? { opacity: 0 } : { opacity: 0, y: 20, scale: 0.9 }, animate: reducedMotion ? { opacity: 1 } : { opacity: 1, y: 0, scale: 1 }, exit: reducedMotion ? { opacity: 0 } : { opacity: 0, x: 100, scale: 0.9 }, transition: { type: "spring", stiffness: 300, damping: 25 }, children: _jsxs(Alert, { variant: toast.type === "error" ? "destructive" : "default", style: surfaceStyle, children: [_jsx(Icon, { size: 20, style: {
100
+ marginTop: 2,
101
+ flexShrink: 0,
102
+ color: intent.solid,
103
+ }, "aria-hidden": "true" }), _jsx(AlertDescription, { style: {
104
+ flex: 1,
105
+ fontSize: theme.typography.fontSize.sm,
106
+ fontWeight: theme.typography.fontWeight.medium,
107
+ lineHeight: theme.typography.lineHeight.relaxed,
108
+ color: intent.onSoft,
109
+ }, children: toast.message }), _jsx(ThemedButton, { type: "button", variant: "ghost", size: "sm", onClick: () => onDismiss(toast.id), style: {
110
+ height: 28,
111
+ width: 28,
112
+ flexShrink: 0,
113
+ borderRadius: theme.radius.pill,
114
+ color: intent.onSoft,
115
+ }, "aria-label": "Close notification", children: _jsx(X, { size: 16, "aria-hidden": "true" }) })] }) }));
116
+ }