@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,124 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useId, useState } from "react";
3
+ import { Drawer, DrawerContent, DrawerDescription, DrawerHeader, DrawerTitle, DrawerTrigger, } from "./Drawer.js";
4
+ import { useChromeSuppression } from "./ChromeSuppressionContext.js";
5
+ import { ThemedButton } from "./ThemedButton.js";
6
+ import { useThemeCssVars } from "../theme/ThemeProvider.js";
7
+ const DEFAULT_MAX_WIDTH = "min(28rem, calc(100vw - 24px))";
8
+ const DEFAULT_MAX_HEIGHT = "min(65vh, calc(100vh - 96px))";
9
+ function placementStyle(placement) {
10
+ const base = {
11
+ position: "fixed",
12
+ bottom: "calc(12px + env(safe-area-inset-bottom, 0px))",
13
+ zIndex: 900,
14
+ };
15
+ switch (placement) {
16
+ case "bottom-center":
17
+ return {
18
+ ...base,
19
+ left: "50%",
20
+ transform: "translateX(-50%)",
21
+ };
22
+ case "bottom-right":
23
+ return {
24
+ ...base,
25
+ right: "calc(12px + env(safe-area-inset-right, 0px))",
26
+ };
27
+ case "bottom-left":
28
+ default:
29
+ return {
30
+ ...base,
31
+ left: "calc(12px + env(safe-area-inset-left, 0px))",
32
+ };
33
+ }
34
+ }
35
+ function triggerAlignment(placement) {
36
+ switch (placement) {
37
+ case "bottom-center":
38
+ return "center";
39
+ case "bottom-right":
40
+ return "flex-end";
41
+ case "bottom-left":
42
+ default:
43
+ return "flex-start";
44
+ }
45
+ }
46
+ function renderToggleLabel(label, count, open, override) {
47
+ if (typeof override === "function")
48
+ return override({ label, count, open });
49
+ if (override !== undefined)
50
+ return override;
51
+ return `${label} (${count})`;
52
+ }
53
+ export function HandDock({ label, count, presentation, children, }) {
54
+ const mode = presentation?.mode ?? "inline";
55
+ const [open, setOpen] = useState(presentation?.defaultOpen ?? false);
56
+ const contentId = useId();
57
+ const themeCssVars = useThemeCssVars();
58
+ useChromeSuppression(contentId, mode === "drawer" && open);
59
+ if (mode === "hidden")
60
+ return null;
61
+ if (mode === "inline")
62
+ return _jsx(_Fragment, { children: children });
63
+ const placement = presentation?.placement ?? "bottom-left";
64
+ const toggleLabel = renderToggleLabel(label, count, open, presentation?.toggleLabel);
65
+ const fallbackContentStyle = {
66
+ maxHeight: presentation?.maxHeight ?? DEFAULT_MAX_HEIGHT,
67
+ overflow: "auto",
68
+ padding: 12,
69
+ pointerEvents: "auto",
70
+ };
71
+ const triggerStyle = {
72
+ alignSelf: triggerAlignment(placement),
73
+ boxShadow: "0 10px 28px rgba(15, 23, 42, 0.22)",
74
+ pointerEvents: "auto",
75
+ visibility: open ? "hidden" : "visible",
76
+ };
77
+ const canUsePortal = typeof document !== "undefined";
78
+ const serverOpenContent = !canUsePortal && open ? (_jsx("div", { id: contentId, role: "region", "aria-label": label, style: fallbackContentStyle, children: children })) : null;
79
+ return (_jsxs(Drawer, { open: open, onOpenChange: setOpen, direction: "bottom", children: [_jsxs("div", { "data-hand-dock": label, "data-state": open ? "open" : "closed", style: {
80
+ ...placementStyle(placement),
81
+ display: "flex",
82
+ maxWidth: presentation?.maxWidth ?? DEFAULT_MAX_WIDTH,
83
+ width: presentation?.maxWidth ?? DEFAULT_MAX_WIDTH,
84
+ flexDirection: "column",
85
+ alignItems: "stretch",
86
+ gap: 8,
87
+ pointerEvents: "none",
88
+ ...presentation?.style,
89
+ }, children: [serverOpenContent, _jsx(DrawerTrigger, { asChild: true, children: _jsx(ThemedButton, { type: "button", variant: "secondary", size: "sm", "data-state": open ? "open" : "closed", "aria-expanded": open, "aria-controls": open ? contentId : undefined, className: "rounded-full", style: triggerStyle, children: toggleLabel }) })] }), canUsePortal ? (_jsxs(DrawerContent, { id: contentId, "aria-describedby": undefined, className: "border-border bg-background/95 shadow-2xl backdrop-blur supports-[backdrop-filter]:bg-background/90", style: {
90
+ ...themeCssVars,
91
+ position: "fixed",
92
+ right: 0,
93
+ bottom: 0,
94
+ left: 0,
95
+ zIndex: 50,
96
+ display: "flex",
97
+ maxHeight: "80vh",
98
+ flexDirection: "column",
99
+ overflow: "hidden",
100
+ borderTop: "1px solid var(--border, #cbd5e1)",
101
+ borderTopLeftRadius: 16,
102
+ borderTopRightRadius: 16,
103
+ background: "var(--background, rgba(255, 255, 255, 0.96))",
104
+ color: "var(--foreground, #0f172a)",
105
+ fontFamily: "var(--font-sans)",
106
+ boxShadow: "0 -18px 48px rgba(15, 23, 42, 0.22)",
107
+ backdropFilter: "blur(8px)",
108
+ }, children: [_jsxs(DrawerHeader, { className: "border-border border-b px-4 pb-3 pt-3 text-left", style: {
109
+ display: "flex",
110
+ flexDirection: "column",
111
+ gap: 4,
112
+ borderBottom: "1px solid var(--border, #e2e8f0)",
113
+ padding: "12px 16px",
114
+ textAlign: "left",
115
+ }, children: [_jsx(DrawerTitle, { className: "text-base", style: { fontSize: 16, fontWeight: 600, lineHeight: 1.25 }, children: label }), _jsxs(DrawerDescription, { children: [count, " card", count === 1 ? "" : "s", " available."] })] }), _jsx("div", { role: "region", "aria-label": label, style: {
116
+ maxHeight: presentation?.maxHeight ?? DEFAULT_MAX_HEIGHT,
117
+ maxWidth: presentation?.maxWidth ?? DEFAULT_MAX_WIDTH,
118
+ width: "100%",
119
+ margin: "0 auto",
120
+ overflow: "auto",
121
+ padding: "12px 16px calc(16px + env(safe-area-inset-bottom, 0px))",
122
+ boxSizing: "border-box",
123
+ }, className: "mx-auto w-full overflow-y-auto px-4 pb-[calc(1rem+env(safe-area-inset-bottom,0px))] pt-3", children: children })] })) : null] }));
124
+ }
@@ -0,0 +1,50 @@
1
+ import { type CSSProperties, type ReactNode } from "react";
2
+ import type { InteractionHandle, InteractionParamsShape } from "../hooks/useInteractionHandle.js";
3
+ import type { InteractionDescriptor, InteractionInputDescriptor } from "../types/plugin-state.js";
4
+ export interface InteractionFieldRenderProps<Params extends InteractionParamsShape = InteractionParamsShape, Key extends keyof Params & string = keyof Params & string> {
5
+ descriptor: InteractionDescriptor;
6
+ input: InteractionInputDescriptor & {
7
+ key: Key;
8
+ };
9
+ handle: InteractionHandle<Params>;
10
+ value: Params[Key] | undefined;
11
+ setValue: (value: Params[Key]) => void;
12
+ clearValue: () => void;
13
+ errors: readonly string[];
14
+ missing: boolean;
15
+ disabled: boolean;
16
+ }
17
+ export type InteractionFieldRenderMap<Params extends InteractionParamsShape = InteractionParamsShape> = Partial<{
18
+ [K in keyof Params & string]: (props: InteractionFieldRenderProps<Params, K>) => ReactNode;
19
+ }>;
20
+ export interface InteractionFieldProps<Params extends InteractionParamsShape = InteractionParamsShape, Key extends keyof Params & string = keyof Params & string> {
21
+ descriptor: InteractionDescriptor;
22
+ inputKey: Key;
23
+ handle: InteractionHandle<Params>;
24
+ errors?: readonly string[];
25
+ missing?: boolean;
26
+ disabled?: boolean;
27
+ render?: InteractionFieldRenderMap<Params>[Key];
28
+ }
29
+ export interface InteractionFormProps<Params extends InteractionParamsShape = InteractionParamsShape, DefaultedKeys extends keyof Params & string = never> {
30
+ descriptor: InteractionDescriptor;
31
+ handle: InteractionHandle<Params, DefaultedKeys>;
32
+ fields?: ReadonlyArray<keyof Params & string>;
33
+ hiddenFields?: ReadonlyArray<keyof Params & string>;
34
+ renderFields?: InteractionFieldRenderMap<Params>;
35
+ title?: ReactNode;
36
+ description?: ReactNode;
37
+ submitLabel?: ReactNode;
38
+ cancelLabel?: ReactNode;
39
+ onCancel?: () => void;
40
+ onSubmitSuccess?: () => void;
41
+ disabled?: boolean;
42
+ accordion?: boolean;
43
+ defaultOpen?: boolean;
44
+ style?: CSSProperties;
45
+ }
46
+ export declare function InteractionForm<Params extends InteractionParamsShape = InteractionParamsShape, DefaultedKeys extends keyof Params & string = never>({ descriptor, handle, fields, hiddenFields, renderFields, title, description, submitLabel, cancelLabel, onCancel, onSubmitSuccess, disabled, accordion, defaultOpen, style, }: InteractionFormProps<Params, DefaultedKeys>): import("react/jsx-runtime").JSX.Element;
47
+ export declare function InteractionField<Params extends InteractionParamsShape = InteractionParamsShape, Key extends keyof Params & string = keyof Params & string>({ descriptor, inputKey, handle, errors, missing, disabled, render, }: InteractionFieldProps<Params, Key>): import("react/jsx-runtime").JSX.Element | null;
48
+ export declare function hasDefaultInteractionFormFields(descriptor: Pick<InteractionDescriptor, "inputs">): boolean;
49
+ export declare function defaultFormInputs(descriptor: Pick<InteractionDescriptor, "inputs">): InteractionInputDescriptor[];
50
+ //# sourceMappingURL=InteractionForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InteractionForm.d.ts","sourceRoot":"","sources":["../../src/components/InteractionForm.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAElB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAYf,OAAO,KAAK,EAEV,iBAAiB,EACjB,sBAAsB,EACvB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAEV,qBAAqB,EACrB,0BAA0B,EAE3B,MAAM,0BAA0B,CAAC;AAKlC,MAAM,WAAW,2BAA2B,CAC1C,MAAM,SAAS,sBAAsB,GAAG,sBAAsB,EAC9D,GAAG,SAAS,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,MAAM,GAAG,MAAM;IAEzD,UAAU,EAAE,qBAAqB,CAAC;IAClC,KAAK,EAAE,0BAA0B,GAAG;QAAE,GAAG,EAAE,GAAG,CAAA;KAAE,CAAC;IACjD,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;IAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IACvC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,yBAAyB,CACnC,MAAM,SAAS,sBAAsB,GAAG,sBAAsB,IAC5D,OAAO,CAAC;KACT,CAAC,IAAI,MAAM,MAAM,GAAG,MAAM,GAAG,CAC5B,KAAK,EAAE,2BAA2B,CAAC,MAAM,EAAE,CAAC,CAAC,KAC1C,SAAS;CACf,CAAC,CAAC;AAEH,MAAM,WAAW,qBAAqB,CACpC,MAAM,SAAS,sBAAsB,GAAG,sBAAsB,EAC9D,GAAG,SAAS,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,MAAM,GAAG,MAAM;IAEzD,UAAU,EAAE,qBAAqB,CAAC;IAClC,QAAQ,EAAE,GAAG,CAAC;IACd,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,yBAAyB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,oBAAoB,CACnC,MAAM,SAAS,sBAAsB,GAAG,sBAAsB,EAC9D,aAAa,SAAS,MAAM,MAAM,GAAG,MAAM,GAAG,KAAK;IAEnD,UAAU,EAAE,qBAAqB,CAAC;IAClC,MAAM,EAAE,iBAAiB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACjD,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC;IAC9C,YAAY,CAAC,EAAE,aAAa,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC;IACpD,YAAY,CAAC,EAAE,yBAAyB,CAAC,MAAM,CAAC,CAAC;IACjD,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAID,wBAAgB,eAAe,CAC7B,MAAM,SAAS,sBAAsB,GAAG,sBAAsB,EAC9D,aAAa,SAAS,MAAM,MAAM,GAAG,MAAM,GAAG,KAAK,EACnD,EACA,UAAU,EACV,MAAM,EACN,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,KAAK,EACL,WAAW,EACX,WAAW,EACX,WAAsB,EACtB,QAAQ,EACR,eAAe,EACf,QAAgB,EAChB,SAAgB,EAChB,WAAmB,EACnB,KAAK,GACN,EAAE,oBAAoB,CAAC,MAAM,EAAE,aAAa,CAAC,2CA2Q7C;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,SAAS,sBAAsB,GAAG,sBAAsB,EAC9D,GAAG,SAAS,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,MAAM,GAAG,MAAM,EACzD,EACA,UAAU,EACV,QAAQ,EACR,MAAM,EACN,MAA2B,EAC3B,OAAe,EACf,QAAgB,EAChB,MAAM,GACP,EAAE,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,kDAoBpC;AAED,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,CAAC,GAChD,OAAO,CAET;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,CAAC,GAChD,0BAA0B,EAAE,CAY9B"}
@@ -0,0 +1,402 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useId, useMemo, useState, } from "react";
3
+ import * as AccordionPrimitive from "@radix-ui/react-accordion";
4
+ import { Input } from "../internal/ui/input.js";
5
+ import { Label } from "../internal/ui/label.js";
6
+ import { Select, SelectContent, SelectItem, SelectTrigger, } from "../internal/ui/select.js";
7
+ import { surfaceStyle } from "../theme/derive.js";
8
+ import { useTheme, useThemeCssVars } from "../theme/ThemeProvider.js";
9
+ import { interactionLabel } from "../utils/interaction-labels.js";
10
+ import { useChromeSuppression } from "./ChromeSuppressionContext.js";
11
+ import { ThemedButton } from "./ThemedButton.js";
12
+ const EMPTY_FIELD_ERRORS = [];
13
+ export function InteractionForm({ descriptor, handle, fields, hiddenFields, renderFields, title, description, submitLabel, cancelLabel = "Cancel", onCancel, onSubmitSuccess, disabled = false, accordion = true, defaultOpen = false, style, }) {
14
+ const theme = useTheme();
15
+ const fallbackLabel = interactionLabel(descriptor);
16
+ const formId = useId();
17
+ useChromeSuppression(formId, true);
18
+ const [pending, setPending] = useState(false);
19
+ const [validation, setValidation] = useState(null);
20
+ const [formError, setFormError] = useState(null);
21
+ const [accordionOpen, setAccordionOpen] = useState(defaultOpen);
22
+ const hidden = useMemo(() => new Set(hiddenFields ?? []), [hiddenFields]);
23
+ const visibleInputs = useMemo(() => {
24
+ const allowed = fields ? new Set(fields) : null;
25
+ return defaultFormInputs(descriptor).filter((input) => {
26
+ const key = input.key;
27
+ if (allowed && !allowed.has(key))
28
+ return false;
29
+ return !hidden.has(key);
30
+ });
31
+ }, [descriptor, fields, hidden]);
32
+ const currentValidation = validation;
33
+ const fieldErrors = (currentValidation?.fieldErrors ?? {});
34
+ const missing = new Set(currentValidation?.missing ?? []);
35
+ const formErrors = [
36
+ ...(currentValidation?.formErrors ?? []),
37
+ ...(formError ? [formError] : []),
38
+ ];
39
+ const isDisabled = disabled || pending || !descriptor.available;
40
+ const useAccordion = accordion && visibleInputs.length > 0;
41
+ useEffect(() => {
42
+ setAccordionOpen(defaultOpen);
43
+ }, [defaultOpen, descriptor.interactionId]);
44
+ const containerStyle = {
45
+ ...surfaceStyle(theme, { tone: "card" }),
46
+ display: "flex",
47
+ flexDirection: "column",
48
+ gap: theme.space[2],
49
+ padding: theme.space[3],
50
+ minWidth: "min(100%, 280px)",
51
+ boxSizing: "border-box",
52
+ fontFamily: theme.typography.fontFamily.body,
53
+ ...style,
54
+ };
55
+ const submit = async (event) => {
56
+ event.preventDefault();
57
+ if (isDisabled)
58
+ return;
59
+ const nextValidation = handle.validateDraft();
60
+ setValidation(nextValidation);
61
+ setFormError(null);
62
+ if (!nextValidation.ok) {
63
+ setAccordionOpen(true);
64
+ return;
65
+ }
66
+ setPending(true);
67
+ try {
68
+ await handle.submitDraft();
69
+ onSubmitSuccess?.();
70
+ setAccordionOpen(defaultOpen);
71
+ }
72
+ catch (error) {
73
+ setAccordionOpen(true);
74
+ setFormError(error instanceof Error
75
+ ? error.message
76
+ : "Interaction submission failed");
77
+ }
78
+ finally {
79
+ setPending(false);
80
+ }
81
+ };
82
+ const header = (_jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 2 }, children: [_jsx("strong", { style: {
83
+ fontFamily: theme.typography.fontFamily.display,
84
+ fontSize: theme.typography.fontSize.md,
85
+ color: theme.semantic.text.primary,
86
+ }, children: title ?? fallbackLabel }), description ? (_jsx("span", { style: {
87
+ fontSize: theme.typography.fontSize.sm,
88
+ color: theme.semantic.text.muted,
89
+ }, children: description })) : null] }));
90
+ const fieldsContent = visibleInputs.length > 0 ? (_jsx("div", { style: {
91
+ display: "flex",
92
+ flexDirection: "column",
93
+ gap: theme.space[3],
94
+ }, children: visibleInputs.map((input) => {
95
+ const key = input.key;
96
+ return (_jsx(InteractionField, { descriptor: descriptor, inputKey: key, handle: handle, errors: fieldErrors[key] ?? [], missing: missing.has(key), disabled: isDisabled, render: renderFields?.[key] }, input.key));
97
+ }) })) : (_jsx("span", { style: {
98
+ fontSize: theme.typography.fontSize.sm,
99
+ color: theme.semantic.text.muted,
100
+ }, children: "No visible fields are required. Board or card selection may complete this interaction." }));
101
+ const formErrorContent = formErrors.length > 0 ? (_jsx("div", { role: "alert", style: {
102
+ display: "flex",
103
+ flexDirection: "column",
104
+ gap: theme.space[1],
105
+ color: theme.semantic.intent.danger.solid,
106
+ fontSize: theme.typography.fontSize.sm,
107
+ }, children: formErrors.map((error) => (_jsx("span", { children: error }, error))) })) : null;
108
+ const actions = (_jsxs("div", { style: {
109
+ display: "flex",
110
+ gap: theme.space[2],
111
+ justifyContent: "flex-end",
112
+ }, children: [onCancel ? (_jsx(ThemedButton, { type: "button", variant: "secondary", size: "sm", disabled: pending, onClick: onCancel, className: "h-9 px-3 text-sm", children: cancelLabel })) : null, _jsx(ThemedButton, { type: "submit", variant: "primary", size: "sm", disabled: isDisabled, className: "h-9 px-3 text-sm", children: pending ? "Submitting..." : (submitLabel ?? fallbackLabel) })] }));
113
+ const body = (_jsxs(_Fragment, { children: [fieldsContent, formErrorContent, actions] }));
114
+ return (_jsx("form", { "data-interaction-form": true, "data-interaction-id": descriptor.interactionId, onSubmit: (event) => void submit(event), style: containerStyle, children: useAccordion ? (_jsx(AccordionPrimitive.Root, { type: "single", collapsible: true, value: accordionOpen ? "fields" : undefined, onValueChange: (value) => setAccordionOpen(value === "fields"), children: _jsxs(AccordionPrimitive.Item, { value: "fields", children: [_jsx(AccordionPrimitive.Header, { style: { margin: 0 }, children: _jsxs(AccordionPrimitive.Trigger, { style: {
115
+ alignItems: "center",
116
+ appearance: "none",
117
+ background: "transparent",
118
+ border: 0,
119
+ color: theme.semantic.text.primary,
120
+ cursor: "pointer",
121
+ display: "flex",
122
+ fontFamily: theme.typography.fontFamily.display,
123
+ fontSize: theme.typography.fontSize.md,
124
+ fontWeight: theme.typography.fontWeight.bold,
125
+ justifyContent: "space-between",
126
+ padding: 0,
127
+ textAlign: "left",
128
+ width: "100%",
129
+ }, children: [_jsx("span", { children: title ?? fallbackLabel }), _jsx("span", { "aria-hidden": true, children: accordionOpen ? "−" : "+" })] }) }), _jsx(AccordionPrimitive.Content, { children: _jsxs("div", { style: {
130
+ display: "flex",
131
+ flexDirection: "column",
132
+ gap: theme.space[2],
133
+ marginTop: theme.space[2],
134
+ }, children: [description ? (_jsx("span", { style: {
135
+ fontSize: theme.typography.fontSize.sm,
136
+ color: theme.semantic.text.muted,
137
+ }, children: description })) : null, body] }) })] }) })) : (_jsxs(_Fragment, { children: [header, body] })) }));
138
+ }
139
+ export function InteractionField({ descriptor, inputKey, handle, errors = EMPTY_FIELD_ERRORS, missing = false, disabled = false, render, }) {
140
+ const input = descriptor.inputs.find((candidate) => candidate.key === inputKey);
141
+ if (!input)
142
+ return null;
143
+ const typedInput = input;
144
+ const value = handle.values[inputKey];
145
+ const props = {
146
+ descriptor,
147
+ input: typedInput,
148
+ handle,
149
+ value,
150
+ setValue: (next) => handle.setInput(inputKey, next),
151
+ clearValue: () => handle.clearInput(inputKey),
152
+ errors,
153
+ missing,
154
+ disabled,
155
+ };
156
+ if (render)
157
+ return _jsx(_Fragment, { children: render(props) });
158
+ return _jsx(DefaultInteractionField, { ...props });
159
+ }
160
+ export function hasDefaultInteractionFormFields(descriptor) {
161
+ return defaultFormInputs(descriptor).length > 0;
162
+ }
163
+ export function defaultFormInputs(descriptor) {
164
+ return descriptor.inputs.filter((input) => {
165
+ switch (input.domain.type) {
166
+ case "choice":
167
+ case "choiceList":
168
+ case "resourceMap":
169
+ case "boundedNumber":
170
+ return true;
171
+ case "target":
172
+ return input.domain.selection?.mode === "many";
173
+ }
174
+ });
175
+ }
176
+ function DefaultInteractionField(props) {
177
+ const { input } = props;
178
+ switch (input.domain.type) {
179
+ case "choice":
180
+ if (input.domain.selection?.mode === "many") {
181
+ return (_jsx(ChoiceListField, { ...props, domain: {
182
+ type: "choiceList",
183
+ choices: input.domain.choices,
184
+ min: input.domain.selection.min ?? 0,
185
+ max: input.domain.selection.max,
186
+ selection: input.domain.selection,
187
+ } }));
188
+ }
189
+ return _jsx(ChoiceField, { ...props, domain: input.domain });
190
+ case "choiceList":
191
+ return _jsx(ChoiceListField, { ...props, domain: input.domain });
192
+ case "resourceMap":
193
+ return _jsx(ResourceMapField, { ...props, domain: input.domain });
194
+ case "boundedNumber":
195
+ return _jsx(BoundedNumberField, { ...props, domain: input.domain });
196
+ case "target":
197
+ return _jsx(TargetSummaryField, { ...props, domain: input.domain });
198
+ }
199
+ }
200
+ function FieldFrame({ label, controlId, errors, missing, children, }) {
201
+ const theme = useTheme();
202
+ const messages = errors.length > 0 ? errors : missing ? ["Required"] : [];
203
+ return (_jsxs("div", { style: {
204
+ display: "flex",
205
+ flexDirection: "column",
206
+ gap: theme.space[1],
207
+ fontSize: theme.typography.fontSize.sm,
208
+ color: theme.semantic.text.primary,
209
+ }, children: [_jsx(Label, { htmlFor: controlId, style: {
210
+ color: theme.semantic.text.primary,
211
+ fontWeight: theme.typography.fontWeight.bold,
212
+ }, children: label }), children, messages.length > 0 ? (_jsx("span", { role: "alert", style: {
213
+ display: "flex",
214
+ flexDirection: "column",
215
+ gap: 2,
216
+ color: theme.semantic.intent.danger.solid,
217
+ fontSize: theme.typography.fontSize.xs,
218
+ }, children: messages.map((message) => (_jsx("span", { children: message }, message))) })) : null] }));
219
+ }
220
+ function ChoiceOptionLabel({ choice }) {
221
+ const theme = useTheme();
222
+ return (_jsxs("span", { style: {
223
+ display: "inline-flex",
224
+ alignItems: "center",
225
+ gap: 6,
226
+ minWidth: 0,
227
+ }, children: [_jsxs("span", { style: {
228
+ display: "inline-flex",
229
+ alignItems: "center",
230
+ gap: 6,
231
+ minWidth: 0,
232
+ }, children: [choice.icon ? (_jsx("span", { "aria-hidden": true, style: { fontSize: "1.1em", lineHeight: 1 }, children: choice.icon })) : null, _jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: choice.label })] }), choice.badge ? (_jsx("span", { style: {
233
+ borderRadius: 999,
234
+ background: theme.semantic.surface.inset,
235
+ color: theme.semantic.text.muted,
236
+ fontSize: theme.typography.fontSize.xs,
237
+ fontWeight: theme.typography.fontWeight.bold,
238
+ lineHeight: 1,
239
+ padding: "3px 6px",
240
+ whiteSpace: "nowrap",
241
+ }, children: choice.badge })) : null] }));
242
+ }
243
+ function ChoiceDescription({ choice }) {
244
+ const theme = useTheme();
245
+ const message = choice?.disabledReason ?? choice?.description;
246
+ if (!message)
247
+ return null;
248
+ return (_jsx("span", { style: {
249
+ color: choice?.disabledReason
250
+ ? theme.semantic.intent.danger.solid
251
+ : theme.semantic.text.muted,
252
+ fontSize: theme.typography.fontSize.xs,
253
+ }, children: message }));
254
+ }
255
+ function ChoiceField({ input, value, setValue, errors, missing, disabled, domain, }) {
256
+ const theme = useTheme();
257
+ const themeCssVars = useThemeCssVars();
258
+ const choices = domain.choices ?? [];
259
+ const controlId = useId();
260
+ const selectedChoice = typeof value === "string"
261
+ ? choices.find((choice) => choice.value === value)
262
+ : undefined;
263
+ if (choices.length > 0 && choices.length <= 3) {
264
+ return (_jsx(FieldFrame, { label: labelForInput(input), errors: errors, missing: missing, children: _jsx("span", { style: {
265
+ display: "inline-flex",
266
+ flexWrap: "wrap",
267
+ gap: theme.space[1],
268
+ }, children: choices.map((choice) => {
269
+ const selected = value === choice.value;
270
+ return (_jsx(ThemedButton, { type: "button", variant: selected ? "primary" : "secondary", size: "sm", disabled: disabled || choice.disabled, "aria-pressed": selected, title: choice.disabledReason ?? choice.description, onClick: () => setValue(choice.value), className: "h-8 px-3 text-sm", children: _jsx(ChoiceOptionLabel, { choice: choice }) }, choice.value));
271
+ }) }) }));
272
+ }
273
+ return (_jsxs(FieldFrame, { label: labelForInput(input), controlId: controlId, errors: errors, missing: missing, children: [_jsxs(Select, { disabled: disabled, value: typeof value === "string" ? value : undefined, onValueChange: (next) => setValue(next), children: [_jsx(SelectTrigger, { id: controlId, size: "sm", className: "w-full bg-white", children: _jsx("span", { "data-slot": "select-value", children: selectedChoice ? (_jsx(ChoiceOptionLabel, { choice: selectedChoice })) : (_jsx("span", { style: { color: theme.semantic.text.muted }, children: "Choose..." })) }) }), _jsx(SelectContent, { style: {
274
+ ...themeCssVars,
275
+ fontFamily: theme.typography.fontFamily.body,
276
+ }, children: choices.map((choice) => (_jsx(SelectItem, { value: choice.value, textValue: choice.label, disabled: choice.disabled, children: _jsx(ChoiceOptionLabel, { choice: choice }) }, choice.value))) })] }), _jsx(ChoiceDescription, { choice: selectedChoice })] }));
277
+ }
278
+ function ChoiceListField({ input, value, setValue, errors, missing, disabled, domain, }) {
279
+ const theme = useTheme();
280
+ const selected = new Set(Array.isArray(value) ? value : []);
281
+ const min = domain.selection?.mode === "many"
282
+ ? (domain.selection.min ?? 0)
283
+ : domain.min;
284
+ const max = (domain.selection?.mode === "many" ? domain.selection.max : domain.max) ??
285
+ domain.choices?.length ??
286
+ Number.POSITIVE_INFINITY;
287
+ const toggle = (choice) => {
288
+ const next = new Set(selected);
289
+ if (next.has(choice))
290
+ next.delete(choice);
291
+ else if (next.size < max)
292
+ next.add(choice);
293
+ setValue([...next]);
294
+ };
295
+ const meta = min || Number.isFinite(max)
296
+ ? `Pick ${min ?? 0}${Number.isFinite(max) ? `-${max}` : "+"}`
297
+ : undefined;
298
+ return (_jsx(FieldFrame, { label: _jsxs("span", { style: {
299
+ display: "flex",
300
+ justifyContent: "space-between",
301
+ gap: theme.space[2],
302
+ }, children: [_jsx("span", { children: labelForInput(input) }), meta ? (_jsx("span", { style: { color: theme.semantic.text.muted }, children: meta })) : null] }), errors: errors, missing: missing, children: _jsx("span", { style: { display: "flex", flexWrap: "wrap", gap: theme.space[1] }, children: (domain.choices ?? []).map((choice) => {
303
+ const checked = selected.has(choice.value);
304
+ return (_jsx(ThemedButton, { type: "button", variant: checked ? "primary" : "secondary", size: "sm", disabled: disabled ||
305
+ choice.disabled ||
306
+ (!checked && selected.size >= max), "aria-pressed": checked, title: choice.disabledReason ?? choice.description, onClick: () => toggle(choice.value), className: "h-8 px-3 text-sm", children: _jsx(ChoiceOptionLabel, { choice: choice }) }, choice.value));
307
+ }) }) }));
308
+ }
309
+ function ResourceMapField({ input, value, setValue, errors, missing, disabled, domain, }) {
310
+ const theme = useTheme();
311
+ const current = isRecord(value) ? value : {};
312
+ const update = (resourceId, delta, min, max) => {
313
+ const previous = numberOrZero(current[resourceId]);
314
+ const next = Math.max(min, Math.min(max, previous + delta));
315
+ setValue({ ...current, [resourceId]: next });
316
+ };
317
+ return (_jsx(FieldFrame, { label: labelForInput(input), errors: errors, missing: missing, children: _jsx("span", { style: {
318
+ display: "grid",
319
+ gridTemplateColumns: "repeat(auto-fit, minmax(140px, 1fr))",
320
+ gap: theme.space[2],
321
+ }, children: (domain.resources ?? []).map((resource) => {
322
+ const min = resource.min ?? 0;
323
+ const max = resource.max ?? 0;
324
+ const amount = numberOrZero(current[resource.resourceId]);
325
+ return (_jsxs("span", { style: {
326
+ display: "grid",
327
+ gridTemplateColumns: "minmax(0, 1fr) auto auto auto",
328
+ alignItems: "center",
329
+ gap: theme.space[1],
330
+ padding: theme.space[2],
331
+ borderRadius: theme.radius.md,
332
+ background: theme.semantic.surface.inset,
333
+ }, children: [_jsxs("span", { style: {
334
+ minWidth: 0,
335
+ display: "inline-flex",
336
+ alignItems: "center",
337
+ gap: theme.space[1],
338
+ }, children: [resource.icon ? (_jsx("span", { "aria-hidden": true, style: { fontSize: "1.1em" }, children: resource.icon })) : null, resource.label ?? humanize(input.key)] }), _jsx(StepperButton, { label: `Decrease ${resource.label ?? resource.resourceId}`, disabled: disabled || amount <= min, onClick: () => update(resource.resourceId, -1, min, max), children: "-" }), _jsx("span", { style: {
339
+ minWidth: "2ch",
340
+ textAlign: "center",
341
+ fontVariantNumeric: "tabular-nums",
342
+ }, children: amount }), _jsx(StepperButton, { label: `Increase ${resource.label ?? resource.resourceId}`, disabled: disabled || amount >= max, onClick: () => update(resource.resourceId, 1, min, max), children: "+" })] }, resource.resourceId));
343
+ }) }) }));
344
+ }
345
+ function BoundedNumberField({ input, value, setValue, errors, missing, disabled, domain, }) {
346
+ const theme = useTheme();
347
+ const min = domain.min ?? 0;
348
+ const max = domain.max ?? Number.POSITIVE_INFINITY;
349
+ const step = domain.step ?? 1;
350
+ const current = typeof value === "number" ? value : min;
351
+ const controlId = useId();
352
+ const update = (next) => setValue(Math.max(min, Math.min(max, next)));
353
+ return (_jsx(FieldFrame, { label: labelForInput(input), controlId: controlId, errors: errors, missing: missing, children: _jsxs("span", { style: {
354
+ display: "inline-flex",
355
+ alignItems: "center",
356
+ gap: theme.space[1],
357
+ }, children: [_jsx(StepperButton, { label: `Decrease ${input.key}`, disabled: disabled || current <= min, onClick: () => update(current - step), children: "-" }), _jsx(Input, { id: controlId, type: "number", min: min, max: Number.isFinite(max) ? max : undefined, step: step, value: current, disabled: disabled, onChange: (event) => update(Number(event.target.value)), className: "h-9 w-[8ch] px-2 text-center text-sm md:text-sm" }), _jsx(StepperButton, { label: `Increase ${input.key}`, disabled: disabled || current >= max, onClick: () => update(current + step), children: "+" })] }) }));
358
+ }
359
+ function TargetSummaryField({ input, value, errors, missing, domain, }) {
360
+ return (_jsx(FieldFrame, { label: labelForInput(input), errors: errors, missing: missing, children: _jsx("span", { children: Array.isArray(value)
361
+ ? value.length > 0
362
+ ? `${value.length} selected: ${value.join(", ")}`
363
+ : `Select ${targetSelectionLabel(domain)}.`
364
+ : typeof value === "string"
365
+ ? value
366
+ : `Select a ${domain.targetKind ?? "target"} on the board.` }) }));
367
+ }
368
+ function targetSelectionLabel(domain) {
369
+ const target = domain.targetKind ?? "target";
370
+ const selection = domain.selection;
371
+ if (selection?.mode !== "many")
372
+ return `a ${target}`;
373
+ const min = selection.min ?? 0;
374
+ if (selection.max !== undefined && min === selection.max) {
375
+ return `${min} ${target}${min === 1 ? "" : "s"}`;
376
+ }
377
+ return `${min}${selection.max ? `-${selection.max}` : "+"} ${target}s`;
378
+ }
379
+ function StepperButton({ label, disabled, onClick, children, }) {
380
+ return (_jsx(ThemedButton, { type: "button", variant: "secondary", size: "sm", "aria-label": label, disabled: disabled, onClick: onClick, className: "h-8 w-8 text-sm", children: children }));
381
+ }
382
+ function labelForInput(input) {
383
+ if (input.domain.type === "choice") {
384
+ const exact = input.domain.choices?.find((choice) => choice.value === input.defaultValue);
385
+ if (exact?.label && input.key === exact.value)
386
+ return exact.label;
387
+ }
388
+ return humanize(input.key);
389
+ }
390
+ function humanize(key) {
391
+ return key
392
+ .replace(/Id$/, "")
393
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
394
+ .replace(/[-_]+/g, " ")
395
+ .replace(/\b\w/g, (letter) => letter.toUpperCase());
396
+ }
397
+ function isRecord(value) {
398
+ return typeof value === "object" && value !== null && !Array.isArray(value);
399
+ }
400
+ function numberOrZero(value) {
401
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
402
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Disclosure that hides a list of low-salience actions behind a single
3
+ * "More" toggle. Sized and styled by the active theme so it looks
4
+ * consistent with neighbouring `<DefaultInteractionButton>` rows.
5
+ *
6
+ * Why not a popover or dropdown? Two reasons:
7
+ *
8
+ * 1. **Layout safety.** The default panel surface lives directly above
9
+ * the hand strip; a floating popover would be obscured by the
10
+ * hand's `overflow-x: auto` clipping. An inline expansion stays
11
+ * inside the panel container and pushes neighbouring rows down.
12
+ * 2. **Discoverability.** Players miss menus that hide behind triple
13
+ * dots / chevrons. An expanded inline list still looks like a row
14
+ * of buttons (Jakob — same affordance as the always-visible row).
15
+ *
16
+ * The toggle reports its open state via `aria-expanded` and labels
17
+ * the disclosed region via `aria-controls` so screen readers announce
18
+ * "Expanded — More actions, region containing 3 buttons" naturally.
19
+ */
20
+ import { type CSSProperties, type ReactNode } from "react";
21
+ export interface MoreActionsProps {
22
+ /**
23
+ * Items rendered inside the disclosure when expanded. Typically
24
+ * `<DefaultInteractionButton>` instances for `salience: "tertiary"`
25
+ * descriptors, but any `ReactNode` works (custom panel cards, etc.).
26
+ */
27
+ children: ReactNode;
28
+ /**
29
+ * Toggle label. Defaults to `"More"`. The descriptor count gets
30
+ * appended automatically when {@link count} is supplied.
31
+ */
32
+ label?: string;
33
+ /**
34
+ * Number of hidden items, used to render the trailing "(N)" badge.
35
+ * Omit when the count is irrelevant or already implied (e.g. when
36
+ * the panel only has a fixed set of disclosed items).
37
+ */
38
+ count?: number;
39
+ /**
40
+ * Initial open state. Defaults to `false` — the disclosure is the
41
+ * point. Authors who want it open by default for a specific seat
42
+ * (e.g. tutorial mode) should pass `true`.
43
+ */
44
+ defaultOpen?: boolean;
45
+ /** Additional inline style merged after the default container. */
46
+ style?: CSSProperties;
47
+ }
48
+ export declare function MoreActions({ children, label, count, defaultOpen, style, }: MoreActionsProps): import("react/jsx-runtime").JSX.Element;
49
+ //# sourceMappingURL=MoreActions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MoreActions.d.ts","sourceRoot":"","sources":["../../src/components/MoreActions.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAmB,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAK5E,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kEAAkE;IAClE,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,KAAc,EACd,KAAK,EACL,WAAmB,EACnB,KAAK,GACN,EAAE,gBAAgB,2CAmFlB"}