@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,111 @@
1
+ import type { CSSProperties, 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
+ /**
6
+ * Resolved salience tier for a panel interaction. Authors set
7
+ * `descriptor.salience` directly; when omitted we derive a sensible
8
+ * default from `descriptor.emphasis` so existing workspaces inherit
9
+ * the new ordering / disclosure behaviour without being touched.
10
+ *
11
+ * - `descriptor.salience === "hero"` → `hero`
12
+ * - `descriptor.salience === "tertiary"` → `tertiary`
13
+ * - `descriptor.emphasis === "primary"` → `hero`
14
+ * - `descriptor.emphasis === "destructive"` → `tertiary`
15
+ * - everything else → `secondary` (the default tier)
16
+ */
17
+ export type PanelSalience = "hero" | "secondary" | "tertiary";
18
+ export interface PanelSurfaceProps<I extends string = never, ParamsByKey extends Partial<InteractionParamsByKeyShape> = {}> {
19
+ /**
20
+ * Optional per-interaction overrides. Omit entirely to use the default
21
+ * renderer (`DefaultInteractionButton`) for every interaction; supply a
22
+ * partial map to replace the default UI for specific interaction ids.
23
+ */
24
+ render?: SurfaceRenderMap<I, ParamsByKey>;
25
+ /**
26
+ * Fallback renderer for interactions without a `render` entry. Defaults
27
+ * to the built-in `DefaultInteractionButton` which honours metadata
28
+ * (`icon`, `label`, `emphasis`, `unavailableReason`).
29
+ */
30
+ renderItem?: (descriptor: InteractionDescriptor<I>, handle: InteractionHandle<InteractionParamsOf<ParamsByKey, I>, InteractionDefaultedKeysOf<ParamsByKey, I>>) => ReactNode;
31
+ /** Shown when no panel interactions are available. */
32
+ empty?: ReactNode;
33
+ /**
34
+ * Optional grouping function. Defaults to `descriptor.group`; authors
35
+ * can override to cluster interactions differently. Returning
36
+ * `undefined` keeps the interaction in the ungrouped tail cluster.
37
+ */
38
+ groupBy?: (descriptor: InteractionDescriptor<I>) => string | undefined;
39
+ /**
40
+ * Override the default salience derivation. Receives the descriptor
41
+ * and returns the tier it should occupy. Use to demote something the
42
+ * authoring layer mis-tagged as `emphasis: "primary"` without
43
+ * changing the upstream contract.
44
+ */
45
+ salienceFor?: (descriptor: InteractionDescriptor<I>) => PanelSalience;
46
+ /**
47
+ * Maximum number of `secondary`-tier items to render directly in the
48
+ * panel. Excess secondaries spill into the {@link MoreActions}
49
+ * disclosure (alongside the always-disclosed `tertiary` tier).
50
+ * Defaults to `Infinity` — secondaries stay visible. Lower this on
51
+ * dense HUDs to fight Hick's Law.
52
+ *
53
+ * Hero items are never spilled, so a panel with three hero entries
54
+ * and `maxVisibleSecondary: 0` still renders three buttons inline
55
+ * plus the disclosure.
56
+ */
57
+ maxVisibleSecondary?: number;
58
+ /**
59
+ * Label for the disclosure toggle. Defaults to `"More"`. Pass a
60
+ * workspace-specific copy ("Advanced", "Manage", …) when the
61
+ * generic label feels wrong.
62
+ */
63
+ moreActionsLabel?: string;
64
+ /** Interaction keys intentionally rendered elsewhere, such as auto primary actions. */
65
+ excludeInteractionKeys?: readonly string[];
66
+ /**
67
+ * Render unavailable interactions as disabled items. Defaults to false so
68
+ * stale-step actions do not compete with legal actions.
69
+ */
70
+ showUnavailable?: boolean;
71
+ /**
72
+ * Layout overrides for the default container. Useful for tightly
73
+ * constrained mobile layouts. When the caller supplies their own
74
+ * `render` for every interaction they can ignore these entirely.
75
+ */
76
+ layout?: {
77
+ direction?: "row" | "column";
78
+ wrap?: boolean;
79
+ gap?: CSSProperties["gap"];
80
+ align?: CSSProperties["alignItems"];
81
+ justify?: CSSProperties["justifyContent"];
82
+ };
83
+ }
84
+ /**
85
+ * Default salience resolver — see {@link PanelSalience}. Exported so
86
+ * authors who want to slightly tweak the policy can compose with it
87
+ * (`salienceFor: (d) => d.id === "x" ? "hero" : defaultPanelSalience(d)`).
88
+ */
89
+ export declare function defaultPanelSalience(_descriptor: InteractionDescriptor): PanelSalience;
90
+ /**
91
+ * Default renderer for `surface: "panel"` interactions.
92
+ *
93
+ * Visual styling comes entirely from the active {@link useTheme}; mount
94
+ * `<ThemeProvider theme={...}/>` to swap the look. Per-interaction overrides
95
+ * via `render` are the escape hatch when a specific interaction needs bespoke
96
+ * UI.
97
+ *
98
+ * Salience policy
99
+ * ===============
100
+ * Each descriptor is assigned a {@link PanelSalience} via
101
+ * {@link defaultPanelSalience} (override with the `salienceFor` prop).
102
+ * The panel sorts groups so `hero` items render first, then
103
+ * `secondary`, then `tertiary` — and the `tertiary` cluster (plus any
104
+ * spill from `maxVisibleSecondary`) lives behind a {@link MoreActions}
105
+ * disclosure so a crowded panel doesn't drown the player in choices
106
+ * (Hick's Law). Groups stay contiguous: a group inherits the highest
107
+ * salience among its members so a hero+secondary cluster doesn't get
108
+ * split across the disclosure boundary.
109
+ */
110
+ export declare function PanelSurface<I extends string = never, ParamsByKey extends Partial<InteractionParamsByKeyShape> = {}>({ render, renderItem, empty, groupBy, salienceFor, maxVisibleSecondary, moreActionsLabel, excludeInteractionKeys, showUnavailable, layout, }: PanelSurfaceProps<I, ParamsByKey>): import("react/jsx-runtime").JSX.Element;
111
+ //# sourceMappingURL=PanelSurface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PanelSurface.d.ts","sourceRoot":"","sources":["../../../src/components/surfaces/PanelSurface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,qCAAqC,CAAC;AAE7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAGzE,OAAO,KAAK,EACV,0BAA0B,EAC1B,2BAA2B,EAC3B,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;AAE9D,MAAM,WAAW,iBAAiB,CAChC,CAAC,SAAS,MAAM,GAAG,KAAK,EACxB,WAAW,SAAS,OAAO,CAAC,2BAA2B,CAAC,GAAG,EAAE;IAE7D;;;;OAIG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IAC1C;;;;OAIG;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,sDAAsD;IACtD,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;IACvE;;;;;OAKG;IACH,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC;IACtE;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,sBAAsB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;QAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,GAAG,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3B,KAAK,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;QACpC,OAAO,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;KAC3C,CAAC;CACH;AAQD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,qBAAqB,GACjC,aAAa,CAEf;AAkBD;;;;;;;;;;;;;;;;;;;GAmBG;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,OAAyB,EACzB,WAAW,EACX,mBAA8C,EAC9C,gBAAgB,EAChB,sBAAsB,EACtB,eAAuB,EACvB,MAAM,GACP,EAAE,iBAAiB,CAAC,CAAC,EAAE,WAAW,CAAC,2CAkGnC"}
@@ -0,0 +1,180 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useSeatInbox } from "../../hooks/useSeatInbox.js";
3
+ import { useInteractionHandle, } from "../../hooks/useInteractionHandle.js";
4
+ import { useTheme } from "../../theme/ThemeProvider.js";
5
+ import { DefaultInteractionButton } from "./internal/DefaultInteractionButton.js";
6
+ import { MoreActions } from "../MoreActions.js";
7
+ const SALIENCE_RANK = {
8
+ hero: 0,
9
+ secondary: 1,
10
+ tertiary: 2,
11
+ };
12
+ /**
13
+ * Default salience resolver — see {@link PanelSalience}. Exported so
14
+ * authors who want to slightly tweak the policy can compose with it
15
+ * (`salienceFor: (d) => d.id === "x" ? "hero" : defaultPanelSalience(d)`).
16
+ */
17
+ export function defaultPanelSalience(_descriptor) {
18
+ return "secondary";
19
+ }
20
+ // `align: "flex-start"` is deliberate. Panel items are heterogeneous —
21
+ // a `DefaultInteractionButton` sits next to authored cards that can
22
+ // expand into multi-row draft forms (e.g. an offer-trade card). With
23
+ // `stretch` the short buttons get dragged to the tallest sibling's
24
+ // height and render as floor-to-ceiling bars next to the expanded form.
25
+ // Authors who *do* want uniform heights can opt in via `layout.align`.
26
+ const defaultLayout = {
27
+ direction: "row",
28
+ wrap: true,
29
+ gap: "8px",
30
+ align: "flex-start",
31
+ justify: "flex-start",
32
+ };
33
+ /**
34
+ * Default renderer for `surface: "panel"` interactions.
35
+ *
36
+ * Visual styling comes entirely from the active {@link useTheme}; mount
37
+ * `<ThemeProvider theme={...}/>` to swap the look. Per-interaction overrides
38
+ * via `render` are the escape hatch when a specific interaction needs bespoke
39
+ * UI.
40
+ *
41
+ * Salience policy
42
+ * ===============
43
+ * Each descriptor is assigned a {@link PanelSalience} via
44
+ * {@link defaultPanelSalience} (override with the `salienceFor` prop).
45
+ * The panel sorts groups so `hero` items render first, then
46
+ * `secondary`, then `tertiary` — and the `tertiary` cluster (plus any
47
+ * spill from `maxVisibleSecondary`) lives behind a {@link MoreActions}
48
+ * disclosure so a crowded panel doesn't drown the player in choices
49
+ * (Hick's Law). Groups stay contiguous: a group inherits the highest
50
+ * salience among its members so a hero+secondary cluster doesn't get
51
+ * split across the disclosure boundary.
52
+ */
53
+ export function PanelSurface({ render, renderItem, empty = null, groupBy = () => undefined, salienceFor, maxVisibleSecondary = Number.POSITIVE_INFINITY, moreActionsLabel, excludeInteractionKeys, showUnavailable = false, layout, }) {
54
+ const inbox = useSeatInbox();
55
+ const excluded = new Set(excludeInteractionKeys ?? []);
56
+ const items = (inbox.bySurface.panel ?? []).filter((descriptor) => !excluded.has(descriptor.interactionKey) &&
57
+ (showUnavailable || descriptor.available));
58
+ if (items.length === 0)
59
+ return _jsx(_Fragment, { children: empty });
60
+ const resolvedLayout = { ...defaultLayout, ...(layout ?? {}) };
61
+ const resolveSalience = salienceFor ?? defaultPanelSalience;
62
+ // Compute groups first (preserves authored cohesion), then assign
63
+ // each group a tier from its highest-salience member, then sort by
64
+ // tier while keeping members in their original order.
65
+ const grouped = groupInteractions(items, groupBy, resolveSalience);
66
+ const sorted = [...grouped].sort((a, b) => {
67
+ const tierDiff = SALIENCE_RANK[a.tier] - SALIENCE_RANK[b.tier];
68
+ if (tierDiff !== 0)
69
+ return tierDiff;
70
+ // Same tier — preserve authored order via the cached index.
71
+ return a.firstIndex - b.firstIndex;
72
+ });
73
+ // Decide which groups stay in the main row vs. spill into the
74
+ // disclosure. Hero groups always stay; tertiary groups always
75
+ // spill; secondary groups spill once we've already shown
76
+ // `maxVisibleSecondary` of them. A group counts as 1 toward the
77
+ // budget regardless of how many descriptors it contains — losing
78
+ // half a "build" cluster would be more confusing than rendering
79
+ // the whole sub-row.
80
+ const visible = [];
81
+ const disclosed = [];
82
+ let secondariesShown = 0;
83
+ for (const group of sorted) {
84
+ if (group.tier === "hero") {
85
+ visible.push(group);
86
+ continue;
87
+ }
88
+ if (group.tier === "tertiary") {
89
+ disclosed.push(group);
90
+ continue;
91
+ }
92
+ if (secondariesShown < maxVisibleSecondary) {
93
+ visible.push(group);
94
+ secondariesShown += 1;
95
+ }
96
+ else {
97
+ disclosed.push(group);
98
+ }
99
+ }
100
+ // Count the underlying descriptors so the disclosure badge reads
101
+ // "More (3)" not "More (1 group)".
102
+ const disclosedCount = disclosed.reduce((sum, group) => sum + group.interactions.length, 0);
103
+ return (_jsxs("div", { role: "toolbar", "aria-label": "Panel actions", "data-shell-slot": "panel-actions", style: {
104
+ display: "flex",
105
+ flexDirection: resolvedLayout.direction,
106
+ flexWrap: resolvedLayout.wrap ? "wrap" : "nowrap",
107
+ gap: resolvedLayout.gap,
108
+ alignItems: resolvedLayout.align,
109
+ justifyContent: resolvedLayout.justify,
110
+ }, children: [visible.map((group) => (_jsx(PanelGroup, { group: group, render: render, renderItem: renderItem }, group.id))), disclosed.length > 0 ? (_jsx(MoreActions, { label: moreActionsLabel, count: disclosedCount, children: disclosed.map((group) => (_jsx(PanelGroup, { group: group, render: render, renderItem: renderItem }, group.id))) })) : null] }));
111
+ }
112
+ function groupInteractions(items, groupBy, resolveSalience) {
113
+ const ordered = [];
114
+ const byGroup = new Map();
115
+ items.forEach((descriptor, index) => {
116
+ const tier = resolveSalience(descriptor);
117
+ const key = groupBy(descriptor);
118
+ if (key === undefined) {
119
+ ordered.push({
120
+ id: `solo:${descriptor.interactionId}`,
121
+ grouped: false,
122
+ interactions: [descriptor],
123
+ tier,
124
+ firstIndex: index,
125
+ });
126
+ return;
127
+ }
128
+ const bucket = byGroup.get(key);
129
+ if (bucket) {
130
+ bucket.interactions.push(descriptor);
131
+ if (SALIENCE_RANK[tier] < SALIENCE_RANK[bucket.tier]) {
132
+ bucket.tier = tier;
133
+ }
134
+ return;
135
+ }
136
+ const fresh = {
137
+ id: `group:${key}`,
138
+ grouped: true,
139
+ interactions: [descriptor],
140
+ tier,
141
+ firstIndex: index,
142
+ };
143
+ byGroup.set(key, fresh);
144
+ ordered.push(fresh);
145
+ });
146
+ return ordered.map((bucket) => ({
147
+ id: bucket.id,
148
+ interactions: bucket.interactions,
149
+ grouped: bucket.grouped,
150
+ tier: bucket.tier,
151
+ firstIndex: bucket.firstIndex,
152
+ }));
153
+ }
154
+ function PanelGroup({ group, render, renderItem, }) {
155
+ const theme = useTheme();
156
+ if (!group.grouped || group.interactions.length === 1) {
157
+ return (_jsx(_Fragment, { children: group.interactions.map((descriptor) => (_jsx(PanelItem, { descriptor: descriptor, render: render, renderItem: renderItem, tier: group.tier }, descriptor.interactionKey))) }));
158
+ }
159
+ return (_jsx("div", { "data-panel-group": group.id, "data-panel-tier": group.tier, style: {
160
+ display: "inline-flex",
161
+ gap: theme.space[1],
162
+ padding: theme.space[1],
163
+ borderRadius: theme.radius.lg,
164
+ background: theme.semantic.surface.inset,
165
+ }, children: group.interactions.map((descriptor) => (_jsx(PanelItem, { descriptor: descriptor, render: render, renderItem: renderItem, compact: true, tier: group.tier }, descriptor.interactionKey))) }));
166
+ }
167
+ function PanelItem({ descriptor, render, renderItem, compact, tier, }) {
168
+ const handle = useInteractionHandle(descriptor);
169
+ const override = render?.[descriptor.interactionKey];
170
+ if (override)
171
+ return _jsx(_Fragment, { children: override(descriptor, handle) });
172
+ if (renderItem)
173
+ return _jsx(_Fragment, { children: renderItem(descriptor, handle) });
174
+ // Salience-driven sizing: hero buttons use the `lg` size so they
175
+ // outweigh the `secondary` tier next to them. Tertiary items render
176
+ // inside the disclosure where the smaller `sm` size keeps the
177
+ // disclosed cluster from feeling like a second main panel.
178
+ const size = compact || tier === "tertiary" ? "sm" : tier === "hero" ? "lg" : "md";
179
+ return (_jsx(DefaultInteractionButton, { descriptor: descriptor, handle: handle, compact: compact, size: size, "data-panel-tier": tier }));
180
+ }
@@ -0,0 +1,104 @@
1
+ import { type ReactNode } from "react";
2
+ import type { ViewCard } from "@dreamboard/sdk-types";
3
+ import type { CardSize, HandLayout } from "../../hooks/useHandLayout.js";
4
+ import { type CardZoneInteractionContext } from "./internal/useCardZoneInteractions.js";
5
+ import type { InteractionParamsByKeyShape } from "./types.js";
6
+ export type PlayerCardsLayout<ZoneKey extends string = string> = PlayerCardZoneNode<ZoneKey> | PlayerCardsGroup<ZoneKey>;
7
+ export interface PlayerCardsGroup<ZoneKey extends string = string> {
8
+ kind: "group";
9
+ direction: "row" | "column";
10
+ children: ReadonlyArray<PlayerCardsLayout<ZoneKey>>;
11
+ }
12
+ export interface PlayerCardZoneModel<I extends string = string> {
13
+ zoneId: string;
14
+ label: string;
15
+ totalCount: number;
16
+ visibleCards: readonly ViewCard[];
17
+ hiddenCount: number;
18
+ hiddenCardIds: readonly string[];
19
+ contexts: ReadonlyArray<CardZoneInteractionContext<I>>;
20
+ contextsByCardId: ReadonlyMap<string, CardZoneInteractionContext<I>>;
21
+ }
22
+ export type PlayerCardZoneNode<ZoneKey extends string = string> = PlayerCardsPileNode<ZoneKey> | PlayerCardsFanNode<ZoneKey> | PlayerCardsCustomNode<ZoneKey>;
23
+ export interface PlayerCardsPileNode<ZoneKey extends string = string> {
24
+ kind: "pile";
25
+ zone: ZoneKey;
26
+ label?: string;
27
+ top?: "first" | "last";
28
+ details?: "drawer" | "none";
29
+ /**
30
+ * Explicit override for the count badge. Use when the player view
31
+ * hides the zone's `cardIds` (private decks, hidden draw piles) so
32
+ * the SDK's auto-derived `zone.totalCount` reads zero. The reducer
33
+ * still owns the source of truth — pass it through `defineView`.
34
+ */
35
+ count?: number;
36
+ /**
37
+ * Explicit override for the visible top-card preview. Use when the
38
+ * top card isn't part of the player's zone projection but is known
39
+ * via a custom view field. Falls back to {@link top} selection over
40
+ * `zone.visibleCards` when omitted.
41
+ */
42
+ topCard?: ViewCard | null;
43
+ /**
44
+ * Replace just the visible top-card / face-down preview while keeping
45
+ * the SDK's button + count badge + drawer machinery. Use this when you
46
+ * want a custom card face but still want clicks to open the drawer.
47
+ */
48
+ renderPreview?: (zone: PlayerCardZoneModel) => ReactNode;
49
+ /** Replace the empty-state (no cards) preview only. */
50
+ renderEmpty?: (zone: PlayerCardZoneModel) => ReactNode;
51
+ /**
52
+ * Per-card content renderer used by the default drawer body. Authors
53
+ * who supply this on every node can hoist it to the surface root via
54
+ * {@link PlayerCardsSurfaceConfig.renderCardContent}.
55
+ */
56
+ renderCardContent?: (card: ViewCard, ctx: CardZoneInteractionContext) => ReactNode;
57
+ /** Replace the drawer body wholesale. */
58
+ renderDrawerContent?: (zone: PlayerCardZoneModel) => ReactNode;
59
+ /**
60
+ * Escape hatch — replaces the pile entirely (button, count badge,
61
+ * drawer, click handling). Prefer {@link renderPreview} +
62
+ * {@link renderDrawerContent} so authors don't accidentally drop the
63
+ * default click-to-open behavior. Reserved for cases that need fully
64
+ * bespoke chrome.
65
+ */
66
+ renderPile?: (zone: PlayerCardZoneModel) => ReactNode;
67
+ }
68
+ export interface PlayerCardsFanNode<ZoneKey extends string = string> {
69
+ kind: "fan";
70
+ zone: ZoneKey;
71
+ label?: string;
72
+ renderCardContent?: (card: ViewCard, ctx: CardZoneInteractionContext) => ReactNode;
73
+ renderZone?: (zone: PlayerCardZoneModel) => ReactNode;
74
+ cardSize?: CardSize;
75
+ layout?: HandLayout;
76
+ }
77
+ export interface PlayerCardsCustomNode<ZoneKey extends string = string> {
78
+ kind: "custom";
79
+ zone: ZoneKey;
80
+ label?: string;
81
+ renderZone: (zone: PlayerCardZoneModel) => ReactNode;
82
+ }
83
+ export interface PlayerCardsSurfaceConfig<ZoneKey extends string = string> {
84
+ layout: PlayerCardsLayout<ZoneKey>;
85
+ /**
86
+ * Default per-card content renderer inherited by every `pile` and
87
+ * `fan` in the layout. Per-node `renderCardContent` (on a fan) or
88
+ * `renderCardContent` / `renderPreview` (on a pile) still wins. Set
89
+ * this once at the surface root to avoid passing the same `<CardFace>`
90
+ * to every zone.
91
+ */
92
+ renderCardContent?: (card: ViewCard, ctx: CardZoneInteractionContext) => ReactNode;
93
+ }
94
+ export interface PlayerCardsSurfaceProps<ZoneKey extends string = string> extends PlayerCardsSurfaceConfig<ZoneKey> {
95
+ empty?: ReactNode;
96
+ }
97
+ export declare function definePlayerCardsSurface<const Config extends PlayerCardsSurfaceConfig<string>>(config: Config): Config;
98
+ export declare function row<const ZoneKey extends string>(children: ReadonlyArray<PlayerCardsLayout<ZoneKey>>): PlayerCardsGroup<ZoneKey>;
99
+ export declare function column<const ZoneKey extends string>(children: ReadonlyArray<PlayerCardsLayout<ZoneKey>>): PlayerCardsGroup<ZoneKey>;
100
+ export declare function pile<const ZoneKey extends string>(zone: ZoneKey, options?: Omit<PlayerCardsPileNode<ZoneKey>, "kind" | "zone">): PlayerCardsPileNode<ZoneKey>;
101
+ export declare function fan<const ZoneKey extends string>(zone: ZoneKey, options?: Omit<PlayerCardsFanNode<ZoneKey>, "kind" | "zone">): PlayerCardsFanNode<ZoneKey>;
102
+ export declare function custom<const ZoneKey extends string>(zone: ZoneKey, options: Omit<PlayerCardsCustomNode<ZoneKey>, "kind" | "zone">): PlayerCardsCustomNode<ZoneKey>;
103
+ export declare function PlayerCardsSurface<I extends string = never, ParamsByKey extends Partial<InteractionParamsByKeyShape> = {}, ZoneKey extends string = string>({ layout, renderCardContent, empty, }: PlayerCardsSurfaceProps<ZoneKey>): import("react/jsx-runtime").JSX.Element;
104
+ //# sourceMappingURL=PlayerCardsSurface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlayerCardsSurface.d.ts","sourceRoot":"","sources":["../../../src/components/surfaces/PlayerCardsSurface.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,178 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Fragment, useMemo, useState } from "react";
3
+ import { usePluginState } from "../../context/PluginStateContext.js";
4
+ import { useTheme } from "../../theme/ThemeProvider.js";
5
+ import { Card } from "../Card.js";
6
+ import { Drawer, DrawerContent, DrawerHeader, DrawerTitle } from "../Drawer.js";
7
+ import { Hand } from "../Hand.js";
8
+ import { useCardZoneInteractions, } from "./internal/useCardZoneInteractions.js";
9
+ import { CardZoneFollowUpForm } from "./internal/CardZoneFollowUpForm.js";
10
+ export function definePlayerCardsSurface(config) {
11
+ return config;
12
+ }
13
+ export function row(children) {
14
+ return { kind: "group", direction: "row", children };
15
+ }
16
+ export function column(children) {
17
+ return { kind: "group", direction: "column", children };
18
+ }
19
+ export function pile(zone, options = {}) {
20
+ return { kind: "pile", zone, ...options };
21
+ }
22
+ export function fan(zone, options = {}) {
23
+ return { kind: "fan", zone, ...options };
24
+ }
25
+ export function custom(zone, options) {
26
+ return { kind: "custom", zone, ...options };
27
+ }
28
+ export function PlayerCardsSurface({ layout, renderCardContent, empty = null, }) {
29
+ if (!layout)
30
+ return _jsx(_Fragment, { children: empty });
31
+ return (_jsx(PlayerCardsLayoutNode, { layout: layout, surfaceRenderCardContent: renderCardContent }));
32
+ }
33
+ function PlayerCardsLayoutNode({ layout, surfaceRenderCardContent, }) {
34
+ const theme = useTheme();
35
+ if (layout.kind === "group") {
36
+ return (_jsx("div", { "data-player-cards-group": layout.direction, style: {
37
+ display: "flex",
38
+ flexDirection: layout.direction,
39
+ gap: theme.space[2],
40
+ alignItems: layout.direction === "row" ? "flex-end" : "stretch",
41
+ // Fill the parent so flex children (especially the fan with
42
+ // `flex: 1 1 ...`) can grow to use the available width.
43
+ // Without this, the row collapses to its children's intrinsic
44
+ // size and the fan never gets room to spread.
45
+ width: "100%",
46
+ minWidth: 0,
47
+ }, children: layout.children.map((child, index) => (_jsx(PlayerCardsLayoutNode, { layout: child, surfaceRenderCardContent: surfaceRenderCardContent }, index))) }));
48
+ }
49
+ return (_jsx(PlayerCardsZoneNode, { node: layout, surfaceRenderCardContent: surfaceRenderCardContent }));
50
+ }
51
+ function PlayerCardsZoneNode({ node, surfaceRenderCardContent, }) {
52
+ const zone = usePlayerCardZone(String(node.zone), node.label);
53
+ if (node.kind === "custom")
54
+ return _jsx(_Fragment, { children: node.renderZone(zone) });
55
+ if (node.kind === "pile") {
56
+ return (_jsx(PlayerCardsPile, { node: node, zone: zone, surfaceRenderCardContent: surfaceRenderCardContent }));
57
+ }
58
+ return (_jsx(PlayerCardsFan, { node: node, zone: zone, surfaceRenderCardContent: surfaceRenderCardContent }));
59
+ }
60
+ function usePlayerCardZone(zoneId, label) {
61
+ const interactions = useCardZoneInteractions(zoneId, { surface: "hand" });
62
+ const zone = usePluginState((s) => s.gameplay.zones?.[zoneId]);
63
+ return useMemo(() => {
64
+ const cardIds = zone?.cardIds ?? [];
65
+ const visibleIds = new Set(interactions.cards.map((card) => card.id));
66
+ const contextsByCardId = new Map(interactions.contexts.map((ctx) => [ctx.card.id, ctx]));
67
+ return {
68
+ ...interactions,
69
+ zoneId,
70
+ label: label ?? zoneId,
71
+ totalCount: cardIds.length,
72
+ visibleCards: interactions.cards,
73
+ hiddenCount: Math.max(0, cardIds.length - interactions.cards.length),
74
+ hiddenCardIds: cardIds.filter((cardId) => !visibleIds.has(cardId)),
75
+ contexts: interactions.contexts,
76
+ contextsByCardId,
77
+ };
78
+ }, [interactions, label, zone?.cardIds, zoneId]);
79
+ }
80
+ function PlayerCardsPile({ node, zone, surfaceRenderCardContent, }) {
81
+ const [open, setOpen] = useState(false);
82
+ const top = node.top ?? "first";
83
+ const previewCard = node.topCard !== undefined
84
+ ? node.topCard
85
+ : top === "last"
86
+ ? (zone.visibleCards[zone.visibleCards.length - 1] ?? null)
87
+ : (zone.visibleCards[0] ?? null);
88
+ const totalCount = node.count ?? zone.totalCount;
89
+ const drawerEnabled = (node.details ?? "drawer") !== "none";
90
+ const cardContent = node.renderCardContent ?? surfaceRenderCardContent;
91
+ // Full escape hatch — author owns button + drawer + everything.
92
+ if (node.renderPile)
93
+ return _jsx(_Fragment, { children: node.renderPile(zone) });
94
+ const previewNode = node.renderPreview ? (node.renderPreview(zone)) : previewCard ? (_jsx(Card, { card: previewCard, disabled: true, size: "sm", renderContent: cardContent
95
+ ? (card) => {
96
+ const ctx = zone.contextsByCardId.get(card.id);
97
+ return cardContent(card, ctx ?? emptyZoneContext(card));
98
+ }
99
+ : undefined })) : node.renderEmpty ? (node.renderEmpty(zone)) : (_jsx("div", { "aria-label": "Hidden card", style: {
100
+ width: 72,
101
+ height: 100,
102
+ borderRadius: 8,
103
+ border: "2px solid #111",
104
+ background: "repeating-linear-gradient(135deg, #ddd, #ddd 6px, #bbb 6px, #bbb 12px)",
105
+ } }));
106
+ return (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", "data-player-cards-pile": zone.zoneId, onClick: () => {
107
+ if (drawerEnabled)
108
+ setOpen(true);
109
+ }, style: {
110
+ display: "flex",
111
+ flexDirection: "column",
112
+ alignItems: "center",
113
+ gap: 6,
114
+ border: 0,
115
+ background: "transparent",
116
+ padding: 0,
117
+ cursor: drawerEnabled ? "pointer" : "default",
118
+ }, children: [_jsx("span", { style: { fontSize: 12, fontWeight: 700 }, children: zone.label }), _jsxs("div", { style: { position: "relative", minWidth: 72, minHeight: 100 }, children: [previewNode, _jsx("span", { "data-player-cards-pile-count": true, style: {
119
+ position: "absolute",
120
+ right: -6,
121
+ bottom: -6,
122
+ borderRadius: 999,
123
+ padding: "2px 6px",
124
+ background: "#111",
125
+ color: "#fff",
126
+ fontSize: 12,
127
+ }, children: totalCount })] })] }), _jsx(Drawer, { open: open, onOpenChange: setOpen, children: _jsxs(DrawerContent, { children: [_jsx(DrawerHeader, { children: _jsx(DrawerTitle, { children: zone.label }) }), node.renderDrawerContent ? (node.renderDrawerContent(zone)) : (_jsxs("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: [zone.visibleCards.map((card) => (_jsx(Card, { card: card, disabled: true, size: "sm", renderContent: cardContent
128
+ ? (c) => {
129
+ const ctx = zone.contextsByCardId.get(c.id);
130
+ return cardContent(c, ctx ?? emptyZoneContext(c));
131
+ }
132
+ : undefined }, card.id))), Array.from({ length: zone.hiddenCount }).map((_, index) => (_jsx("div", { children: "Hidden card" }, index)))] }))] }) })] }));
133
+ }
134
+ function emptyZoneContext(card) {
135
+ return {
136
+ card,
137
+ interactions: [],
138
+ play: null,
139
+ disabled: true,
140
+ actionState: "unavailable",
141
+ selected: false,
142
+ };
143
+ }
144
+ function PlayerCardsFan({ node, zone, surfaceRenderCardContent, }) {
145
+ const cardSize = node.cardSize ?? "md";
146
+ if (node.renderZone)
147
+ return _jsx(_Fragment, { children: node.renderZone(zone) });
148
+ const renderCardContent = node.renderCardContent ?? surfaceRenderCardContent;
149
+ return (
150
+ // `min-width: 0` lets the flex item shrink below its intrinsic
151
+ // content width when the row's other children need space. `Hand`
152
+ // self-clamps card positions to the measured container width via
153
+ // `useHandLayout`, so cards no longer bleed into sibling piles
154
+ // without us needing to clip the wrapper (which would also
155
+ // suppress the hover-lift translateY above the dock chrome).
156
+ _jsxs("div", { "data-player-cards-fan": zone.zoneId, style: { flex: "1 1 280px", minWidth: 0 }, children: [_jsx(Hand, { cards: zone.visibleCards, cardSize: cardSize, layout: node.layout, renderCard: (props) => {
157
+ const ctx = zone.contextsByCardId.get(props.card.id);
158
+ const disabled = ctx?.disabled ?? true;
159
+ return (_jsx("div", { className: "absolute bottom-0 transition-all duration-150 ease-out", style: {
160
+ left: props.x,
161
+ zIndex: props.zIndex,
162
+ transform: `translateY(${props.y}px)`,
163
+ }, children: _jsx(Card, { card: props.card, selected: props.isSelected, disabled: disabled, size: cardSize, onCardClick: disabled
164
+ ? undefined
165
+ : (cardId) => {
166
+ const clickedCtx = zone.contextsByCardId.get(cardId);
167
+ if (clickedCtx?.play)
168
+ void clickedCtx.play();
169
+ }, renderContent: renderCardContent
170
+ ? (card) => {
171
+ const renderCtx = zone.contextsByCardId.get(card.id);
172
+ if (!renderCtx)
173
+ return null;
174
+ return renderCardContent(card, renderCtx);
175
+ }
176
+ : undefined }) }, props.card.id));
177
+ } }), zone.followUp ? (_jsx(Fragment, { children: _jsx(CardZoneFollowUpForm, { descriptor: zone.followUp, onDone: () => zone.setFollowUp(null) }, zone.followUp.interactionKey) })) : null] }));
178
+ }
@@ -0,0 +1,7 @@
1
+ import type { InteractionDescriptor } from "../../../types/plugin-state.js";
2
+ import type { InteractionParamsByKeyShape } from "../types.js";
3
+ export declare function CardZoneFollowUpForm<I extends string, ParamsByKey extends Partial<InteractionParamsByKeyShape> = {}>({ descriptor, onDone, }: {
4
+ descriptor: InteractionDescriptor<I>;
5
+ onDone: () => void;
6
+ }): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=CardZoneFollowUpForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CardZoneFollowUpForm.d.ts","sourceRoot":"","sources":["../../../../src/components/surfaces/internal/CardZoneFollowUpForm.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,KAAK,EAEV,2BAA2B,EAE5B,MAAM,aAAa,CAAC;AAErB,wBAAgB,oBAAoB,CAClC,CAAC,SAAS,MAAM,EAChB,WAAW,SAAS,OAAO,CAAC,2BAA2B,CAAC,GAAG,EAAE,EAC7D,EACA,UAAU,EACV,MAAM,GACP,EAAE;IACD,UAAU,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB,2CAgBA"}
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { InteractionForm } from "../../InteractionForm.js";
3
+ import { useInteractionHandle } from "../../../hooks/useInteractionHandle.js";
4
+ export function CardZoneFollowUpForm({ descriptor, onDone, }) {
5
+ const handle = useInteractionHandle(descriptor);
6
+ return (_jsx(InteractionForm, { descriptor: descriptor, handle: handle, hiddenFields: [
7
+ "cardId",
8
+ ], onCancel: onDone, onSubmitSuccess: onDone }));
9
+ }