@ankhorage/zora 21.0.23 → 21.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (554) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +6 -2
  3. package/dist/features/authoring/allowedChildren.d.ts +5 -2
  4. package/dist/features/authoring/allowedChildren.d.ts.map +1 -1
  5. package/dist/features/authoring/allowedChildren.js +13 -2
  6. package/dist/features/authoring/allowedChildren.js.map +1 -1
  7. package/dist/features/authoring/componentMeta.d.ts.map +1 -1
  8. package/dist/features/authoring/componentMeta.js +21 -0
  9. package/dist/features/authoring/componentMeta.js.map +1 -1
  10. package/dist/features/authoring/constants.d.ts +3 -0
  11. package/dist/features/authoring/constants.d.ts.map +1 -1
  12. package/dist/features/authoring/constants.js +3 -0
  13. package/dist/features/authoring/constants.js.map +1 -1
  14. package/dist/features/card/cardMeta.d.ts +1 -1
  15. package/dist/features/card/cardMeta.d.ts.map +1 -1
  16. package/dist/features/card/cardMeta.js +7 -2
  17. package/dist/features/card/cardMeta.js.map +1 -1
  18. package/dist/features/chess/adapters/inbound/ChessBoard.d.ts +5 -0
  19. package/dist/features/chess/adapters/inbound/ChessBoard.d.ts.map +1 -0
  20. package/dist/features/chess/adapters/inbound/ChessBoard.js +119 -0
  21. package/dist/features/chess/adapters/inbound/ChessBoard.js.map +1 -0
  22. package/dist/features/chess/adapters/inbound/OpeningBook.d.ts +5 -0
  23. package/dist/features/chess/adapters/inbound/OpeningBook.d.ts.map +1 -0
  24. package/dist/features/chess/adapters/inbound/OpeningBook.js +94 -0
  25. package/dist/features/chess/adapters/inbound/OpeningBook.js.map +1 -0
  26. package/dist/features/chess/meta.d.ts +219 -0
  27. package/dist/features/chess/meta.d.ts.map +1 -0
  28. package/dist/features/chess/meta.js +165 -0
  29. package/dist/features/chess/meta.js.map +1 -0
  30. package/dist/features/chess/public.d.ts +12 -0
  31. package/dist/features/chess/public.d.ts.map +1 -0
  32. package/dist/features/chess/public.js +10 -0
  33. package/dist/features/chess/public.js.map +1 -0
  34. package/dist/features/chess/utils/chessSquares.d.ts +4 -0
  35. package/dist/features/chess/utils/chessSquares.d.ts.map +1 -0
  36. package/dist/features/chess/utils/chessSquares.js +3 -0
  37. package/dist/features/chess/utils/chessSquares.js.map +1 -0
  38. package/dist/features/chess/utils/createBoardSquares.d.ts +4 -0
  39. package/dist/features/chess/utils/createBoardSquares.d.ts.map +1 -0
  40. package/dist/features/chess/utils/createBoardSquares.js +9 -0
  41. package/dist/features/chess/utils/createBoardSquares.js.map +1 -0
  42. package/dist/features/chess/utils/createChessBoardColorScheme.d.ts +35 -0
  43. package/dist/features/chess/utils/createChessBoardColorScheme.d.ts.map +1 -0
  44. package/dist/features/chess/utils/createChessBoardColorScheme.js +26 -0
  45. package/dist/features/chess/utils/createChessBoardColorScheme.js.map +1 -0
  46. package/dist/features/chess/utils/createOpeningBookColorScheme.d.ts +11 -0
  47. package/dist/features/chess/utils/createOpeningBookColorScheme.d.ts.map +1 -0
  48. package/dist/features/chess/utils/createOpeningBookColorScheme.js +21 -0
  49. package/dist/features/chess/utils/createOpeningBookColorScheme.js.map +1 -0
  50. package/dist/features/chess/utils/getSquareFile.d.ts +4 -0
  51. package/dist/features/chess/utils/getSquareFile.d.ts.map +1 -0
  52. package/dist/features/chess/utils/getSquareFile.js +5 -0
  53. package/dist/features/chess/utils/getSquareFile.js.map +1 -0
  54. package/dist/features/chess/utils/getSquareRank.d.ts +4 -0
  55. package/dist/features/chess/utils/getSquareRank.d.ts.map +1 -0
  56. package/dist/features/chess/utils/getSquareRank.js +5 -0
  57. package/dist/features/chess/utils/getSquareRank.js.map +1 -0
  58. package/dist/features/chess/utils/isLightSquare.d.ts +4 -0
  59. package/dist/features/chess/utils/isLightSquare.d.ts.map +1 -0
  60. package/dist/features/chess/utils/isLightSquare.js +6 -0
  61. package/dist/features/chess/utils/isLightSquare.js.map +1 -0
  62. package/dist/features/game/adapters/inbound/Game.d.ts +5 -0
  63. package/dist/features/game/adapters/inbound/Game.d.ts.map +1 -0
  64. package/dist/features/game/adapters/inbound/Game.js +24 -0
  65. package/dist/features/game/adapters/inbound/Game.js.map +1 -0
  66. package/dist/features/game/adapters/inbound/GameEntity.d.ts +5 -0
  67. package/dist/features/game/adapters/inbound/GameEntity.d.ts.map +1 -0
  68. package/dist/features/game/adapters/inbound/GameEntity.js +29 -0
  69. package/dist/features/game/adapters/inbound/GameEntity.js.map +1 -0
  70. package/dist/features/game/adapters/inbound/GameField.d.ts +4 -0
  71. package/dist/features/game/adapters/inbound/GameField.d.ts.map +1 -0
  72. package/dist/features/game/adapters/inbound/GameField.js +32 -0
  73. package/dist/features/game/adapters/inbound/GameField.js.map +1 -0
  74. package/dist/features/game/adapters/inbound/GameInputZone.d.ts +4 -0
  75. package/dist/features/game/adapters/inbound/GameInputZone.d.ts.map +1 -0
  76. package/dist/features/game/adapters/inbound/GameInputZone.js +50 -0
  77. package/dist/features/game/adapters/inbound/GameInputZone.js.map +1 -0
  78. package/dist/features/game/adapters/inbound/GameMeasurementProbe.d.ts +4 -0
  79. package/dist/features/game/adapters/inbound/GameMeasurementProbe.d.ts.map +1 -0
  80. package/dist/features/game/adapters/inbound/GameMeasurementProbe.js +54 -0
  81. package/dist/features/game/adapters/inbound/GameMeasurementProbe.js.map +1 -0
  82. package/dist/features/game/adapters/inbound/GameOverlay.d.ts +4 -0
  83. package/dist/features/game/adapters/inbound/GameOverlay.d.ts.map +1 -0
  84. package/dist/features/game/adapters/inbound/GameOverlay.js +39 -0
  85. package/dist/features/game/adapters/inbound/GameOverlay.js.map +1 -0
  86. package/dist/features/game/adapters/inbound/createGameKeyboardEvent.d.ts +16 -0
  87. package/dist/features/game/adapters/inbound/createGameKeyboardEvent.d.ts.map +1 -0
  88. package/dist/features/game/adapters/inbound/createGameKeyboardEvent.js +16 -0
  89. package/dist/features/game/adapters/inbound/createGameKeyboardEvent.js.map +1 -0
  90. package/dist/features/game/adapters/inbound/createGameMeasurementEvent.d.ts +14 -0
  91. package/dist/features/game/adapters/inbound/createGameMeasurementEvent.d.ts.map +1 -0
  92. package/dist/features/game/adapters/inbound/createGameMeasurementEvent.js +25 -0
  93. package/dist/features/game/adapters/inbound/createGameMeasurementEvent.js.map +1 -0
  94. package/dist/features/game/adapters/inbound/createGamePointerEvent.d.ts +17 -0
  95. package/dist/features/game/adapters/inbound/createGamePointerEvent.d.ts.map +1 -0
  96. package/dist/features/game/adapters/inbound/createGamePointerEvent.js +20 -0
  97. package/dist/features/game/adapters/inbound/createGamePointerEvent.js.map +1 -0
  98. package/dist/features/game/adapters/inbound/measureGameEntity.d.ts +5 -0
  99. package/dist/features/game/adapters/inbound/measureGameEntity.d.ts.map +1 -0
  100. package/dist/features/game/adapters/inbound/measureGameEntity.js +22 -0
  101. package/dist/features/game/adapters/inbound/measureGameEntity.js.map +1 -0
  102. package/dist/features/game/adapters/inbound/useGameInputZoneResponder.d.ts +15 -0
  103. package/dist/features/game/adapters/inbound/useGameInputZoneResponder.d.ts.map +1 -0
  104. package/dist/features/game/adapters/inbound/useGameInputZoneResponder.js +67 -0
  105. package/dist/features/game/adapters/inbound/useGameInputZoneResponder.js.map +1 -0
  106. package/dist/features/game/composition/GameRuntimeContext.d.ts +5 -0
  107. package/dist/features/game/composition/GameRuntimeContext.d.ts.map +1 -0
  108. package/dist/features/game/composition/GameRuntimeContext.js +4 -0
  109. package/dist/features/game/composition/GameRuntimeContext.js.map +1 -0
  110. package/dist/features/game/composition/createGameBindingContext.d.ts +4 -0
  111. package/dist/features/game/composition/createGameBindingContext.d.ts.map +1 -0
  112. package/dist/features/game/composition/createGameBindingContext.js +10 -0
  113. package/dist/features/game/composition/createGameBindingContext.js.map +1 -0
  114. package/dist/features/game/composition/createGameMeasurementRegistry.d.ts +4 -0
  115. package/dist/features/game/composition/createGameMeasurementRegistry.d.ts.map +1 -0
  116. package/dist/features/game/composition/createGameMeasurementRegistry.js +15 -0
  117. package/dist/features/game/composition/createGameMeasurementRegistry.js.map +1 -0
  118. package/dist/features/game/composition/useGameRuntime.d.ts +5 -0
  119. package/dist/features/game/composition/useGameRuntime.d.ts.map +1 -0
  120. package/dist/features/game/composition/useGameRuntime.js +117 -0
  121. package/dist/features/game/composition/useGameRuntime.js.map +1 -0
  122. package/dist/features/game/composition/useGameScheduledEffects.d.ts +17 -0
  123. package/dist/features/game/composition/useGameScheduledEffects.d.ts.map +1 -0
  124. package/dist/features/game/composition/useGameScheduledEffects.js +40 -0
  125. package/dist/features/game/composition/useGameScheduledEffects.js.map +1 -0
  126. package/dist/features/game/meta/gameEntityMeta.d.ts +403 -0
  127. package/dist/features/game/meta/gameEntityMeta.d.ts.map +1 -0
  128. package/dist/features/game/meta/gameEntityMeta.js +224 -0
  129. package/dist/features/game/meta/gameEntityMeta.js.map +1 -0
  130. package/dist/features/game/meta/gameFieldMeta.d.ts +61 -0
  131. package/dist/features/game/meta/gameFieldMeta.d.ts.map +1 -0
  132. package/dist/features/game/meta/gameFieldMeta.js +48 -0
  133. package/dist/features/game/meta/gameFieldMeta.js.map +1 -0
  134. package/dist/features/game/meta/gameInputZoneMeta.d.ts +163 -0
  135. package/dist/features/game/meta/gameInputZoneMeta.d.ts.map +1 -0
  136. package/dist/features/game/meta/gameInputZoneMeta.js +138 -0
  137. package/dist/features/game/meta/gameInputZoneMeta.js.map +1 -0
  138. package/dist/features/game/meta/gameMeasurementProbeMeta.d.ts +112 -0
  139. package/dist/features/game/meta/gameMeasurementProbeMeta.d.ts.map +1 -0
  140. package/dist/features/game/meta/gameMeasurementProbeMeta.js +70 -0
  141. package/dist/features/game/meta/gameMeasurementProbeMeta.js.map +1 -0
  142. package/dist/features/game/meta/gameMeta.d.ts +130 -0
  143. package/dist/features/game/meta/gameMeta.d.ts.map +1 -0
  144. package/dist/features/game/meta/gameMeta.js +113 -0
  145. package/dist/features/game/meta/gameMeta.js.map +1 -0
  146. package/dist/features/game/meta/gameOverlayMeta.d.ts +55 -0
  147. package/dist/features/game/meta/gameOverlayMeta.d.ts.map +1 -0
  148. package/dist/features/game/meta/gameOverlayMeta.js +65 -0
  149. package/dist/features/game/meta/gameOverlayMeta.js.map +1 -0
  150. package/dist/features/game/public.d.ts +8 -0
  151. package/dist/features/game/public.d.ts.map +1 -0
  152. package/dist/features/game/public.js +7 -0
  153. package/dist/features/game/public.js.map +1 -0
  154. package/dist/features/game/utils/clampGamePercentage.d.ts +3 -0
  155. package/dist/features/game/utils/clampGamePercentage.d.ts.map +1 -0
  156. package/dist/features/game/utils/clampGamePercentage.js +5 -0
  157. package/dist/features/game/utils/clampGamePercentage.js.map +1 -0
  158. package/dist/features/game/utils/resolveGameEntityMotionPlan.d.ts +15 -0
  159. package/dist/features/game/utils/resolveGameEntityMotionPlan.d.ts.map +1 -0
  160. package/dist/features/game/utils/resolveGameEntityMotionPlan.js +31 -0
  161. package/dist/features/game/utils/resolveGameEntityMotionPlan.js.map +1 -0
  162. package/dist/features/game/utils/toGamePercentage.d.ts +3 -0
  163. package/dist/features/game/utils/toGamePercentage.d.ts.map +1 -0
  164. package/dist/features/game/utils/toGamePercentage.js +6 -0
  165. package/dist/features/game/utils/toGamePercentage.js.map +1 -0
  166. package/dist/features/game/utils/useAnimatedGameEntityValue.d.ts +5 -0
  167. package/dist/features/game/utils/useAnimatedGameEntityValue.d.ts.map +1 -0
  168. package/dist/features/game/utils/useAnimatedGameEntityValue.js +33 -0
  169. package/dist/features/game/utils/useAnimatedGameEntityValue.js.map +1 -0
  170. package/dist/features/game/utils/useGameEntityAnimatedStyle.d.ts +16 -0
  171. package/dist/features/game/utils/useGameEntityAnimatedStyle.d.ts.map +1 -0
  172. package/dist/features/game/utils/useGameEntityAnimatedStyle.js +52 -0
  173. package/dist/features/game/utils/useGameEntityAnimatedStyle.js.map +1 -0
  174. package/dist/features/game/utils/useGameEntityMeasurement.d.ts +5 -0
  175. package/dist/features/game/utils/useGameEntityMeasurement.d.ts.map +1 -0
  176. package/dist/features/game/utils/useGameEntityMeasurement.js +14 -0
  177. package/dist/features/game/utils/useGameEntityMeasurement.js.map +1 -0
  178. package/dist/features/game/utils/useGameEntityMotionProgress.d.ts +5 -0
  179. package/dist/features/game/utils/useGameEntityMotionProgress.d.ts.map +1 -0
  180. package/dist/features/game/utils/useGameEntityMotionProgress.js +87 -0
  181. package/dist/features/game/utils/useGameEntityMotionProgress.js.map +1 -0
  182. package/dist/features/game/utils/useGameReducedMotion.d.ts +3 -0
  183. package/dist/features/game/utils/useGameReducedMotion.d.ts.map +1 -0
  184. package/dist/features/game/utils/useGameReducedMotion.js +13 -0
  185. package/dist/features/game/utils/useGameReducedMotion.js.map +1 -0
  186. package/dist/features/layout/gridMeta.d.ts +1 -1
  187. package/dist/features/layout/gridMeta.d.ts.map +1 -1
  188. package/dist/features/layout/gridMeta.js +7 -2
  189. package/dist/features/layout/gridMeta.js.map +1 -1
  190. package/dist/features/layout/screenMeta.d.ts +1 -1
  191. package/dist/features/layout/viewMeta.d.ts +1 -1
  192. package/dist/features/layout/viewMeta.d.ts.map +1 -1
  193. package/dist/features/layout/viewMeta.js +6 -2
  194. package/dist/features/layout/viewMeta.js.map +1 -1
  195. package/dist/features/registry/ZORA_COMPONENT_REGISTRY.d.ts.map +1 -1
  196. package/dist/features/registry/ZORA_COMPONENT_REGISTRY.js +16 -0
  197. package/dist/features/registry/ZORA_COMPONENT_REGISTRY.js.map +1 -1
  198. package/dist/features/section/screenSectionMeta.d.ts +1 -1
  199. package/dist/features/tabletop/adapters/inbound/CardBack.d.ts +5 -0
  200. package/dist/features/tabletop/adapters/inbound/CardBack.d.ts.map +1 -0
  201. package/dist/features/tabletop/adapters/inbound/CardBack.js +47 -0
  202. package/dist/features/tabletop/adapters/inbound/CardBack.js.map +1 -0
  203. package/dist/features/tabletop/adapters/inbound/CardHand.d.ts +5 -0
  204. package/dist/features/tabletop/adapters/inbound/CardHand.d.ts.map +1 -0
  205. package/dist/features/tabletop/adapters/inbound/CardHand.js +28 -0
  206. package/dist/features/tabletop/adapters/inbound/CardHand.js.map +1 -0
  207. package/dist/features/tabletop/adapters/inbound/PlayingCard.d.ts +5 -0
  208. package/dist/features/tabletop/adapters/inbound/PlayingCard.d.ts.map +1 -0
  209. package/dist/features/tabletop/adapters/inbound/PlayingCard.js +64 -0
  210. package/dist/features/tabletop/adapters/inbound/PlayingCard.js.map +1 -0
  211. package/dist/features/tabletop/adapters/inbound/PokerTrainingTable.d.ts +5 -0
  212. package/dist/features/tabletop/adapters/inbound/PokerTrainingTable.d.ts.map +1 -0
  213. package/dist/features/tabletop/adapters/inbound/PokerTrainingTable.js +12 -0
  214. package/dist/features/tabletop/adapters/inbound/PokerTrainingTable.js.map +1 -0
  215. package/dist/features/tabletop/adapters/inbound/TabletopTable.d.ts +5 -0
  216. package/dist/features/tabletop/adapters/inbound/TabletopTable.d.ts.map +1 -0
  217. package/dist/features/tabletop/adapters/inbound/TabletopTable.js +206 -0
  218. package/dist/features/tabletop/adapters/inbound/TabletopTable.js.map +1 -0
  219. package/dist/features/tabletop/meta.d.ts +353 -0
  220. package/dist/features/tabletop/meta.d.ts.map +1 -0
  221. package/dist/features/tabletop/meta.js +252 -0
  222. package/dist/features/tabletop/meta.js.map +1 -0
  223. package/dist/features/tabletop/public.d.ts +10 -0
  224. package/dist/features/tabletop/public.d.ts.map +1 -0
  225. package/dist/features/tabletop/public.js +9 -0
  226. package/dist/features/tabletop/public.js.map +1 -0
  227. package/dist/features/tabletop/utils/createPokerTrainingTableState.d.ts +13 -0
  228. package/dist/features/tabletop/utils/createPokerTrainingTableState.d.ts.map +1 -0
  229. package/dist/features/tabletop/utils/createPokerTrainingTableState.js +112 -0
  230. package/dist/features/tabletop/utils/createPokerTrainingTableState.js.map +1 -0
  231. package/dist/features/tabletop/utils/createTabletopColorScheme.d.ts +36 -0
  232. package/dist/features/tabletop/utils/createTabletopColorScheme.d.ts.map +1 -0
  233. package/dist/features/tabletop/utils/createTabletopColorScheme.js +144 -0
  234. package/dist/features/tabletop/utils/createTabletopColorScheme.js.map +1 -0
  235. package/dist/features/tabletop/utils/createTabletopGameSeats.d.ts +13 -0
  236. package/dist/features/tabletop/utils/createTabletopGameSeats.d.ts.map +1 -0
  237. package/dist/features/tabletop/utils/createTabletopGameSeats.js +22 -0
  238. package/dist/features/tabletop/utils/createTabletopGameSeats.js.map +1 -0
  239. package/dist/features/tabletop/utils/getPlayingCardLabel.d.ts +4 -0
  240. package/dist/features/tabletop/utils/getPlayingCardLabel.d.ts.map +1 -0
  241. package/dist/features/tabletop/utils/getPlayingCardLabel.js +6 -0
  242. package/dist/features/tabletop/utils/getPlayingCardLabel.js.map +1 -0
  243. package/dist/features/tabletop/utils/getTabletopCardDimensions.d.ts +12 -0
  244. package/dist/features/tabletop/utils/getTabletopCardDimensions.d.ts.map +1 -0
  245. package/dist/features/tabletop/utils/getTabletopCardDimensions.js +35 -0
  246. package/dist/features/tabletop/utils/getTabletopCardDimensions.js.map +1 -0
  247. package/dist/features/tabletop/utils/getTabletopSeatPosition.d.ts +9 -0
  248. package/dist/features/tabletop/utils/getTabletopSeatPosition.d.ts.map +1 -0
  249. package/dist/features/tabletop/utils/getTabletopSeatPosition.js +88 -0
  250. package/dist/features/tabletop/utils/getTabletopSeatPosition.js.map +1 -0
  251. package/dist/index.d.ts +8 -0
  252. package/dist/index.d.ts.map +1 -1
  253. package/dist/index.js +4 -0
  254. package/dist/index.js.map +1 -1
  255. package/dist/types/chess.d.ts +83 -0
  256. package/dist/types/chess.d.ts.map +1 -0
  257. package/dist/types/chess.js +2 -0
  258. package/dist/types/chess.js.map +1 -0
  259. package/dist/types/gamePresentation.d.ts +94 -0
  260. package/dist/types/gamePresentation.d.ts.map +1 -0
  261. package/dist/types/gamePresentation.js +2 -0
  262. package/dist/types/gamePresentation.js.map +1 -0
  263. package/dist/types/gameRuntime.d.ts +29 -0
  264. package/dist/types/gameRuntime.d.ts.map +1 -0
  265. package/dist/types/gameRuntime.js +2 -0
  266. package/dist/types/gameRuntime.js.map +1 -0
  267. package/dist/types/tabletop.d.ts +129 -0
  268. package/dist/types/tabletop.d.ts.map +1 -0
  269. package/dist/types/tabletop.js +2 -0
  270. package/dist/types/tabletop.js.map +1 -0
  271. package/package.json +3 -1
  272. package/src/features/authoring/allowedChildren.ts +15 -2
  273. package/src/features/authoring/componentMeta.test.ts +93 -0
  274. package/src/features/authoring/componentMeta.ts +27 -0
  275. package/src/features/authoring/constants.ts +3 -0
  276. package/src/features/card/cardMeta.ts +12 -2
  277. package/src/features/chess/adapters/inbound/ChessBoard.tsx +169 -0
  278. package/src/features/chess/adapters/inbound/OpeningBook.tsx +131 -0
  279. package/src/features/chess/meta.ts +168 -0
  280. package/src/features/chess/public.test.tsx +165 -0
  281. package/src/features/chess/public.ts +27 -0
  282. package/src/features/chess/utils/chessSquares.ts +6 -0
  283. package/src/features/chess/utils/createBoardSquares.ts +13 -0
  284. package/src/features/chess/utils/createChessBoardColorScheme.ts +55 -0
  285. package/src/features/chess/utils/createOpeningBookColorScheme.ts +26 -0
  286. package/src/features/chess/utils/getSquareFile.ts +6 -0
  287. package/src/features/chess/utils/getSquareRank.ts +6 -0
  288. package/src/features/chess/utils/isLightSquare.ts +8 -0
  289. package/src/features/chessTabletopOwnership.test.ts +71 -0
  290. package/src/features/game/adapters/inbound/Game.tsx +43 -0
  291. package/src/features/game/adapters/inbound/GameEntity.tsx +44 -0
  292. package/src/features/game/adapters/inbound/GameField.tsx +52 -0
  293. package/src/features/game/adapters/inbound/GameInputZone.tsx +99 -0
  294. package/src/features/game/adapters/inbound/GameMeasurementProbe.tsx +83 -0
  295. package/src/features/game/adapters/inbound/GameOverlay.tsx +58 -0
  296. package/src/features/game/adapters/inbound/createGameKeyboardEvent.test.ts +51 -0
  297. package/src/features/game/adapters/inbound/createGameKeyboardEvent.ts +33 -0
  298. package/src/features/game/adapters/inbound/createGameMeasurementEvent.test.ts +56 -0
  299. package/src/features/game/adapters/inbound/createGameMeasurementEvent.ts +38 -0
  300. package/src/features/game/adapters/inbound/createGamePointerEvent.test.ts +56 -0
  301. package/src/features/game/adapters/inbound/createGamePointerEvent.ts +39 -0
  302. package/src/features/game/adapters/inbound/measureGameEntity.ts +28 -0
  303. package/src/features/game/adapters/inbound/useGameInputZoneResponder.ts +85 -0
  304. package/src/features/game/composition/GameRuntimeContext.ts +6 -0
  305. package/src/features/game/composition/createGameBindingContext.test.ts +66 -0
  306. package/src/features/game/composition/createGameBindingContext.ts +11 -0
  307. package/src/features/game/composition/createGameMeasurementRegistry.test.ts +35 -0
  308. package/src/features/game/composition/createGameMeasurementRegistry.ts +16 -0
  309. package/src/features/game/composition/useGameRuntime.test.tsx +173 -0
  310. package/src/features/game/composition/useGameRuntime.ts +200 -0
  311. package/src/features/game/composition/useGameScheduledEffects.ts +85 -0
  312. package/src/features/game/meta/gameEntityMeta.ts +226 -0
  313. package/src/features/game/meta/gameFieldMeta.ts +49 -0
  314. package/src/features/game/meta/gameInputZoneMeta.ts +140 -0
  315. package/src/features/game/meta/gameMeasurementProbeMeta.ts +72 -0
  316. package/src/features/game/meta/gameMeta.ts +115 -0
  317. package/src/features/game/meta/gameOverlayMeta.ts +66 -0
  318. package/src/features/game/public.test.tsx +64 -0
  319. package/src/features/game/public.ts +19 -0
  320. package/src/features/game/utils/clampGamePercentage.ts +4 -0
  321. package/src/features/game/utils/resolveGameEntityMotionPlan.test.ts +63 -0
  322. package/src/features/game/utils/resolveGameEntityMotionPlan.ts +53 -0
  323. package/src/features/game/utils/toGamePercentage.ts +6 -0
  324. package/src/features/game/utils/useAnimatedGameEntityValue.ts +41 -0
  325. package/src/features/game/utils/useGameEntityAnimatedStyle.ts +87 -0
  326. package/src/features/game/utils/useGameEntityMeasurement.ts +19 -0
  327. package/src/features/game/utils/useGameEntityMotionProgress.ts +114 -0
  328. package/src/features/game/utils/useGameReducedMotion.ts +15 -0
  329. package/src/features/layout/gridMeta.ts +12 -2
  330. package/src/features/layout/viewMeta.ts +10 -2
  331. package/src/features/registry/ZORA_COMPONENT_REGISTRY.ts +29 -0
  332. package/src/features/tabletop/adapters/inbound/CardBack.tsx +70 -0
  333. package/src/features/tabletop/adapters/inbound/CardHand.tsx +61 -0
  334. package/src/features/tabletop/adapters/inbound/PlayingCard.tsx +95 -0
  335. package/src/features/tabletop/adapters/inbound/PokerTrainingTable.tsx +34 -0
  336. package/src/features/tabletop/adapters/inbound/TabletopTable.tsx +264 -0
  337. package/src/features/tabletop/meta.ts +254 -0
  338. package/src/features/tabletop/public.test.tsx +127 -0
  339. package/src/features/tabletop/public.ts +32 -0
  340. package/src/features/tabletop/utils/createPokerTrainingTableState.ts +152 -0
  341. package/src/features/tabletop/utils/createTabletopColorScheme.ts +232 -0
  342. package/src/features/tabletop/utils/createTabletopGameSeats.ts +31 -0
  343. package/src/features/tabletop/utils/getPlayingCardLabel.ts +8 -0
  344. package/src/features/tabletop/utils/getTabletopCardDimensions.ts +45 -0
  345. package/src/features/tabletop/utils/getTabletopSeatPosition.ts +100 -0
  346. package/src/index.ts +83 -0
  347. package/src/types/chess.ts +95 -0
  348. package/src/types/gamePresentation.ts +103 -0
  349. package/src/types/gameRuntime.ts +34 -0
  350. package/src/types/tabletop.ts +131 -0
  351. package/web-dist/chunks/{Accordion-cscmtcn8.js → Accordion-0txegc16.js} +1 -1
  352. package/web-dist/chunks/{Accordion-06588rzn.js → Accordion-10xw59gm.js} +1 -1
  353. package/web-dist/chunks/{Accordion-8kgtg62g.js → Accordion-2zh15wt9.js} +6 -6
  354. package/web-dist/chunks/{Accordion-pkqj4g3r.js → Accordion-481bknsd.js} +5 -5
  355. package/web-dist/chunks/{Accordion-grfbz6f2.js → Accordion-4fkjn6r5.js} +1 -1
  356. package/web-dist/chunks/{Accordion-ftjkdjqs.js → Accordion-4gx45mn0.js} +3 -3
  357. package/web-dist/chunks/{Accordion-fjnck2tg.js → Accordion-4s69xvqy.js} +6 -6
  358. package/web-dist/chunks/{Accordion-jh7nxehr.js → Accordion-50jz5nhg.js} +1 -1
  359. package/web-dist/chunks/{Accordion-t6sdgmbz.js → Accordion-52xke54s.js} +1 -1
  360. package/web-dist/chunks/{Accordion-far6szrp.js → Accordion-6npzmbgk.js} +5 -5
  361. package/web-dist/chunks/{Accordion-q7c1ryf2.js → Accordion-6z4npcgf.js} +4 -4
  362. package/web-dist/chunks/{Accordion-gbba10rg.js → Accordion-8gw5tkfw.js} +6 -6
  363. package/web-dist/chunks/{Accordion-fmxygyb6.js → Accordion-8qteyww0.js} +4 -4
  364. package/web-dist/chunks/{Accordion-1pp37dtg.js → Accordion-9h5dx3ck.js} +4 -4
  365. package/web-dist/chunks/{Accordion-paha5aje.js → Accordion-9mmqf3wr.js} +2 -2
  366. package/web-dist/chunks/{Accordion-f5swy5bs.js → Accordion-b21zrnzj.js} +1 -1
  367. package/web-dist/chunks/{Accordion-ars389m1.js → Accordion-b8qd23hr.js} +3 -3
  368. package/web-dist/chunks/{Accordion-hxfa71g9.js → Accordion-c79y8g44.js} +7 -7
  369. package/web-dist/chunks/Accordion-ca2csh5r.js +321 -0
  370. package/web-dist/chunks/{Accordion-49gf1zb8.js → Accordion-cjht9dyv.js} +1 -1
  371. package/web-dist/chunks/{Accordion-sz21xsf4.js → Accordion-cq6hn45r.js} +1 -1
  372. package/web-dist/chunks/{Accordion-33rd76r7.js → Accordion-d90g9wcb.js} +8 -8
  373. package/web-dist/chunks/{Accordion-crx58d5n.js → Accordion-f5jb299b.js} +2 -2
  374. package/web-dist/chunks/{Accordion-h95wvyn5.js → Accordion-fe6vmbpf.js} +2 -2
  375. package/web-dist/chunks/{Accordion-jzbq36ec.js → Accordion-fqm027n3.js} +8 -8
  376. package/web-dist/chunks/{Accordion-0jkm3y3w.js → Accordion-gpccarct.js} +1 -1
  377. package/web-dist/chunks/{Accordion-v6ykq9hv.js → Accordion-h95h3xdb.js} +10 -10
  378. package/web-dist/chunks/{Accordion-t3p4ykg7.js → Accordion-j8ab9k8k.js} +8 -8
  379. package/web-dist/chunks/{Accordion-qpwhmqzd.js → Accordion-k5z591wx.js} +13 -13
  380. package/web-dist/chunks/{Accordion-rrpej6sv.js → Accordion-kdncjvc7.js} +7 -7
  381. package/web-dist/chunks/{Accordion-f05a7r28.js → Accordion-ks4a1c6w.js} +5 -5
  382. package/web-dist/chunks/{Accordion-x0j8b2by.js → Accordion-ma1sfe5z.js} +5 -5
  383. package/web-dist/chunks/{Accordion-2dws3778.js → Accordion-mhtyce1k.js} +4 -4
  384. package/web-dist/chunks/{Accordion-1vewf8aa.js → Accordion-n7gtb5ec.js} +2 -2
  385. package/web-dist/chunks/{Accordion-0psdn97s.js → Accordion-p42mm8rr.js} +1 -1
  386. package/web-dist/chunks/{Accordion-3404tth9.js → Accordion-panw5f0q.js} +7 -7
  387. package/web-dist/chunks/{Accordion-4a6wj3ez.js → Accordion-pxq8gfgg.js} +9 -9
  388. package/web-dist/chunks/{Accordion-xshn7k8f.js → Accordion-qwbshc4s.js} +4 -4
  389. package/web-dist/chunks/{Accordion-395r3wra.js → Accordion-r51wsmvy.js} +2 -2
  390. package/web-dist/chunks/Accordion-rt13cqr7.js +830 -0
  391. package/web-dist/chunks/{Accordion-hz4xaqjf.js → Accordion-s1f9hb5a.js} +9 -9
  392. package/web-dist/chunks/{Accordion-7ja4mtbz.js → Accordion-sv87mbqa.js} +1 -1
  393. package/web-dist/chunks/{Accordion-r4c9k9y7.js → Accordion-t4k9egq6.js} +2 -2
  394. package/web-dist/chunks/{Accordion-96cqeekv.js → Accordion-t64m1kca.js} +5 -5
  395. package/web-dist/chunks/Accordion-wg31jkvp.js +1559 -0
  396. package/web-dist/chunks/{Accordion-ch67q4t0.js → Accordion-y9zr4x2x.js} +4 -4
  397. package/web-dist/chunks/{Accordion-31aeqxak.js → Accordion-ye3k55r7.js} +3 -3
  398. package/web-dist/chunks/{Accordion-s42wwh6m.js → Accordion-z29agann.js} +6 -6
  399. package/web-dist/chunks/{Accordion-f1h2f05v.js → Accordion-ze26effy.js} +5 -5
  400. package/web-dist/chunks/{Accordion-tx78txec.js → Accordion-zqzcagxz.js} +5 -5
  401. package/web-dist/components/accordion/Accordion.js +12 -12
  402. package/web-dist/components/accordion-item/AccordionItem.js +12 -12
  403. package/web-dist/components/activity-indicator/ActivityIndicator.js +3 -3
  404. package/web-dist/components/app-bar/AppBar.js +19 -19
  405. package/web-dist/components/app-shell/AppShell.js +6 -6
  406. package/web-dist/components/avatar/Avatar.js +12 -12
  407. package/web-dist/components/avatar-group/AvatarGroup.js +12 -12
  408. package/web-dist/components/badge/Badge.js +7 -7
  409. package/web-dist/components/barcode-scanner-view/BarcodeScannerView.js +20 -20
  410. package/web-dist/components/bottom-sheet/BottomSheet.js +8 -8
  411. package/web-dist/components/bottom-sheet-flat-list/BottomSheetFlatList.js +8 -8
  412. package/web-dist/components/bottom-sheet-scroll-view/BottomSheetScrollView.js +8 -8
  413. package/web-dist/components/bottom-sheet-section-list/BottomSheetSectionList.js +8 -8
  414. package/web-dist/components/bottom-sheet-view/BottomSheetView.js +8 -8
  415. package/web-dist/components/bottom-sheet-virtualized-list/BottomSheetVirtualizedList.js +8 -8
  416. package/web-dist/components/breadcrumbs/Breadcrumbs.js +15 -15
  417. package/web-dist/components/button/Button.js +12 -12
  418. package/web-dist/components/button-group/ButtonGroup.js +12 -12
  419. package/web-dist/components/camera-permission-view/CameraPermissionView.js +20 -20
  420. package/web-dist/components/card/Card.js +19 -19
  421. package/web-dist/components/card-back/CardBack.d.ts +7 -0
  422. package/web-dist/components/card-back/CardBack.js +19 -0
  423. package/web-dist/components/card-back/index.d.ts +1 -0
  424. package/web-dist/components/card-back/index.js +2 -0
  425. package/web-dist/components/card-hand/CardHand.d.ts +7 -0
  426. package/web-dist/components/card-hand/CardHand.js +19 -0
  427. package/web-dist/components/card-hand/index.d.ts +1 -0
  428. package/web-dist/components/card-hand/index.js +2 -0
  429. package/web-dist/components/chat-list-item/ChatListItem.js +16 -16
  430. package/web-dist/components/checkbox/Checkbox.js +12 -12
  431. package/web-dist/components/checkbox-group/CheckboxGroup.js +12 -12
  432. package/web-dist/components/chess-board/ChessBoard.d.ts +4 -0
  433. package/web-dist/components/chess-board/ChessBoard.js +13 -0
  434. package/web-dist/components/chess-board/index.d.ts +1 -0
  435. package/web-dist/components/chess-board/index.js +2 -0
  436. package/web-dist/components/chip/Chip.js +13 -13
  437. package/web-dist/components/chip-group/ChipGroup.js +13 -13
  438. package/web-dist/components/collection-editor/CollectionEditor.js +19 -19
  439. package/web-dist/components/content-rail/ContentRail.js +13 -13
  440. package/web-dist/components/data-table/DataTable.js +26 -26
  441. package/web-dist/components/date-picker/DatePicker.js +17 -17
  442. package/web-dist/components/dialog/Dialog.js +12 -12
  443. package/web-dist/components/divider/Divider.js +6 -6
  444. package/web-dist/components/empty-state/EmptyState.js +20 -20
  445. package/web-dist/components/field/Field.js +12 -12
  446. package/web-dist/components/flat-list/FlatList.js +13 -13
  447. package/web-dist/components/forgot-password-form/ForgotPasswordForm.js +18 -18
  448. package/web-dist/components/form/Form.js +16 -16
  449. package/web-dist/components/form-actions/FormActions.js +16 -16
  450. package/web-dist/components/form-error/FormError.js +16 -16
  451. package/web-dist/components/game/Game.d.ts +8 -0
  452. package/web-dist/components/game/Game.js +25 -0
  453. package/web-dist/components/game/index.d.ts +1 -0
  454. package/web-dist/components/game/index.js +2 -0
  455. package/web-dist/components/game-entity/GameEntity.d.ts +8 -0
  456. package/web-dist/components/game-entity/GameEntity.js +25 -0
  457. package/web-dist/components/game-entity/index.d.ts +1 -0
  458. package/web-dist/components/game-entity/index.js +2 -0
  459. package/web-dist/components/game-field/GameField.d.ts +8 -0
  460. package/web-dist/components/game-field/GameField.js +25 -0
  461. package/web-dist/components/game-field/index.d.ts +1 -0
  462. package/web-dist/components/game-field/index.js +2 -0
  463. package/web-dist/components/game-input-zone/GameInputZone.d.ts +8 -0
  464. package/web-dist/components/game-input-zone/GameInputZone.js +25 -0
  465. package/web-dist/components/game-input-zone/index.d.ts +1 -0
  466. package/web-dist/components/game-input-zone/index.js +2 -0
  467. package/web-dist/components/game-measurement-probe/GameMeasurementProbe.d.ts +8 -0
  468. package/web-dist/components/game-measurement-probe/GameMeasurementProbe.js +25 -0
  469. package/web-dist/components/game-measurement-probe/index.d.ts +1 -0
  470. package/web-dist/components/game-measurement-probe/index.js +2 -0
  471. package/web-dist/components/game-overlay/GameOverlay.d.ts +8 -0
  472. package/web-dist/components/game-overlay/GameOverlay.js +25 -0
  473. package/web-dist/components/game-overlay/index.d.ts +1 -0
  474. package/web-dist/components/game-overlay/index.js +2 -0
  475. package/web-dist/components/gradient/Gradient.js +7 -7
  476. package/web-dist/components/gradient-renderer-provider/GradientRendererProvider.js +7 -7
  477. package/web-dist/components/grid/Grid.js +6 -6
  478. package/web-dist/components/heading/Heading.js +6 -6
  479. package/web-dist/components/hero/Hero.js +19 -19
  480. package/web-dist/components/icon/Icon.js +4 -4
  481. package/web-dist/components/icon-button/IconButton.js +12 -12
  482. package/web-dist/components/image/Image.js +10 -10
  483. package/web-dist/components/keyboard-avoiding-view/KeyboardAvoidingView.js +2 -2
  484. package/web-dist/components/list/List.js +13 -13
  485. package/web-dist/components/list-item/ListItem.js +13 -13
  486. package/web-dist/components/list-section/ListSection.js +13 -13
  487. package/web-dist/components/media-card/MediaCard.js +19 -19
  488. package/web-dist/components/message-bubble/MessageBubble.js +16 -16
  489. package/web-dist/components/metric-card/MetricCard.js +19 -19
  490. package/web-dist/components/missing-element/MissingElement.js +11 -11
  491. package/web-dist/components/o-auth-provider-button/OAuthProviderButton.js +18 -18
  492. package/web-dist/components/o-auth-provider-list/OAuthProviderList.js +18 -18
  493. package/web-dist/components/opening-book/OpeningBook.d.ts +4 -0
  494. package/web-dist/components/opening-book/OpeningBook.js +13 -0
  495. package/web-dist/components/opening-book/index.d.ts +1 -0
  496. package/web-dist/components/opening-book/index.js +2 -0
  497. package/web-dist/components/otp-form/OtpForm.js +18 -18
  498. package/web-dist/components/pagination/Pagination.js +13 -13
  499. package/web-dist/components/palette-item/PaletteItem.js +19 -19
  500. package/web-dist/components/playing-card/PlayingCard.d.ts +7 -0
  501. package/web-dist/components/playing-card/PlayingCard.js +19 -0
  502. package/web-dist/components/playing-card/index.d.ts +1 -0
  503. package/web-dist/components/playing-card/index.js +2 -0
  504. package/web-dist/components/poker-training-table/PokerTrainingTable.d.ts +7 -0
  505. package/web-dist/components/poker-training-table/PokerTrainingTable.js +19 -0
  506. package/web-dist/components/poker-training-table/index.d.ts +1 -0
  507. package/web-dist/components/poker-training-table/index.js +2 -0
  508. package/web-dist/components/popover-menu/PopoverMenu.js +14 -14
  509. package/web-dist/components/post-card/PostCard.js +19 -19
  510. package/web-dist/components/product-card/ProductCard.js +19 -19
  511. package/web-dist/components/progress/Progress.js +10 -10
  512. package/web-dist/components/progress-ring/ProgressRing.js +10 -10
  513. package/web-dist/components/radio/Radio.js +14 -14
  514. package/web-dist/components/radio-group/RadioGroup.js +14 -14
  515. package/web-dist/components/rating/Rating.js +9 -9
  516. package/web-dist/components/reader-surface/ReaderSurface.js +21 -21
  517. package/web-dist/components/scan-overlay/ScanOverlay.js +20 -20
  518. package/web-dist/components/screen/Screen.js +6 -6
  519. package/web-dist/components/screen-section/ScreenSection.js +10 -10
  520. package/web-dist/components/scroll-view/ScrollView.js +6 -6
  521. package/web-dist/components/search-input/SearchInput.js +13 -13
  522. package/web-dist/components/section-header/SectionHeader.js +10 -10
  523. package/web-dist/components/section-list/SectionList.js +13 -13
  524. package/web-dist/components/select/Select.js +16 -16
  525. package/web-dist/components/selectable-item/SelectableItem.js +5 -5
  526. package/web-dist/components/selection-provider/SelectionProvider.js +5 -5
  527. package/web-dist/components/sign-in-form/SignInForm.js +18 -18
  528. package/web-dist/components/sign-up-form/SignUpForm.js +18 -18
  529. package/web-dist/components/skeleton/Skeleton.js +22 -22
  530. package/web-dist/components/skeleton-card/SkeletonCard.js +22 -22
  531. package/web-dist/components/skeleton-list/SkeletonList.js +22 -22
  532. package/web-dist/components/skeleton-text/SkeletonText.js +22 -22
  533. package/web-dist/components/surface/Surface.js +7 -7
  534. package/web-dist/components/switch/Switch.js +7 -7
  535. package/web-dist/components/tab/Tab.js +7 -7
  536. package/web-dist/components/tab-list/TabList.js +7 -7
  537. package/web-dist/components/tab-panel/TabPanel.js +7 -7
  538. package/web-dist/components/tabletop-table/TabletopTable.d.ts +7 -0
  539. package/web-dist/components/tabletop-table/TabletopTable.js +19 -0
  540. package/web-dist/components/tabletop-table/index.d.ts +1 -0
  541. package/web-dist/components/tabletop-table/index.js +2 -0
  542. package/web-dist/components/tabs/Tabs.js +7 -7
  543. package/web-dist/components/text/Text.js +6 -6
  544. package/web-dist/components/text-input/TextInput.js +13 -13
  545. package/web-dist/components/time-picker/TimePicker.js +17 -17
  546. package/web-dist/components/timeline/Timeline.js +11 -11
  547. package/web-dist/components/toast/Toast.js +9 -9
  548. package/web-dist/components/toast-provider/ToastProvider.js +9 -9
  549. package/web-dist/components/toolbar/Toolbar.js +19 -19
  550. package/web-dist/components/tree-item/TreeItem.js +16 -16
  551. package/web-dist/components/uploader/Uploader.js +22 -22
  552. package/web-dist/components/view/View.js +6 -6
  553. package/web-dist/manifest.json +1650 -1379
  554. package/web-dist/runtime/ZoraProvider.js +8 -8
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabletop.js","sourceRoot":"","sources":["../../src/types/tabletop.ts"],"names":[],"mappings":"","sourcesContent":["import type React from 'react';\n\nimport type { ZoraBaseProps } from './base';\n\nexport type PlayingCardSuit = 'clubs' | 'diamonds' | 'hearts' | 'spades';\nexport type TabletopCardSize = 'large' | 'medium' | 'small';\nexport type TabletopShape = 'circle' | 'oval' | 'rounded';\nexport type TabletopSeatCount = 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;\n\nexport interface PlayingCardValue {\n readonly rank: string;\n readonly suit: PlayingCardSuit;\n}\nexport interface TabletopSeatState {\n readonly id: string;\n readonly label: React.ReactNode;\n readonly sublabel?: React.ReactNode;\n readonly cards?: readonly PlayingCardValue[];\n readonly faceDownCards?: number;\n readonly selected?: boolean;\n readonly muted?: boolean;\n readonly disabled?: boolean;\n readonly tokenLabel?: React.ReactNode;\n readonly accessibilityLabel?: string;\n}\nexport type TabletopGameSeatPresentation = Omit<TabletopSeatState, 'id'>;\nexport interface TabletopGameSeatDefinition {\n readonly id: string;\n readonly defaultState: TabletopGameSeatPresentation;\n}\nexport interface TabletopGameParticipantState {\n readonly seatId: string;\n readonly state: Partial<TabletopGameSeatPresentation>;\n}\nexport interface CreateTabletopGameSeatsInput {\n readonly seats: readonly TabletopGameSeatDefinition[];\n readonly participants: readonly TabletopGameParticipantState[];\n readonly missingParticipantState?: Partial<TabletopGameSeatPresentation>;\n}\nexport interface TabletopColorScheme {\n readonly cardBack: string;\n readonly cardBackBorder: string;\n readonly cardBorder: string;\n readonly cardSurface: string;\n readonly cardText: string;\n readonly mutedText: string;\n readonly redSuitText: string;\n readonly seatBorder: string;\n readonly seatMutedText: string;\n readonly seatSelectedBorder: string;\n readonly seatSurface: string;\n readonly seatText: string;\n readonly tableBorder: string;\n readonly tableFelt: string;\n readonly tableInnerBorder: string;\n readonly tableMutedText: string;\n readonly tableText: string;\n readonly tokenSurface: string;\n readonly tokenText: string;\n}\nexport type TabletopColorOverrides = Partial<TabletopColorScheme>;\nexport interface CardBackProps extends ZoraBaseProps {\n readonly size?: TabletopCardSize;\n readonly muted?: boolean;\n readonly accessibilityLabel?: string;\n readonly colorScheme?: TabletopColorOverrides;\n}\nexport interface CardHandProps extends ZoraBaseProps {\n readonly cards?: readonly PlayingCardValue[];\n readonly faceDownCards?: number;\n readonly size?: TabletopCardSize;\n readonly muted?: boolean;\n readonly colorScheme?: TabletopColorOverrides;\n readonly accessibilityLabel?: string;\n}\nexport interface PlayingCardProps extends ZoraBaseProps {\n readonly card: PlayingCardValue;\n readonly size?: TabletopCardSize;\n readonly selected?: boolean;\n readonly muted?: boolean;\n readonly accessibilityLabel?: string;\n readonly colorScheme?: TabletopColorOverrides;\n}\nexport interface TabletopTableProps extends ZoraBaseProps {\n readonly seats: readonly TabletopSeatState[];\n readonly centerCards?: readonly PlayingCardValue[];\n readonly centerLabel?: React.ReactNode;\n readonly centerSublabel?: React.ReactNode;\n readonly shape?: TabletopShape;\n readonly seatCount?: TabletopSeatCount;\n readonly cardSize?: TabletopCardSize;\n readonly disabled?: boolean;\n readonly colorScheme?: TabletopColorOverrides;\n readonly accessibilityLabel?: string;\n}\nexport interface PokerTrainingPlayer {\n readonly position: string;\n readonly stack?: number;\n readonly bet?: number;\n readonly cards?: readonly PlayingCardValue[];\n readonly folded?: boolean;\n readonly isHero?: boolean;\n}\nexport type PokerTrainingTableSize = '6max' | '9max';\nexport interface PokerTrainingTaskTableData {\n readonly tableSize?: PokerTrainingTableSize;\n readonly blinds?: { readonly small: number; readonly big: number };\n readonly heroPosition?: string;\n readonly heroCards?: readonly PlayingCardValue[];\n readonly communityCards?: readonly PlayingCardValue[];\n readonly pot?: number;\n readonly players?: readonly PokerTrainingPlayer[];\n}\nexport interface PokerTrainingTableProps extends Omit<\n TabletopTableProps,\n 'seatCount' | 'seats' | 'centerCards' | 'centerLabel' | 'centerSublabel'\n> {\n readonly task?: PokerTrainingTaskTableData;\n readonly defaultStackBigBlinds?: number;\n}\nexport interface CreatePokerTrainingTableStateOptions {\n readonly defaultStackBigBlinds?: number;\n}\nexport interface PokerTrainingTableState {\n readonly seatCount: TabletopSeatCount;\n readonly seats: readonly TabletopSeatState[];\n readonly centerCards: readonly PlayingCardValue[];\n readonly centerLabel?: string;\n readonly centerSublabel?: string;\n readonly accessibilityLabel: string;\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/zora",
3
3
  "type": "module",
4
- "version": "21.0.23",
4
+ "version": "21.1.0",
5
5
  "description": "Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.",
6
6
  "homepage": "https://github.com/ankhorage/zora#readme",
7
7
  "bugs": {
@@ -42,6 +42,8 @@
42
42
  "dependencies": {
43
43
  "@ankhorage/color-theory": "^0.3.1",
44
44
  "@ankhorage/contracts": "^22.8.2",
45
+ "@ankhorage/game": "^0.1.2",
46
+ "@ankhorage/runtime": "^3.0.25",
45
47
  "@ankhorage/surface": "^9.1.7",
46
48
  "@ankhorage/utility": "^1.8.1",
47
49
  "expo-document-picker": "~57.0.1",
@@ -63,6 +63,11 @@ export const CONTAINER_ALLOWED_CHILDREN = [
63
63
  'MissingElement',
64
64
  ] as const;
65
65
 
66
+ export const GAME_ALLOWED_CHILDREN = ['Game', 'GameField'] as const;
67
+
68
+ export const CHESS_ALLOWED_CHILDREN = ['ChessBoard', 'OpeningBook'] as const;
69
+ export const TABLETOP_ALLOWED_CHILDREN = ['TabletopTable', 'PokerTrainingTable'] as const;
70
+
66
71
  export const CONTENT_RAIL_ALLOWED_CHILDREN = [
67
72
  'Chip',
68
73
  'ChipGroup',
@@ -84,6 +89,14 @@ export const CONTENT_RAIL_ALLOWED_CHILDREN = [
84
89
  'MissingElement',
85
90
  ] as const;
86
91
 
87
- export const SCREEN_SECTION_ALLOWED_CHILDREN = [...CONTAINER_ALLOWED_CHILDREN] as const;
92
+ export const SCREEN_SECTION_ALLOWED_CHILDREN = [
93
+ ...CONTAINER_ALLOWED_CHILDREN,
94
+ ...CHESS_ALLOWED_CHILDREN,
95
+ ...GAME_ALLOWED_CHILDREN,
96
+ ...TABLETOP_ALLOWED_CHILDREN,
97
+ ] as const;
88
98
 
89
- export const SCREEN_ALLOWED_CHILDREN = ['ScreenSection', ...CONTAINER_ALLOWED_CHILDREN] as const;
99
+ export const SCREEN_ALLOWED_CHILDREN = [
100
+ 'ScreenSection',
101
+ ...SCREEN_SECTION_ALLOWED_CHILDREN,
102
+ ] as const;
@@ -17,6 +17,32 @@ describe('ZORA_COMPONENT_META public API', () => {
17
17
  });
18
18
 
19
19
  describe('ZORA_COMPONENT_META registry coverage', () => {
20
+ test('registers the six Game components and their canonical placements', () => {
21
+ const names = [
22
+ 'Game',
23
+ 'GameField',
24
+ 'GameEntity',
25
+ 'GameInputZone',
26
+ 'GameMeasurementProbe',
27
+ 'GameOverlay',
28
+ ] as const;
29
+ const gameMetadata = Object.values(ZORA_COMPONENT_META).filter((meta) =>
30
+ names.some((name) => name === meta.name),
31
+ );
32
+ expect(gameMetadata).toHaveLength(names.length);
33
+ for (const meta of gameMetadata) expect(meta.directManifestNode).toBe(true);
34
+ expect(ZORA_COMPONENT_META.Screen.allowedChildren).toContain('Game');
35
+ expect(ZORA_COMPONENT_META.ScreenSection.allowedChildren).toContain('GameField');
36
+ expect(ZORA_COMPONENT_META.Game.allowedChildren).toContain('GameInputZone');
37
+ expect(ZORA_COMPONENT_META.Game.allowedChildren).toContain('GameMeasurementProbe');
38
+ expect(ZORA_COMPONENT_META.GameField.allowedChildren).toContain('GameEntity');
39
+ expect(ZORA_COMPONENT_META.GameField.allowedChildren).toContain('GameOverlay');
40
+ expect(ZORA_COMPONENT_META.Game.bindings?.props?.definition?.value.type).toBe('object');
41
+ expect(ZORA_COMPONENT_META.Game.bindings?.events?.output?.payload.eventType).toBe(
42
+ 'game.output',
43
+ );
44
+ });
45
+
20
46
  test('covers every public UI React component export (foundation/components/patterns/layout)', async () => {
21
47
  const source = await Bun.file('src/index.ts').text();
22
48
  const componentExports = Array.from(
@@ -185,6 +211,10 @@ describe('ZORA_COMPONENT_META invariants', () => {
185
211
  'Divider',
186
212
  'ChatListItem',
187
213
  'CameraPermissionView',
214
+ 'ChessBoard',
215
+ 'GameInputZone',
216
+ 'GameMeasurementProbe',
217
+ 'OpeningBook',
188
218
  'ScanOverlay',
189
219
  'ProductCard',
190
220
  'Progress',
@@ -192,6 +222,8 @@ describe('ZORA_COMPONENT_META invariants', () => {
192
222
  'ReaderSurface',
193
223
  'MissingElement',
194
224
  'TimePicker',
225
+ 'TabletopTable',
226
+ 'PokerTrainingTable',
195
227
  ]);
196
228
 
197
229
  const expectedContainerNodes = new Set([
@@ -200,6 +232,10 @@ describe('ZORA_COMPONENT_META invariants', () => {
200
232
  'Dialog',
201
233
  'Form',
202
234
  'Gradient',
235
+ 'Game',
236
+ 'GameEntity',
237
+ 'GameField',
238
+ 'GameOverlay',
203
239
  'Surface',
204
240
  'MediaCard',
205
241
  'FlatList',
@@ -254,6 +290,63 @@ describe('ZORA_COMPONENT_META invariants', () => {
254
290
  expect(ZORA_COMPONENT_META.Tabs.events?.valueChange?.eventType).toBe('tabs.valueChange');
255
291
  });
256
292
 
293
+ test('Chess and Tabletop retain their direct placement hierarchy without exposing card subprimitives', () => {
294
+ for (const name of ['CardBack', 'CardHand', 'PlayingCard']) {
295
+ expect(
296
+ Object.values(ZORA_COMPONENT_META).find((meta) => meta.name === name)?.directManifestNode,
297
+ ).toBe(false);
298
+ for (const meta of Object.values(ZORA_COMPONENT_META)) {
299
+ expect(meta.allowedChildren).not.toContain(name);
300
+ }
301
+ }
302
+ for (const parent of [
303
+ ZORA_COMPONENT_META.Card,
304
+ ZORA_COMPONENT_META.Grid,
305
+ ZORA_COMPONENT_META.Screen,
306
+ ZORA_COMPONENT_META.ScreenSection,
307
+ ]) {
308
+ for (const name of ['ChessBoard', 'OpeningBook', 'TabletopTable', 'PokerTrainingTable']) {
309
+ expect(parent.allowedChildren).toContain(name);
310
+ }
311
+ }
312
+ expect(ZORA_COMPONENT_META.View.allowedChildren).toContain('ChessBoard');
313
+ expect(ZORA_COMPONENT_META.View.allowedChildren).not.toContain('TabletopTable');
314
+ expect(ZORA_COMPONENT_META.ScrollView.allowedChildren).not.toContain('PokerTrainingTable');
315
+ });
316
+
317
+ test('Chess and Tabletop presentation bindings retain typed inputs and interaction intents', () => {
318
+ expect(ZORA_COMPONENT_META.ChessBoard.bindings?.props?.pieces?.value).toEqual({
319
+ type: 'array',
320
+ itemType: 'object',
321
+ });
322
+ expect(ZORA_COMPONENT_META.ChessBoard.bindings?.props?.legalTargets?.value).toEqual({
323
+ type: 'array',
324
+ itemType: 'string',
325
+ });
326
+ expect(ZORA_COMPONENT_META.OpeningBook.bindings?.props?.moves?.value).toEqual({
327
+ type: 'array',
328
+ itemType: 'object',
329
+ });
330
+ expect(ZORA_COMPONENT_META.OpeningBook.bindings?.events?.movePress?.payload.eventType).toBe(
331
+ 'chess.openingMovePress',
332
+ );
333
+ expect(ZORA_COMPONENT_META.TabletopTable.bindings?.props?.seats?.value).toEqual({
334
+ type: 'array',
335
+ itemType: 'object',
336
+ });
337
+ expect(ZORA_COMPONENT_META.PokerTrainingTable.bindings?.props?.task?.value).toMatchObject({
338
+ type: 'object',
339
+ fields: [
340
+ { path: 'blinds' },
341
+ { path: 'heroPosition' },
342
+ { path: 'heroCards' },
343
+ { path: 'communityCards' },
344
+ { path: 'pot' },
345
+ { path: 'players' },
346
+ ],
347
+ });
348
+ });
349
+
257
350
  test('Accordion constrains authored items to its canonical hierarchy', () => {
258
351
  expect(ZORA_COMPONENT_META.Accordion.directManifestNode).toBe(true);
259
352
  expect(ZORA_COMPONENT_META.Accordion.allowedChildren).toEqual(['AccordionItem']);
@@ -24,6 +24,7 @@ import { postCardMeta } from '../card/postCardMeta';
24
24
  import { productCardMeta } from '../card/productCardMeta';
25
25
  import { chatListItemMeta } from '../chat/chatListItemMeta';
26
26
  import { messageBubbleMeta } from '../chat/messageBubbleMeta';
27
+ import { chessBoardMeta, openingBookMeta } from '../chess/meta';
27
28
  import { chipGroupMeta } from '../chip/chipGroupMeta';
28
29
  import { chipMeta } from '../chip/chipMeta';
29
30
  import { collectionEditorMeta } from '../collection-editor/meta';
@@ -42,6 +43,12 @@ import { searchInputMeta } from '../form/search-input/searchInputMeta';
42
43
  import { selectMeta } from '../form/select/selectMeta';
43
44
  import { switchMeta } from '../form/switch/switchMeta';
44
45
  import { textInputMeta } from '../form/text-input/textInputMeta';
46
+ import { gameEntityMeta } from '../game/meta/gameEntityMeta';
47
+ import { gameFieldMeta } from '../game/meta/gameFieldMeta';
48
+ import { gameInputZoneMeta } from '../game/meta/gameInputZoneMeta';
49
+ import { gameMeasurementProbeMeta } from '../game/meta/gameMeasurementProbeMeta';
50
+ import { gameMeta } from '../game/meta/gameMeta';
51
+ import { gameOverlayMeta } from '../game/meta/gameOverlayMeta';
45
52
  import { gradientMeta } from '../gradient/gradientMeta';
46
53
  import { heroMeta } from '../hero/heroMeta';
47
54
  import { iconMeta } from '../icon/iconMeta';
@@ -74,6 +81,13 @@ import {
74
81
  skeletonTextMeta,
75
82
  } from '../skeleton/skeletonMeta';
76
83
  import { surfaceMeta } from '../surface/surfaceMeta';
84
+ import {
85
+ cardBackMeta,
86
+ cardHandMeta,
87
+ playingCardMeta,
88
+ pokerTrainingTableMeta,
89
+ tabletopTableMeta,
90
+ } from '../tabletop/meta';
77
91
  import { tabListMeta } from '../tabs/tabListMeta';
78
92
  import { tabMeta } from '../tabs/tabMeta';
79
93
  import { tabPanelMeta } from '../tabs/tabPanelMeta';
@@ -119,6 +133,12 @@ export const ZORA_COMPONENT_META: ZoraComponentMetaRegistry = finalizeFeatureMet
119
133
  FormError: formErrorMeta,
120
134
  Field: fieldMeta,
121
135
  Gradient: gradientMeta,
136
+ Game: gameMeta,
137
+ GameField: gameFieldMeta,
138
+ GameEntity: gameEntityMeta,
139
+ GameInputZone: gameInputZoneMeta,
140
+ GameMeasurementProbe: gameMeasurementProbeMeta,
141
+ GameOverlay: gameOverlayMeta,
122
142
  Heading: headingMeta,
123
143
  Icon: iconMeta,
124
144
  IconButton: iconButtonMeta,
@@ -165,6 +185,7 @@ export const ZORA_COMPONENT_META: ZoraComponentMetaRegistry = finalizeFeatureMet
165
185
  SignInForm: signInFormMeta,
166
186
  SignUpForm: signUpFormMeta,
167
187
  ChatListItem: chatListItemMeta,
188
+ ChessBoard: chessBoardMeta,
168
189
  CollectionEditor: collectionEditorMeta,
169
190
  ContentRail: contentRailMeta,
170
191
  EmptyState: emptyStateMeta,
@@ -173,6 +194,7 @@ export const ZORA_COMPONENT_META: ZoraComponentMetaRegistry = finalizeFeatureMet
173
194
  ListItem: listItemMeta,
174
195
  ListSection: listSectionMeta,
175
196
  MessageBubble: messageBubbleMeta,
197
+ OpeningBook: openingBookMeta,
176
198
  MissingElement: missingElementMeta,
177
199
  PostCard: postCardMeta,
178
200
  ProductCard: productCardMeta,
@@ -185,6 +207,11 @@ export const ZORA_COMPONENT_META: ZoraComponentMetaRegistry = finalizeFeatureMet
185
207
  SelectionProvider: selectionProviderMeta,
186
208
  PaletteItem: paletteItemMeta,
187
209
  Timeline: timelineMeta,
210
+ CardBack: cardBackMeta,
211
+ CardHand: cardHandMeta,
212
+ PlayingCard: playingCardMeta,
213
+ TabletopTable: tabletopTableMeta,
214
+ PokerTrainingTable: pokerTrainingTableMeta,
188
215
  TreeItem: treeItemMeta,
189
216
  TreeView: treeViewMeta,
190
217
  });
@@ -42,6 +42,9 @@ export const FEATURE_MANIFEST_ELEMENTS = {
42
42
  'time-picker': ['TimePicker'],
43
43
  uploader: ['Uploader'],
44
44
  'bottom-sheet': ['BottomSheet'],
45
+ chess: ['ChessBoard', 'OpeningBook'],
46
+ game: ['Game', 'GameField', 'GameEntity', 'GameInputZone', 'GameMeasurementProbe', 'GameOverlay'],
47
+ tabletop: ['TabletopTable', 'PokerTrainingTable'],
45
48
  } as const;
46
49
 
47
50
  export const ZORA_THEME_TOKEN_FAMILIES = [
@@ -1,12 +1,22 @@
1
1
  import type { ZoraComponentMeta } from '../authoring';
2
- import { CONTAINER_ALLOWED_CHILDREN } from '../authoring/allowedChildren';
2
+ import {
3
+ CHESS_ALLOWED_CHILDREN,
4
+ CONTAINER_ALLOWED_CHILDREN,
5
+ GAME_ALLOWED_CHILDREN,
6
+ TABLETOP_ALLOWED_CHILDREN,
7
+ } from '../authoring/allowedChildren';
3
8
  import { COMPONENT_THEME_AUTHORING } from '../authoring/constants';
4
9
 
5
10
  export const cardMeta = {
6
11
  name: 'Card',
7
12
  category: 'component',
8
13
  directManifestNode: true,
9
- allowedChildren: [...CONTAINER_ALLOWED_CHILDREN],
14
+ allowedChildren: [
15
+ ...CONTAINER_ALLOWED_CHILDREN,
16
+ ...CHESS_ALLOWED_CHILDREN,
17
+ ...GAME_ALLOWED_CHILDREN,
18
+ ...TABLETOP_ALLOWED_CHILDREN,
19
+ ],
10
20
  blueprint: { label: 'Card', defaultProps: { title: 'Card' } },
11
21
  events: { press: { label: 'Press', eventType: 'card.press', payloadFields: [] } },
12
22
  props: {
@@ -0,0 +1,169 @@
1
+ import React from 'react';
2
+ import { Pressable, StyleSheet, Text, View } from 'react-native';
3
+
4
+ import type { ChessBoardProps, ChessPieceState, ChessSquareId } from '../../../../types/chess';
5
+ import { withZoraThemeScope } from '../../../theme/adapters/inbound/withZoraThemeScope';
6
+ import { useZoraTheme } from '../../../theme/composition/useZoraTheme';
7
+ import { createBoardSquares } from '../../utils/createBoardSquares';
8
+ import { createChessBoardColorScheme } from '../../utils/createChessBoardColorScheme';
9
+ import { isLightSquare } from '../../utils/isLightSquare';
10
+
11
+ const symbols = new Map<string, string>([
12
+ ['white:p', '♙'],
13
+ ['white:n', '♘'],
14
+ ['white:b', '♗'],
15
+ ['white:r', '♖'],
16
+ ['white:q', '♕'],
17
+ ['white:k', '♔'],
18
+ ['black:p', '♟'],
19
+ ['black:n', '♞'],
20
+ ['black:b', '♝'],
21
+ ['black:r', '♜'],
22
+ ['black:q', '♛'],
23
+ ['black:k', '♚'],
24
+ ]);
25
+
26
+ /*** Renders caller-owned chess presentation state without chess rule execution. */
27
+ export const ChessBoard = withZoraThemeScope(ChessBoardInner);
28
+
29
+ /*** Renders the current presentation state without executing chess rules. */
30
+ function ChessBoardInner({
31
+ pieces = [],
32
+ orientation = 'white',
33
+ selectedSquare = null,
34
+ legalTargets = [],
35
+ lastMove = null,
36
+ disabled = false,
37
+ showCoordinates = false,
38
+ colorScheme,
39
+ onSquarePress,
40
+ onMoveAttempt,
41
+ renderPiece,
42
+ interactionPolicy,
43
+ testID,
44
+ }: ChessBoardProps) {
45
+ const { theme } = useZoraTheme();
46
+ const colors = createChessBoardColorScheme(theme, colorScheme);
47
+ const squares = createBoardSquares(orientation);
48
+ const piecesBySquare = new Map<ChessSquareId, ChessPieceState>(
49
+ pieces.map((piece) => [piece.square, piece]),
50
+ );
51
+ const legalTargetSet = new Set(legalTargets);
52
+ const pressSquare = (square: ChessSquareId) => {
53
+ if (disabled || interactionPolicy === 'passive') return;
54
+ onSquarePress?.(square);
55
+ if (selectedSquare !== null && selectedSquare !== square)
56
+ onMoveAttempt?.({ from: selectedSquare, to: square });
57
+ };
58
+ return (
59
+ <View
60
+ accessibilityLabel="Chess board"
61
+ style={[styles.board, { borderColor: colors.border, opacity: disabled ? 0.56 : 1 }]}
62
+ testID={testID}
63
+ >
64
+ {squares.map((square) => {
65
+ const piece = piecesBySquare.get(square);
66
+ const light = isLightSquare(square);
67
+ const isTarget = legalTargetSet.has(square);
68
+ const backgroundColor =
69
+ selectedSquare === square
70
+ ? colors.selectedSquare
71
+ : isTarget
72
+ ? colors.legalTarget
73
+ : lastMove?.from === square
74
+ ? colors.lastMoveFrom
75
+ : lastMove?.to === square
76
+ ? colors.lastMoveTo
77
+ : light
78
+ ? colors.lightSquare
79
+ : colors.darkSquare;
80
+ const pieceContent =
81
+ piece === undefined
82
+ ? null
83
+ : renderPiece
84
+ ? renderPiece({
85
+ color: piece.color === 'white' ? colors.lightPiece : colors.darkPiece,
86
+ piece: piece.piece,
87
+ square,
88
+ })
89
+ : (symbols.get(`${piece.color}:${piece.piece.toLowerCase()}`) ?? piece.piece);
90
+ return (
91
+ <Pressable
92
+ accessibilityLabel={square}
93
+ accessibilityRole="button"
94
+ disabled={disabled || interactionPolicy === 'passive'}
95
+ key={square}
96
+ onPress={() => pressSquare(square)}
97
+ style={[styles.square, { backgroundColor }]}
98
+ testID={testID ? `${testID}-square-${square}` : undefined}
99
+ >
100
+ {showCoordinates ? (
101
+ <Text
102
+ style={[
103
+ styles.coordinate,
104
+ { color: light ? colors.lightSquareText : colors.darkSquareText },
105
+ ]}
106
+ >
107
+ {square}
108
+ </Text>
109
+ ) : null}
110
+ {piece === undefined ? null : (
111
+ <View pointerEvents="none" style={styles.pieceContainer}>
112
+ {renderPiece ? (
113
+ pieceContent
114
+ ) : (
115
+ <Text
116
+ style={[
117
+ styles.piece,
118
+ { color: piece.color === 'white' ? colors.lightPiece : colors.darkPiece },
119
+ ]}
120
+ >
121
+ {pieceContent}
122
+ </Text>
123
+ )}
124
+ </View>
125
+ )}
126
+ </Pressable>
127
+ );
128
+ })}
129
+ </View>
130
+ );
131
+ }
132
+
133
+ const styles = StyleSheet.create({
134
+ board: {
135
+ aspectRatio: 1,
136
+ borderRadius: 12,
137
+ borderWidth: StyleSheet.hairlineWidth,
138
+ flexDirection: 'row',
139
+ flexWrap: 'wrap',
140
+ overflow: 'hidden',
141
+ width: '100%',
142
+ },
143
+ coordinate: {
144
+ fontSize: 9,
145
+ fontWeight: '600',
146
+ left: 3,
147
+ opacity: 0.72,
148
+ position: 'absolute',
149
+ top: 2,
150
+ zIndex: 2,
151
+ },
152
+ piece: { fontSize: 32, fontWeight: '600', lineHeight: 38 },
153
+ pieceContainer: {
154
+ alignItems: 'center',
155
+ bottom: 0,
156
+ justifyContent: 'center',
157
+ left: 0,
158
+ position: 'absolute',
159
+ right: 0,
160
+ top: 0,
161
+ },
162
+ square: {
163
+ alignItems: 'center',
164
+ aspectRatio: 1,
165
+ width: '12.5%',
166
+ justifyContent: 'center',
167
+ position: 'relative',
168
+ },
169
+ });
@@ -0,0 +1,131 @@
1
+ import React from 'react';
2
+ import { Pressable, StyleSheet, Text, View } from 'react-native';
3
+
4
+ import type { OpeningBookMove, OpeningBookProps } from '../../../../types/chess';
5
+ import { withZoraThemeScope } from '../../../theme/adapters/inbound/withZoraThemeScope';
6
+ import { useZoraTheme } from '../../../theme/composition/useZoraTheme';
7
+ import { createOpeningBookColorScheme } from '../../utils/createOpeningBookColorScheme';
8
+
9
+ /*** Renders caller-owned opening suggestions and their visual states. */
10
+ export const OpeningBook = withZoraThemeScope(OpeningBookInner);
11
+
12
+ /*** Formats an opening result percentage, accepting fractions or percentages. */
13
+ function rate(label: string, value: number | undefined): string | undefined {
14
+ if (value === undefined || !Number.isFinite(value)) return undefined;
15
+ return `${label} ${Math.round(value <= 1 ? value * 100 : value)}%`;
16
+ }
17
+
18
+ /*** Resolves an opening move's stable row key. */
19
+ function moveKey(move: OpeningBookMove): string {
20
+ return move.uci ?? move.fen ?? move.san;
21
+ }
22
+
23
+ /*** Renders the themed opening list without owning chess rules or data loading. */
24
+ function OpeningBookInner({
25
+ moves = [],
26
+ title = 'Opening book',
27
+ loading = false,
28
+ errorText,
29
+ emptyText = 'No book moves for this position.',
30
+ selectedMove = null,
31
+ colorScheme,
32
+ onMovePress,
33
+ interactionPolicy,
34
+ testID,
35
+ }: OpeningBookProps) {
36
+ const { theme } = useZoraTheme();
37
+ const colors = createOpeningBookColorScheme(theme, colorScheme);
38
+ const stateText = loading ? 'Loading opening moves…' : (errorText ?? emptyText);
39
+ const showState = loading || errorText !== undefined || moves.length === 0;
40
+ return (
41
+ <View
42
+ accessibilityLabel={title}
43
+ style={[
44
+ styles.root,
45
+ {
46
+ borderColor: colors.border,
47
+ backgroundColor: colors.surface,
48
+ },
49
+ ]}
50
+ testID={testID}
51
+ >
52
+ <Text style={[styles.title, { color: colors.titleText }]}>{title}</Text>
53
+ {!showState ? (
54
+ <View style={styles.moves}>
55
+ {moves.map((move) => {
56
+ const selected =
57
+ selectedMove !== null &&
58
+ (selectedMove === move.san || selectedMove === move.uci || selectedMove === move.fen);
59
+ const details = [
60
+ move.eco,
61
+ move.name,
62
+ move.games === undefined ? undefined : `${move.games} games`,
63
+ ].filter((part): part is string => typeof part === 'string' && part.length > 0);
64
+ const stats = [
65
+ rate('W', move.whiteWinRate),
66
+ rate('D', move.drawRate),
67
+ rate('B', move.blackWinRate),
68
+ ].filter((part): part is string => part !== undefined);
69
+ return (
70
+ <Pressable
71
+ accessibilityRole="button"
72
+ disabled={onMovePress === undefined || interactionPolicy === 'passive'}
73
+ key={moveKey(move)}
74
+ onPress={() => {
75
+ if (interactionPolicy === 'passive') return;
76
+ onMovePress?.(move);
77
+ }}
78
+ style={[
79
+ styles.move,
80
+ {
81
+ backgroundColor: selected ? colors.selectedSurface : colors.surfaceHover,
82
+ borderColor: colors.border,
83
+ },
84
+ ]}
85
+ testID={testID ? `${testID}-move-${move.san}` : undefined}
86
+ >
87
+ <View style={styles.moveMain}>
88
+ <Text style={[styles.san, { color: colors.primaryText }]}>{move.san}</Text>
89
+ <Text style={[styles.meta, { color: colors.secondaryText }]}>
90
+ {details.length > 0 ? details.join(' · ') : 'Book move'}
91
+ </Text>
92
+ </View>
93
+ {stats.length > 0 ? (
94
+ <View style={[styles.metric, { backgroundColor: colors.metricSurface }]}>
95
+ <Text style={[styles.metricText, { color: colors.secondaryText }]}>
96
+ {stats.join(' ')}
97
+ </Text>
98
+ </View>
99
+ ) : null}
100
+ </Pressable>
101
+ );
102
+ })}
103
+ </View>
104
+ ) : (
105
+ <Text style={[styles.stateText, { color: colors.secondaryText }]}>{stateText}</Text>
106
+ )}
107
+ </View>
108
+ );
109
+ }
110
+
111
+ const styles = StyleSheet.create({
112
+ root: { borderRadius: 12, borderWidth: StyleSheet.hairlineWidth, gap: 10, padding: 12 },
113
+ title: { fontSize: 15, fontWeight: '700', lineHeight: 20 },
114
+ stateText: { fontSize: 13, lineHeight: 18 },
115
+ moves: { gap: 8 },
116
+ move: {
117
+ alignItems: 'center',
118
+ borderRadius: 10,
119
+ borderWidth: StyleSheet.hairlineWidth,
120
+ flexDirection: 'row',
121
+ gap: 10,
122
+ justifyContent: 'space-between',
123
+ paddingHorizontal: 10,
124
+ paddingVertical: 8,
125
+ },
126
+ moveMain: { flex: 1, gap: 2 },
127
+ san: { fontSize: 16, fontWeight: '700', lineHeight: 20 },
128
+ meta: { fontSize: 12, lineHeight: 16 },
129
+ metric: { borderRadius: 999, paddingHorizontal: 8, paddingVertical: 4 },
130
+ metricText: { fontSize: 11, fontWeight: '600' },
131
+ });