@0xsequence/marketplace-sdk 0.9.0 → 0.10.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 (326) hide show
  1. package/.storybook/main.ts +63 -0
  2. package/.storybook/preview.ts +24 -0
  3. package/.storybook/vitest.setup.ts +6 -0
  4. package/CHANGELOG.md +77 -8
  5. package/dist/{CalendarIcon-DbQ7Vxcw.js → CalendarIcon-CqsuAuCm.js} +4 -51
  6. package/dist/CalendarIcon-CqsuAuCm.js.map +1 -0
  7. package/dist/{CollectibleCard-C8Ae64Ab.d.ts → CollectibleCard-Dd-CG6dE.d.ts} +8 -7
  8. package/dist/InfoIcon-v0w_Lu7t.js +53 -0
  9. package/dist/InfoIcon-v0w_Lu7t.js.map +1 -0
  10. package/dist/{_internal-BgWcRIak.js → _internal-C75gOSNo.js} +2 -10
  11. package/dist/_internal-C75gOSNo.js.map +1 -0
  12. package/dist/actionModal-CMUeVsFX.js +116 -0
  13. package/dist/actionModal-CMUeVsFX.js.map +1 -0
  14. package/dist/{alien_swap-B_76IMma.js → alien_swap-CYv6YlOF.js} +1 -1
  15. package/dist/{alien_swap-B_76IMma.js.map → alien_swap-CYv6YlOF.js.map} +1 -1
  16. package/dist/{api-DTIan01C.js → api-BiMGqWdz.js} +17 -34
  17. package/dist/api-BiMGqWdz.js.map +1 -0
  18. package/dist/{aqua-xyz-CMN_TFY5.js → aqua-xyz-Bzn5baeH.js} +1 -1
  19. package/dist/{aqua-xyz-CMN_TFY5.js.map → aqua-xyz-Bzn5baeH.js.map} +1 -1
  20. package/dist/{aura-Cye_TuHj.js → aura-DzIWh8WT.js} +1 -1
  21. package/dist/{aura-Cye_TuHj.js.map → aura-DzIWh8WT.js.map} +1 -1
  22. package/dist/base-DqaJPvfN.js +22 -0
  23. package/dist/base-DqaJPvfN.js.map +1 -0
  24. package/dist/{blur-DWDMyMpK.js → blur-DSH-Cbpj.js} +1 -1
  25. package/dist/{blur-DWDMyMpK.js.map → blur-DSH-Cbpj.js.map} +1 -1
  26. package/dist/{coinbase-ByA_XRB0.js → coinbase-Df8URNxq.js} +1 -1
  27. package/dist/{coinbase-ByA_XRB0.js.map → coinbase-Df8URNxq.js.map} +1 -1
  28. package/dist/{new-marketplace-types-Bfis0U4J.d.ts → create-config-DKJ-F0jc.d.ts} +402 -41
  29. package/dist/{wagmi-CDzEQbfk.js → create-config-fQ-jbJD1.js} +20 -10
  30. package/dist/create-config-fQ-jbJD1.js.map +1 -0
  31. package/dist/{element-b77CyXIZ.js → element-Cx6uJu5N.js} +1 -1
  32. package/dist/{element-b77CyXIZ.js.map → element-Cx6uJu5N.js.map} +1 -1
  33. package/dist/{foundation-DbOrKP9Y.js → foundation-D6U4aRLN.js} +1 -1
  34. package/dist/{foundation-DbOrKP9Y.js.map → foundation-D6U4aRLN.js.map} +1 -1
  35. package/dist/get-provider-CYYHfrlg.js +10 -0
  36. package/dist/get-provider-CYYHfrlg.js.map +1 -0
  37. package/dist/get-query-client-D19vvfJo.js +23 -0
  38. package/dist/get-query-client-D19vvfJo.js.map +1 -0
  39. package/dist/hooks-4pxIbLbM.js +4044 -0
  40. package/dist/hooks-4pxIbLbM.js.map +1 -0
  41. package/dist/{index-BL9RUSEK.d.ts → index-136YrWDH.d.ts} +1 -1
  42. package/dist/{index-D5v5iluA.d.ts → index-BAhaEfqY.d.ts} +1 -1
  43. package/dist/index-BKBin-rq.d.ts +979 -0
  44. package/dist/{index-BQsgAvtX.d.ts → index-BUWB_RXp.d.ts} +776 -570
  45. package/dist/{index-21LE7OhL.d.ts → index-BhVFc2rX.d.ts} +6 -3
  46. package/dist/{index-DXMfTZ1F.d.ts → index-C5aqo8xu.d.ts} +1 -1
  47. package/dist/{index-ByznONYE.d.ts → index-CKrYP7ot.d.ts} +20 -48
  48. package/dist/{index-DaE5ZNHb.d.ts → index-CUwMH7Ht.d.ts} +5 -5
  49. package/dist/{index-CLy8y5hm.d.ts → index-Cu70Lw-w.d.ts} +1 -1
  50. package/dist/index.css +414 -1
  51. package/dist/index.d.ts +8 -10
  52. package/dist/index.js +13 -9
  53. package/dist/{looks-rare-C1VqNcSM.js → looks-rare-ChBRBY-p.js} +1 -1
  54. package/dist/{looks-rare-C1VqNcSM.js.map → looks-rare-ChBRBY-p.js.map} +1 -1
  55. package/dist/{magic-eden-ea_AGCZr.js → magic-eden-D5U7N1xL.js} +1 -1
  56. package/dist/{magic-eden-ea_AGCZr.js.map → magic-eden-D5U7N1xL.js.map} +1 -1
  57. package/dist/{manifold-8y8J2sjT.js → manifold-CtLF52zU.js} +1 -1
  58. package/dist/{manifold-8y8J2sjT.js.map → manifold-CtLF52zU.js.map} +1 -1
  59. package/dist/{marketplace-nwnZv9Cb.js → marketplace-DmFiyBoS.js} +1 -1
  60. package/dist/{marketplace-nwnZv9Cb.js.map → marketplace-DmFiyBoS.js.map} +1 -1
  61. package/dist/{marketplace-logos-CSeGcPW4.js → marketplace-logos-Cd6W-qOq.js} +21 -21
  62. package/dist/{marketplace-logos-CSeGcPW4.js.map → marketplace-logos-Cd6W-qOq.js.map} +1 -1
  63. package/dist/{marketplace.gen-BSDIX7NZ.js → marketplace.gen-HpnpL5xU.js} +3 -3
  64. package/dist/marketplace.gen-HpnpL5xU.js.map +1 -0
  65. package/dist/{marketplaceConfig-C6X1SUik.js → marketplaceConfig-GQTTmihy.js} +3 -3
  66. package/dist/marketplaceConfig-GQTTmihy.js.map +1 -0
  67. package/dist/{mintify-LA68TzWg.js → mintify-Bi3Bce68.js} +1 -1
  68. package/dist/{mintify-LA68TzWg.js.map → mintify-Bi3Bce68.js.map} +1 -1
  69. package/dist/network-CGD0oKtS.js +15 -0
  70. package/dist/network-CGD0oKtS.js.map +1 -0
  71. package/dist/{nftx-D3Tc8nzd.js → nftx-BDQZjtkX.js} +1 -1
  72. package/dist/{nftx-D3Tc8nzd.js.map → nftx-BDQZjtkX.js.map} +1 -1
  73. package/dist/{okx-hbqg6oIJ.js → okx-D4meadLe.js} +1 -1
  74. package/dist/{okx-hbqg6oIJ.js.map → okx-D4meadLe.js.map} +1 -1
  75. package/dist/{open-sea-BccuK8-t.js → open-sea-DN0hgfVw.js} +1 -1
  76. package/dist/{open-sea-BccuK8-t.js.map → open-sea-DN0hgfVw.js.map} +1 -1
  77. package/dist/{primary-sale-C55ALnfQ.js → primary-sale-CmWxSfFQ.js} +1 -1
  78. package/dist/{primary-sale-C55ALnfQ.js.map → primary-sale-CmWxSfFQ.js.map} +1 -1
  79. package/dist/provider-DPGUA10G.js +125 -0
  80. package/dist/provider-DPGUA10G.js.map +1 -0
  81. package/dist/{queries-CUU65uYZ.js → queries-Ce_2othB.js} +165 -7
  82. package/dist/queries-Ce_2othB.js.map +1 -0
  83. package/dist/{rarible-BgTwwj9g.js → rarible-B0xlD88A.js} +1 -1
  84. package/dist/{rarible-BgTwwj9g.js.map → rarible-B0xlD88A.js.map} +1 -1
  85. package/dist/react/_internal/api/index.d.ts +2 -4
  86. package/dist/react/_internal/api/index.js +7 -4
  87. package/dist/react/_internal/databeat/index.d.ts +2 -73
  88. package/dist/react/_internal/databeat/index.js +4 -21
  89. package/dist/react/_internal/index.d.ts +2 -7
  90. package/dist/react/_internal/index.js +11 -6
  91. package/dist/react/_internal/wagmi/index.d.ts +2 -4
  92. package/dist/react/_internal/wagmi/index.js +5 -3
  93. package/dist/react/hooks/index.d.ts +12 -17
  94. package/dist/react/hooks/index.js +23 -19
  95. package/dist/react/hooks/options/index.d.ts +2 -3
  96. package/dist/react/hooks/options/index.js +12 -7
  97. package/dist/react/index.d.ts +12 -17
  98. package/dist/react/index.js +28 -19
  99. package/dist/react/queries/index.d.ts +9 -8
  100. package/dist/react/queries/index.js +20 -15
  101. package/dist/react/ssr/index.d.ts +7 -9
  102. package/dist/react/ssr/index.js +11 -6
  103. package/dist/react/ssr/index.js.map +1 -1
  104. package/dist/react/ui/components/marketplace-collectible-card/index.d.ts +3 -8
  105. package/dist/react/ui/components/marketplace-collectible-card/index.js +27 -18
  106. package/dist/react/ui/components/marketplace-collectible-card/utils/index.d.ts +2 -7
  107. package/dist/react/ui/components/marketplace-collectible-card/utils/index.js +11 -6
  108. package/dist/react/ui/components/marketplace-logos/index.d.ts +21 -21
  109. package/dist/react/ui/components/marketplace-logos/index.js +1 -1
  110. package/dist/react/ui/icons/index.js +13 -9
  111. package/dist/react/ui/index.d.ts +3 -8
  112. package/dist/react/ui/index.js +27 -18
  113. package/dist/react/ui/modals/_internal/components/actionModal/index.d.ts +2 -2
  114. package/dist/react/ui/modals/_internal/components/actionModal/index.js +23 -18
  115. package/dist/{react-DAIicQPT.js → react-DP0M2Wfm.js} +799 -4306
  116. package/dist/react-DP0M2Wfm.js.map +1 -0
  117. package/dist/{react-BbHBl6gg.css → react-DeDyTgo7.css} +1 -1
  118. package/dist/{react-BbHBl6gg.css.map → react-DeDyTgo7.css.map} +1 -1
  119. package/dist/{sequence-Do3kzb4J.js → sequence-BIrOVRXO.js} +1 -1
  120. package/dist/{sequence-Do3kzb4J.js.map → sequence-BIrOVRXO.js.map} +1 -1
  121. package/dist/{sudo-swap-B6vPKxBz.js → sudo-swap-BPMon-M5.js} +1 -1
  122. package/dist/{sudo-swap-B6vPKxBz.js.map → sudo-swap-BPMon-M5.js.map} +1 -1
  123. package/dist/{super-rare-eCm1SE6O.js → super-rare-kPN6Ua8i.js} +1 -1
  124. package/dist/{super-rare-eCm1SE6O.js.map → super-rare-kPN6Ua8i.js.map} +1 -1
  125. package/dist/{token-Da4TdyUk.js → token-CHSBPYVG.js} +1 -1
  126. package/dist/{token-Da4TdyUk.js.map → token-CHSBPYVG.js.map} +1 -1
  127. package/dist/{transaction-CcVViHEL.js → transaction-CnctdNzS.js} +3 -21
  128. package/dist/transaction-CnctdNzS.js.map +1 -0
  129. package/dist/types/index.d.ts +2 -3
  130. package/dist/types/index.js +2 -2
  131. package/dist/{types-DwWE6xOF.js → types-Yw2ywj6j.js} +1 -1
  132. package/dist/{types-DwWE6xOF.js.map → types-Yw2ywj6j.js.map} +1 -1
  133. package/dist/utils/abi/index.d.ts +4 -4
  134. package/dist/utils/abi/index.js +4 -4
  135. package/dist/utils/abi/marketplace/index.d.ts +1 -1
  136. package/dist/utils/abi/marketplace/index.js +1 -1
  137. package/dist/utils/abi/primary-sale/index.d.ts +1 -1
  138. package/dist/utils/abi/primary-sale/index.js +1 -1
  139. package/dist/utils/abi/token/index.d.ts +1 -1
  140. package/dist/utils/abi/token/index.js +1 -1
  141. package/dist/utils/index.d.ts +7 -8
  142. package/dist/utils/index.js +12 -9
  143. package/dist/{utils-CW2NA5KG.js → utils-9RXDgcBl.js} +4 -11
  144. package/dist/utils-9RXDgcBl.js.map +1 -0
  145. package/dist/{utils-BPYfgDSL.js → utils-DjVJ9tov.js} +5 -6
  146. package/dist/utils-DjVJ9tov.js.map +1 -0
  147. package/dist/wagmi-Do_KW5ke.js +0 -0
  148. package/dist/{x2y2-DD17tT91.js → x2y2-BLz-_Q2O.js} +1 -1
  149. package/dist/{x2y2-DD17tT91.js.map → x2y2-BLz-_Q2O.js.map} +1 -1
  150. package/dist/{zora-BpSG9UzS.js → zora-UGhKs-aL.js} +1 -1
  151. package/dist/{zora-BpSG9UzS.js.map → zora-UGhKs-aL.js.map} +1 -1
  152. package/eslint.config.mjs +4 -0
  153. package/package.json +27 -14
  154. package/postcss.config.mjs +6 -0
  155. package/src/index.css +5 -4
  156. package/src/index.ts +1 -0
  157. package/src/react/__tests__/provider.test.tsx +4 -3
  158. package/src/react/_internal/api/__mocks__/indexer.msw.ts +16 -0
  159. package/src/react/_internal/api/__mocks__/laos.msw.ts +387 -0
  160. package/src/react/_internal/api/__mocks__/marketplace.msw.ts +2 -0
  161. package/src/react/_internal/api/__tests__/laos-api.test.ts +756 -0
  162. package/src/react/_internal/api/laos-api.ts +3 -0
  163. package/src/react/_internal/api/marketplace.gen.ts +5 -3
  164. package/src/react/_internal/api/query-keys.ts +12 -4
  165. package/src/react/_internal/api/services.ts +2 -14
  166. package/src/react/_internal/databeat/index.ts +15 -14
  167. package/src/react/_internal/databeat/types.ts +22 -0
  168. package/src/react/_internal/databeat/utils.ts +26 -0
  169. package/src/react/_internal/utils.ts +4 -4
  170. package/src/react/_internal/wagmi/create-config.ts +28 -13
  171. package/src/react/_internal/wallet/wallet.ts +4 -4
  172. package/src/react/hooks/__tests__/useBalanceOfCollectible.laos.test.tsx +367 -0
  173. package/src/react/hooks/__tests__/useCheckoutOptions.test.tsx +158 -0
  174. package/src/react/hooks/__tests__/useCheckoutOptionsSalesContract.test.tsx +42 -65
  175. package/src/react/hooks/__tests__/useCollectionBalanceDetails.test.tsx +17 -0
  176. package/src/react/hooks/__tests__/useCollectionDetailsPolling.test.tsx +11 -3
  177. package/src/react/hooks/__tests__/useConvertPriceToUSD.test.tsx +3 -3
  178. package/src/react/hooks/__tests__/useCurrencyBalance.test.tsx +7 -3
  179. package/src/react/hooks/__tests__/useFilters.test.tsx +2 -2
  180. package/src/react/hooks/__tests__/useGetTokenRanges.test.tsx +111 -0
  181. package/src/react/hooks/__tests__/useListTokenMetadata.test.tsx +83 -57
  182. package/src/react/hooks/__tests__/useTransferTokens.test.tsx +469 -0
  183. package/src/react/hooks/index.ts +3 -1
  184. package/src/react/hooks/useCheckoutOptions.tsx +96 -0
  185. package/src/react/hooks/useCheckoutOptionsSalesContract.tsx +98 -57
  186. package/src/react/hooks/useCollectionBalanceDetails.tsx +95 -68
  187. package/src/react/hooks/useCollectionDetailsPolling.tsx +3 -7
  188. package/src/react/hooks/useComparePrices.tsx +90 -82
  189. package/src/react/hooks/useConvertPriceToUSD.tsx +85 -71
  190. package/src/react/hooks/useCurrencyBalance.tsx +132 -46
  191. package/src/react/hooks/useERC721SaleMintedTokens.tsx +8 -5
  192. package/src/react/hooks/useFilters.tsx +154 -111
  193. package/src/react/hooks/useGetCountOfPrimarySaleItems.tsx +48 -0
  194. package/src/react/hooks/useGetTokenRanges.tsx +83 -22
  195. package/src/react/hooks/useList1155ShopCardData.tsx +2 -0
  196. package/src/react/hooks/useList721ShopCardData.tsx +12 -7
  197. package/src/react/hooks/useListCollections.tsx +25 -25
  198. package/src/react/hooks/useListMarketCardData.tsx +2 -1
  199. package/src/react/hooks/useListPrimarySaleItems.tsx +66 -0
  200. package/src/react/hooks/useListTokenMetadata.ts +71 -0
  201. package/src/react/hooks/useOpenConnectModal.tsx +9 -0
  202. package/src/react/hooks/useTokenSaleDetailsBatch.tsx +3 -7
  203. package/src/react/hooks/useTokenSupplies.ts +81 -0
  204. package/src/react/hooks/useTransferTokens.tsx +2 -2
  205. package/src/react/provider.tsx +73 -9
  206. package/src/react/queries/__tests__/balanceOfCollectible.laos.test.ts +123 -0
  207. package/src/react/queries/__tests__/inventory.laos.test.ts +496 -0
  208. package/src/react/queries/balanceOfCollectible.ts +7 -4
  209. package/src/react/queries/checkoutOptions.ts +85 -0
  210. package/src/react/queries/checkoutOptionsSalesContract.ts +89 -0
  211. package/src/react/queries/collectionBalanceDetails.ts +92 -0
  212. package/src/react/queries/comparePrices.ts +108 -0
  213. package/src/react/queries/convertPriceToUSD.ts +92 -0
  214. package/src/react/queries/filters.ts +138 -0
  215. package/src/react/queries/getTokenRanges.ts +62 -0
  216. package/src/react/queries/index.ts +3 -0
  217. package/src/react/queries/inventory.ts +6 -0
  218. package/src/react/queries/listBalances.ts +4 -3
  219. package/src/react/queries/listCollections.ts +7 -3
  220. package/src/react/queries/listTokenMetadata.ts +2 -2
  221. package/src/react/queries/marketplaceConfig.ts +1 -1
  222. package/src/react/queries/primarySaleItems.ts +85 -0
  223. package/src/react/queries/primarySaleItemsCount.ts +64 -0
  224. package/src/react/queries/tokenSupplies.ts +93 -0
  225. package/src/react/ui/components/_internals/action-button/ActionButton.tsx +66 -66
  226. package/src/react/ui/components/_internals/action-button/__tests__/ActionButtonBody.test.tsx +22 -4
  227. package/src/react/ui/components/_internals/action-button/components/ActionButtonBody.tsx +5 -4
  228. package/src/react/ui/components/_internals/action-button/components/NonOwnerActions.tsx +3 -0
  229. package/src/react/ui/components/_internals/action-button/components/OwnerActions.tsx +4 -4
  230. package/src/react/ui/components/_internals/action-button/hooks/useActionButtonLogic.ts +13 -8
  231. package/src/react/ui/components/_internals/action-button/store.ts +44 -34
  232. package/src/react/ui/components/_internals/custom-select/CustomSelect.stories.tsx +582 -0
  233. package/src/react/ui/components/_internals/pill/Pill.stories.tsx +83 -0
  234. package/src/react/ui/components/marketplace-collectible-card/Footer.tsx +11 -4
  235. package/src/react/ui/components/marketplace-collectible-card/components/ActionButtonWrapper.tsx +7 -4
  236. package/src/react/ui/components/marketplace-collectible-card/types.ts +4 -3
  237. package/src/react/ui/components/marketplace-collectible-card/utils/supplyStatus.ts +4 -7
  238. package/src/react/ui/components/marketplace-collectible-card/variants/ShopCard.tsx +5 -1
  239. package/src/react/ui/components/marketplace-logos/marketplace-logos.stories.tsx +199 -0
  240. package/src/react/ui/components/media/Media.stories.tsx +642 -0
  241. package/src/react/ui/components/media/Media.tsx +24 -19
  242. package/src/react/ui/components/media/types.ts +6 -0
  243. package/src/react/ui/modals/BuyModal/__tests__/BuyModalRouter.test.tsx +15 -0
  244. package/src/react/ui/modals/BuyModal/__tests__/ERC1155ShopModal.test.tsx +6 -0
  245. package/src/react/ui/modals/BuyModal/__tests__/Modal1155.test.tsx +7 -1
  246. package/src/react/ui/modals/BuyModal/__tests__/store.test.ts +9 -1
  247. package/src/react/ui/modals/BuyModal/components/ERC1155QuantityModal.tsx +15 -8
  248. package/src/react/ui/modals/BuyModal/components/ERC1155ShopModal.tsx +3 -0
  249. package/src/react/ui/modals/BuyModal/hooks/__tests__/useERC1155Checkout.test.tsx +30 -27
  250. package/src/react/ui/modals/BuyModal/hooks/useCheckoutOptions.ts +2 -2
  251. package/src/react/ui/modals/BuyModal/hooks/useERC1155Checkout.ts +11 -2
  252. package/src/react/ui/modals/BuyModal/hooks/useERC721SalePaymentParams.ts +1 -1
  253. package/src/react/ui/modals/BuyModal/hooks/usePaymentModalParams.ts +7 -0
  254. package/src/react/ui/modals/BuyModal/index.tsx +9 -1
  255. package/src/react/ui/modals/BuyModal/store.ts +26 -0
  256. package/src/react/ui/modals/CreateListingModal/Modal.tsx +28 -11
  257. package/src/react/ui/modals/CreateListingModal/store.ts +3 -3
  258. package/src/react/ui/modals/MakeOfferModal/Modal.tsx +30 -13
  259. package/src/react/ui/modals/MakeOfferModal/store.ts +3 -3
  260. package/src/react/ui/modals/SellModal/Modal.tsx +11 -8
  261. package/src/react/ui/modals/SellModal/store.ts +3 -3
  262. package/src/react/ui/modals/TransferModal/__tests__/__snapshots__/store.test.ts.snap +17 -0
  263. package/src/react/ui/modals/TransferModal/__tests__/store.test.ts +366 -0
  264. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/__tests__/useHandleTransfer.test.tsx +402 -0
  265. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/_components/TokenQuantityInput.tsx +51 -48
  266. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/_components/TransferButton.tsx +39 -47
  267. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/_components/WalletAddressInput.tsx +9 -8
  268. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/index.tsx +31 -35
  269. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/useHandleTransfer.tsx +19 -10
  270. package/src/react/ui/modals/TransferModal/index.tsx +28 -31
  271. package/src/react/ui/modals/TransferModal/messages.ts +1 -1
  272. package/src/react/ui/modals/TransferModal/store.ts +122 -0
  273. package/src/react/ui/modals/_internal/components/calendar/index.tsx +0 -1
  274. package/src/react/ui/modals/_internal/components/currencyImage/index.tsx +10 -14
  275. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/__tests__/index.test.tsx +5 -2
  276. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/index.tsx +23 -17
  277. package/src/react/ui/modals/_internal/components/expirationDateSelect/index.tsx +10 -10
  278. package/src/react/ui/modals/_internal/components/floorPriceText/__tests__/FloorPriceText.test.tsx +6 -6
  279. package/src/react/ui/modals/_internal/components/priceInput/__tests__/PriceInput.test.tsx +13 -5
  280. package/src/react/ui/modals/_internal/components/priceInput/index.tsx +41 -26
  281. package/src/react/ui/modals/_internal/components/quantityInput/__tests__/index.test.tsx +68 -59
  282. package/src/react/ui/modals/_internal/components/quantityInput/index.tsx +155 -20
  283. package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/__tests__/SelectWaasFeeOptions.test.tsx +339 -40
  284. package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/index.tsx +95 -101
  285. package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/store.ts +72 -14
  286. package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/useWaasFeeOptionManager.tsx +29 -13
  287. package/src/react/ui/modals/_internal/components/tokenPreview/index.tsx +2 -2
  288. package/src/react/ui/modals/_internal/components/transactionDetails/index.tsx +2 -2
  289. package/src/react/ui/modals/_internal/components/transactionPreview/index.tsx +88 -89
  290. package/src/react/ui/modals/_internal/components/transactionStatusModal/__tests__/TransactionStatusModal.test.tsx +36 -10
  291. package/src/react/ui/modals/_internal/components/transactionStatusModal/index.tsx +32 -20
  292. package/src/react/ui/modals/_internal/components/transactionStatusModal/store.ts +91 -62
  293. package/src/react/ui/modals/_internal/components/waasFeeOptionsSelect/WaasFeeOptionsSelect.tsx +43 -44
  294. package/src/react/ui/modals/_internal/types.ts +2 -2
  295. package/src/types/sdk-config.ts +6 -1
  296. package/src/utils/network.ts +15 -0
  297. package/test/test-utils.tsx +2 -0
  298. package/vitest.shims.d.ts +2 -0
  299. package/vitest.storybook.config.js +33 -0
  300. package/dist/CalendarIcon-DbQ7Vxcw.js.map +0 -1
  301. package/dist/_internal-BgWcRIak.js.map +0 -1
  302. package/dist/api-DTIan01C.js.map +0 -1
  303. package/dist/builder-api-C_zj5mr3.d.ts +0 -12
  304. package/dist/index-BUVWziLP.d.ts +0 -60
  305. package/dist/index-COt10OgI.d.ts +0 -24
  306. package/dist/index-DPNWNa7t.d.ts +0 -414
  307. package/dist/index-DsfCs3-x.d.ts +0 -122
  308. package/dist/index-dUb6wb4Y.d.ts +0 -22
  309. package/dist/marketplace.gen-BSDIX7NZ.js.map +0 -1
  310. package/dist/marketplaceConfig-C6X1SUik.js.map +0 -1
  311. package/dist/queries-CUU65uYZ.js.map +0 -1
  312. package/dist/react-DAIicQPT.js.map +0 -1
  313. package/dist/transaction-CcVViHEL.js.map +0 -1
  314. package/dist/utils-BPYfgDSL.js.map +0 -1
  315. package/dist/utils-CW2NA5KG.js.map +0 -1
  316. package/dist/wagmi-CDzEQbfk.js.map +0 -1
  317. package/src/react/hooks/__tests__/useGetTokenSuppliesMap.test.tsx +0 -104
  318. package/src/react/hooks/useGetTokenSuppliesMap.tsx +0 -73
  319. package/src/react/hooks/useListPrimarySaleItems.ts +0 -102
  320. package/src/react/queries/getTokenSuppliesMap.ts +0 -77
  321. package/src/react/ui/modals/TransferModal/_store.ts +0 -66
  322. package/src/react/ui/modals/_internal/components/quantityInput/QuantityInputBase.tsx +0 -166
  323. package/src/react/ui/modals/_internal/stores/accountModal.ts +0 -3
  324. /package/dist/{abi-BKyRjVcZ.js → abi-BMvgNbKQ.js} +0 -0
  325. /package/dist/{index-C39K_8SG.d.ts → index-CD2bj_xW.d.ts} +0 -0
  326. /package/dist/{options-B4QN7Xou.js → options-BBBR8u_4.js} +0 -0
@@ -1,8 +1,6 @@
1
1
  'use client';
2
2
 
3
3
  import { Skeleton, Text } from '@0xsequence/design-system';
4
- import type { Observable } from '@legendapp/state';
5
- import { observer } from '@legendapp/state/react';
6
4
  import { addDays } from 'date-fns';
7
5
  import { useState } from 'react';
8
6
  import { cn } from '../../../../../../utils';
@@ -47,13 +45,15 @@ export type RangeType =
47
45
 
48
46
  type ExpirationDateSelectProps = {
49
47
  className?: string;
50
- $date: Observable<Date>;
48
+ date: Date;
49
+ onDateChange: (date: Date) => void;
51
50
  disabled?: boolean;
52
51
  };
53
52
 
54
- const ExpirationDateSelect = observer(function ExpirationDateSelect({
53
+ const ExpirationDateSelect = function ExpirationDateSelect({
55
54
  className,
56
- $date,
55
+ date,
56
+ onDateChange,
57
57
  disabled,
58
58
  }: ExpirationDateSelectProps) {
59
59
  const [calendarDropdownOpen, setCalendarDropdownOpen] = useState(false);
@@ -73,14 +73,14 @@ const ExpirationDateSelect = observer(function ExpirationDateSelect({
73
73
  ? setToEndOfDay(baseDate)
74
74
  : addDays(baseDate, presetRange.offset);
75
75
 
76
- $date.set(newDate);
76
+ onDateChange(newDate);
77
77
  }
78
78
 
79
79
  function handleDateValueChange(date: Date) {
80
- $date.set(date);
80
+ onDateChange(date);
81
81
  }
82
82
 
83
- if (!$date.get()) {
83
+ if (!date) {
84
84
  return <Skeleton className="mr-3 h-7 w-20 rounded-2xl" />;
85
85
  }
86
86
 
@@ -102,7 +102,7 @@ const ExpirationDateSelect = observer(function ExpirationDateSelect({
102
102
  className={`${className} mt-0.5 flex w-full items-center gap-2 rounded-sm border border-border-base`}
103
103
  >
104
104
  <CalendarDropdown
105
- selectedDate={$date.get()}
105
+ selectedDate={date}
106
106
  setSelectedDate={handleDateValueChange}
107
107
  onSelectPreset={handleSelectPresetRange}
108
108
  isOpen={calendarDropdownOpen}
@@ -111,6 +111,6 @@ const ExpirationDateSelect = observer(function ExpirationDateSelect({
111
111
  </div>
112
112
  </div>
113
113
  );
114
- });
114
+ };
115
115
 
116
116
  export default ExpirationDateSelect;
@@ -1,5 +1,5 @@
1
1
  import { render } from '@test';
2
- import type { Hex } from 'viem';
2
+ import type { Address } from 'viem';
3
3
  import { beforeEach, describe, expect, it, vi } from 'vitest';
4
4
  import type { Currency } from '../../../../../../_internal/api/marketplace.gen';
5
5
  import * as hooks from '../../../../../../hooks';
@@ -7,7 +7,7 @@ import FloorPriceText from '../index';
7
7
 
8
8
  describe('FloorPriceText', () => {
9
9
  const mockCurrency: Currency = {
10
- contractAddress: '0x0000000000000000000000000000000000000000' as Hex,
10
+ contractAddress: '0x0000000000000000000000000000000000000000' as Address,
11
11
  symbol: 'ETH',
12
12
  decimals: 18,
13
13
  name: 'Ethereum',
@@ -23,7 +23,7 @@ describe('FloorPriceText', () => {
23
23
 
24
24
  const mockProps = {
25
25
  chainId: 1,
26
- collectionAddress: '0x1234567890123456789012345678901234567890' as Hex,
26
+ collectionAddress: '0x1234567890123456789012345678901234567890' as Address,
27
27
  tokenId: '1',
28
28
  price: {
29
29
  amountRaw: '1000000000000000000',
@@ -96,7 +96,7 @@ describe('FloorPriceText', () => {
96
96
  priceAmount: '1000000000000000000',
97
97
  priceAmountFormatted: '1',
98
98
  priceCurrencyAddress:
99
- '0x0000000000000000000000000000000000000000' as Hex,
99
+ '0x0000000000000000000000000000000000000000' as Address,
100
100
  },
101
101
  isLoading: false,
102
102
  status: 'success',
@@ -132,7 +132,7 @@ describe('FloorPriceText', () => {
132
132
  priceAmount: '1200000000000000000', // Floor price is higher
133
133
  priceAmountFormatted: '1.2',
134
134
  priceCurrencyAddress:
135
- '0x0000000000000000000000000000000000000000' as Hex,
135
+ '0x0000000000000000000000000000000000000000' as Address,
136
136
  },
137
137
  isLoading: false,
138
138
  status: 'success',
@@ -170,7 +170,7 @@ describe('FloorPriceText', () => {
170
170
  priceAmount: '800000000000000000', // Floor price is lower
171
171
  priceAmountFormatted: '0.8',
172
172
  priceCurrencyAddress:
173
- '0x0000000000000000000000000000000000000000' as Hex,
173
+ '0x0000000000000000000000000000000000000000' as Address,
174
174
  },
175
175
  isLoading: false,
176
176
  status: 'success',
@@ -1,4 +1,3 @@
1
- import { observable } from '@legendapp/state';
2
1
  import { TEST_CURRENCY } from '@test/const';
3
2
  import { fireEvent, render, screen } from '@test/test-utils';
4
3
  import { zeroAddress } from 'viem';
@@ -8,10 +7,10 @@ import PriceInput from '..';
8
7
  const defaultProps = {
9
8
  chainId: 1,
10
9
  collectionAddress: zeroAddress,
11
- $price: observable({
10
+ price: {
12
11
  amountRaw: '0',
13
12
  currency: TEST_CURRENCY,
14
- }),
13
+ },
15
14
  };
16
15
 
17
16
  describe('PriceInput', () => {
@@ -34,14 +33,23 @@ describe('PriceInput', () => {
34
33
  const input = screen.getByRole('textbox', { name: 'Enter price' });
35
34
  fireEvent.change(input, { target: { value: '100' } });
36
35
  expect(onPriceChange).toHaveBeenCalledTimes(1);
36
+ expect(onPriceChange).toHaveBeenCalledWith({
37
+ amountRaw: expect.any(String),
38
+ currency: TEST_CURRENCY,
39
+ });
37
40
  });
38
41
 
39
- it('should not call onPriceChange when the input is 0', () => {
42
+ it('should call onPriceChange with updated price when the input is 0', () => {
40
43
  const onPriceChange = vi.fn();
41
44
  render(<PriceInput {...defaultProps} onPriceChange={onPriceChange} />);
42
45
  const input = screen.getByRole('textbox', { name: 'Enter price' });
46
+ fireEvent.change(input, { target: { value: '100' } });
43
47
  fireEvent.change(input, { target: { value: '0' } });
44
- expect(onPriceChange).toHaveBeenCalledTimes(0);
48
+ expect(onPriceChange).toHaveBeenCalledTimes(2); // Called once for '100', once for '0'
49
+ expect(onPriceChange).toHaveBeenCalledWith({
50
+ amountRaw: '0',
51
+ currency: TEST_CURRENCY,
52
+ });
45
53
  });
46
54
 
47
55
  it('should handle disabled prop', () => {
@@ -1,24 +1,23 @@
1
1
  'use client';
2
2
 
3
3
  import { NumericInput, Text } from '@0xsequence/design-system';
4
- import type { Observable } from '@legendapp/state';
5
- import { use$ } from '@legendapp/state/react';
6
4
  import { useEffect, useRef, useState } from 'react';
7
- import { type Hex, parseUnits } from 'viem';
5
+ import { type Address, parseUnits } from 'viem';
8
6
  import { useAccount } from 'wagmi';
9
- import type { Price } from '../../../../../../types';
7
+ import type { Currency, Price } from '../../../../../../types';
10
8
  import { cn } from '../../../../../../utils';
11
9
  import { useCurrencyBalance } from '../../../../../hooks/useCurrencyBalance';
12
10
  import CurrencyImage from '../currencyImage';
13
11
  import CurrencyOptionsSelect from '../currencyOptionsSelect';
14
12
 
15
13
  type PriceInputProps = {
16
- collectionAddress: Hex;
14
+ collectionAddress: Address;
17
15
  chainId: number;
18
16
  secondCurrencyAsDefault?: boolean;
19
- $price: Observable<Price | undefined>;
17
+ price: Price | undefined;
20
18
  includeNativeCurrency?: boolean;
21
- onPriceChange?: () => void;
19
+ onPriceChange?: (price: Price) => void;
20
+ onCurrencyChange?: (currency: Currency) => void;
22
21
  checkBalance?: {
23
22
  enabled: boolean;
24
23
  callback: (state: boolean) => void;
@@ -29,8 +28,9 @@ type PriceInputProps = {
29
28
  export default function PriceInput({
30
29
  chainId,
31
30
  collectionAddress,
32
- $price,
31
+ price,
33
32
  onPriceChange,
33
+ onCurrencyChange,
34
34
  checkBalance,
35
35
  secondCurrencyAsDefault,
36
36
  includeNativeCurrency,
@@ -38,9 +38,16 @@ export default function PriceInput({
38
38
  }: PriceInputProps) {
39
39
  const { address: accountAddress } = useAccount();
40
40
  const inputRef = useRef<HTMLInputElement>(null);
41
- const currencyDecimals = use$($price.currency.decimals);
42
- const currencyAddress = use$($price.currency.contractAddress);
43
- const priceAmountRaw = use$($price.amountRaw);
41
+ const currency = price?.currency;
42
+ const currencyDecimals = price?.currency?.decimals;
43
+ const currencyAddress = price?.currency?.contractAddress;
44
+ const priceAmountRaw = price?.amountRaw;
45
+
46
+ const handleCurrencyChange = (newCurrency: Currency) => {
47
+ if (price && onCurrencyChange) {
48
+ onCurrencyChange(newCurrency);
49
+ }
50
+ };
44
51
 
45
52
  useEffect(() => {
46
53
  if (inputRef.current) {
@@ -49,7 +56,7 @@ export default function PriceInput({
49
56
  }, []);
50
57
 
51
58
  const { data: balance, isSuccess: isBalanceSuccess } = useCurrencyBalance({
52
- currencyAddress: currencyAddress as undefined | Hex,
59
+ currencyAddress: currencyAddress as undefined | Address,
53
60
  chainId,
54
61
  userAddress: accountAddress,
55
62
  });
@@ -70,35 +77,42 @@ export default function PriceInput({
70
77
 
71
78
  // Handle currency changes and adjust the raw amount accordingly
72
79
  useEffect(() => {
73
- if (prevCurrencyDecimals.current !== currencyDecimals && value !== '0') {
80
+ if (
81
+ prevCurrencyDecimals.current !== currencyDecimals &&
82
+ value !== '0' &&
83
+ price &&
84
+ onPriceChange
85
+ ) {
74
86
  try {
75
87
  // If the user has entered a value and the currency decimals have changed,
76
88
  // we need to adjust the raw amount to maintain the same displayed value
77
89
  const parsedAmount = parseUnits(value, Number(currencyDecimals));
78
- $price.amountRaw.set(parsedAmount.toString());
90
+ const updatedPrice = { ...price, amountRaw: parsedAmount.toString() };
79
91
 
80
- if (onPriceChange && parsedAmount !== 0n) {
81
- onPriceChange();
82
- }
92
+ onPriceChange(updatedPrice);
83
93
  } catch {
84
- $price.amountRaw.set('0');
94
+ const updatedPrice = { ...price, amountRaw: '0' };
95
+ onPriceChange(updatedPrice);
85
96
  }
86
97
  }
87
98
 
88
99
  prevCurrencyDecimals.current = currencyDecimals;
89
- }, [currencyDecimals, $price.amountRaw, value, onPriceChange]);
100
+ }, [currencyDecimals, price, value, onPriceChange]);
90
101
 
91
102
  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
92
103
  const newValue = event.target.value;
93
104
  setValue(newValue);
105
+
106
+ if (!price || !onPriceChange) return;
107
+
94
108
  try {
95
109
  const parsedAmount = parseUnits(newValue, Number(currencyDecimals));
96
- $price.amountRaw.set(parsedAmount.toString());
97
- if (onPriceChange && parsedAmount !== 0n) {
98
- onPriceChange();
99
- }
110
+ const updatedPrice = { ...price, amountRaw: parsedAmount.toString() };
111
+
112
+ onPriceChange(updatedPrice);
100
113
  } catch {
101
- $price.amountRaw.set('0');
114
+ const updatedPrice = { ...price, amountRaw: '0' };
115
+ onPriceChange(updatedPrice);
102
116
  }
103
117
  };
104
118
 
@@ -110,7 +124,7 @@ export default function PriceInput({
110
124
  )}
111
125
  >
112
126
  <div className="absolute top-8 left-2 flex items-center">
113
- <CurrencyImage price$={$price} />
127
+ <CurrencyImage price={price} />
114
128
  </div>
115
129
 
116
130
  <div className="[&>label>div>div>.rounded-xl]:h-9 [&>label>div>div>.rounded-xl]:rounded-sm [&>label>div>div>.rounded-xl]:px-2 [&>label]:gap-1">
@@ -123,7 +137,8 @@ export default function PriceInput({
123
137
  labelLocation="top"
124
138
  controls={
125
139
  <CurrencyOptionsSelect
126
- selectedCurrency$={$price.currency}
140
+ selectedCurrency={currency}
141
+ onCurrencyChange={handleCurrencyChange}
127
142
  collectionAddress={collectionAddress}
128
143
  chainId={chainId}
129
144
  secondCurrencyAsDefault={secondCurrencyAsDefault}
@@ -1,12 +1,13 @@
1
- import { observable } from '@legendapp/state';
2
1
  import { fireEvent, render, screen } from '@test';
3
- import { describe, expect, it } from 'vitest';
2
+ import { describe, expect, it, vi } from 'vitest';
4
3
  import QuantityInput from '..';
5
4
 
6
5
  describe('QuantityInput', () => {
7
6
  const defaultProps = {
8
- $quantity: observable<string>('1'),
9
- $invalidQuantity: observable<boolean>(false),
7
+ quantity: '1',
8
+ invalidQuantity: false,
9
+ onQuantityChange: vi.fn(),
10
+ onInvalidQuantityChange: vi.fn(),
10
11
  decimals: 1,
11
12
  maxQuantity: '10',
12
13
  };
@@ -19,51 +20,52 @@ describe('QuantityInput', () => {
19
20
  });
20
21
 
21
22
  it('should display current quantity value', () => {
22
- const quantity$ = observable<string>('5');
23
- render(<QuantityInput {...defaultProps} $quantity={quantity$} />);
23
+ render(<QuantityInput {...defaultProps} quantity="5" />);
24
24
 
25
25
  const input = screen.getByRole('textbox', { name: /Enter quantity/i });
26
26
  expect(input).toHaveValue('5');
27
27
  });
28
28
 
29
29
  it('should handle quantity changes', () => {
30
- const quantity$ = observable<string>('1');
31
- render(<QuantityInput {...defaultProps} $quantity={quantity$} />);
30
+ const onQuantityChange = vi.fn();
31
+ render(
32
+ <QuantityInput {...defaultProps} onQuantityChange={onQuantityChange} />,
33
+ );
32
34
 
33
35
  const input = screen.getByRole('textbox', { name: /Enter quantity/i });
34
36
  fireEvent.change(input, { target: { value: '5' } });
35
37
 
36
- expect(quantity$.get()).toBe('5');
38
+ expect(onQuantityChange).toHaveBeenCalledWith('5');
37
39
  });
38
40
 
39
41
  it('should not allow values greater than maxQuantity', () => {
40
- const quantity$ = observable<string>('1');
41
- const invalidQuantity$ = observable<boolean>(false);
42
+ const onQuantityChange = vi.fn();
43
+ const onInvalidQuantityChange = vi.fn();
42
44
 
43
45
  render(
44
46
  <QuantityInput
45
47
  {...defaultProps}
46
- $quantity={quantity$}
47
- $invalidQuantity={invalidQuantity$}
48
+ onQuantityChange={onQuantityChange}
49
+ onInvalidQuantityChange={onInvalidQuantityChange}
48
50
  />,
49
51
  );
50
52
 
51
53
  const input = screen.getByRole('textbox', { name: /Enter quantity/i });
52
54
  fireEvent.change(input, { target: { value: '15' } });
53
55
 
54
- expect(quantity$.get()).toBe('10'); // Now capped at max instead of invalid
55
- expect(invalidQuantity$.get()).toBe(false);
56
+ expect(onQuantityChange).toHaveBeenCalledWith('10'); // Capped at max
57
+ expect(onInvalidQuantityChange).toHaveBeenCalledWith(false);
56
58
  });
57
59
 
58
60
  it('should handle decimal values correctly based on decimal prop', () => {
59
- const quantity$ = observable<string>('1');
60
- const invalidQuantity$ = observable<boolean>(false);
61
+ const onQuantityChange = vi.fn();
62
+ const onInvalidQuantityChange = vi.fn();
61
63
 
62
64
  render(
63
65
  <QuantityInput
64
66
  {...defaultProps}
65
- $quantity={quantity$}
66
- $invalidQuantity={invalidQuantity$}
67
+ onQuantityChange={onQuantityChange}
68
+ onInvalidQuantityChange={onInvalidQuantityChange}
67
69
  decimals={2}
68
70
  />,
69
71
  );
@@ -71,18 +73,18 @@ describe('QuantityInput', () => {
71
73
  const input = screen.getByRole('textbox', { name: /Enter quantity/i });
72
74
  fireEvent.change(input, { target: { value: '1.234' } });
73
75
 
74
- expect(quantity$.get()).toBe('1.23'); // Should truncate to 2 decimals
76
+ expect(onQuantityChange).toHaveBeenCalledWith('1.23'); // Should truncate to 2 decimals
75
77
  });
76
78
 
77
79
  it('should validate and mark invalid quantities', () => {
78
- const quantity$ = observable<string>('1');
79
- const invalidQuantity$ = observable<boolean>(false);
80
+ const onQuantityChange = vi.fn();
81
+ const onInvalidQuantityChange = vi.fn();
80
82
 
81
83
  render(
82
84
  <QuantityInput
83
85
  {...defaultProps}
84
- $quantity={quantity$}
85
- $invalidQuantity={invalidQuantity$}
86
+ onQuantityChange={onQuantityChange}
87
+ onInvalidQuantityChange={onInvalidQuantityChange}
86
88
  />,
87
89
  );
88
90
 
@@ -90,62 +92,75 @@ describe('QuantityInput', () => {
90
92
 
91
93
  // Test less than min value (should set invalidQuantity to true)
92
94
  fireEvent.change(input, { target: { value: '0' } });
93
- expect(invalidQuantity$.get()).toBe(true);
95
+ expect(onInvalidQuantityChange).toHaveBeenCalledWith(true);
94
96
 
95
97
  // Test empty value (should set invalidQuantity to true)
96
98
  fireEvent.change(input, { target: { value: '' } });
97
- expect(invalidQuantity$.get()).toBe(true);
99
+ expect(onInvalidQuantityChange).toHaveBeenCalledWith(true);
98
100
 
99
101
  // Reset to valid value
100
102
  fireEvent.change(input, { target: { value: '1' } });
101
- expect(invalidQuantity$.get()).toBe(false);
103
+ expect(onInvalidQuantityChange).toHaveBeenCalledWith(false);
102
104
  });
103
105
 
104
106
  it('should increment quantity when increment button is clicked', () => {
105
- const quantity$ = observable<string>('5');
107
+ const onQuantityChange = vi.fn();
106
108
 
107
- render(<QuantityInput {...defaultProps} $quantity={quantity$} />);
109
+ render(
110
+ <QuantityInput
111
+ {...defaultProps}
112
+ quantity="5"
113
+ onQuantityChange={onQuantityChange}
114
+ />,
115
+ );
108
116
 
109
117
  const incrementButton = screen.getAllByRole('button')[1]; // The second button is the increment button
110
118
  fireEvent.click(incrementButton);
111
119
 
112
- expect(quantity$.get()).toBe('6');
120
+ expect(onQuantityChange).toHaveBeenCalledWith('6');
113
121
  });
114
122
 
115
123
  it('should decrement quantity when decrement button is clicked', () => {
116
- const quantity$ = observable<string>('5');
124
+ const onQuantityChange = vi.fn();
117
125
 
118
- render(<QuantityInput {...defaultProps} $quantity={quantity$} />);
126
+ render(
127
+ <QuantityInput
128
+ {...defaultProps}
129
+ quantity="5"
130
+ onQuantityChange={onQuantityChange}
131
+ />,
132
+ );
119
133
 
120
134
  const decrementButton = screen.getAllByRole('button')[0]; // The first button is the decrement button
121
135
  fireEvent.click(decrementButton);
122
136
 
123
- expect(quantity$.get()).toBe('4');
137
+ expect(onQuantityChange).toHaveBeenCalledWith('4');
124
138
  });
125
139
 
126
140
  it('should disable decrement button when quantity is minimum value', () => {
127
- const quantity$ = observable<string>('0.1');
128
-
129
- render(<QuantityInput {...defaultProps} $quantity={quantity$} />);
141
+ render(<QuantityInput {...defaultProps} quantity="0.1" />);
130
142
 
131
143
  const decrementButton = screen.getAllByRole('button')[0]; // The first button is the decrement button
132
144
  expect(decrementButton).toBeDisabled();
133
145
  });
134
146
 
135
147
  it('should disable increment button when quantity is maximum value', () => {
136
- const quantity$ = observable<string>('10');
137
-
138
- render(<QuantityInput {...defaultProps} $quantity={quantity$} />);
148
+ render(<QuantityInput {...defaultProps} quantity="10" />);
139
149
 
140
150
  const incrementButton = screen.getAllByRole('button')[1]; // The second button is the increment button
141
151
  expect(incrementButton).toBeDisabled();
142
152
  });
143
153
 
144
154
  it('should properly handle non-zero decimals for minimum values', () => {
145
- const quantity$ = observable<string>('1');
155
+ const onQuantityChange = vi.fn();
146
156
 
147
157
  render(
148
- <QuantityInput {...defaultProps} $quantity={quantity$} decimals={1} />,
158
+ <QuantityInput
159
+ {...defaultProps}
160
+ quantity="1"
161
+ onQuantityChange={onQuantityChange}
162
+ decimals={1}
163
+ />,
149
164
  );
150
165
 
151
166
  // Set to 1 first
@@ -157,21 +172,18 @@ describe('QuantityInput', () => {
157
172
  fireEvent.click(decrementButton);
158
173
 
159
174
  // For decimals=1, the min value should be 0.1
160
- expect(quantity$.get()).toBe('0.1');
161
-
162
- // Clicking again shouldn't reduce below minimum
163
- fireEvent.click(decrementButton);
164
- expect(quantity$.get()).toBe('0.1');
175
+ expect(onQuantityChange).toHaveBeenCalledWith('0.1');
165
176
  });
166
177
 
167
178
  it('should cap quantity to maxQuantity when incrementing past the maximum', () => {
168
- const quantity$ = observable<string>('9');
179
+ const onQuantityChange = vi.fn();
169
180
  const maxQuantity = '10';
170
181
 
171
182
  render(
172
183
  <QuantityInput
173
184
  {...defaultProps}
174
- $quantity={quantity$}
185
+ quantity="9"
186
+ onQuantityChange={onQuantityChange}
175
187
  maxQuantity={maxQuantity}
176
188
  />,
177
189
  );
@@ -181,23 +193,20 @@ describe('QuantityInput', () => {
181
193
  fireEvent.click(incrementButton);
182
194
 
183
195
  // Value should be 10
184
- expect(quantity$.get()).toBe('10');
185
-
186
- // Click increment again - should still be capped at 10
187
- fireEvent.click(incrementButton);
188
- expect(quantity$.get()).toBe('10');
196
+ expect(onQuantityChange).toHaveBeenCalledWith('10');
189
197
  });
190
198
 
191
199
  it('should set quantity to maxQuantity when direct input exceeds max', () => {
192
- const quantity$ = observable<string>('5');
193
- const invalidQuantity$ = observable<boolean>(false);
200
+ const onQuantityChange = vi.fn();
201
+ const onInvalidQuantityChange = vi.fn();
194
202
  const maxQuantity = '10';
195
203
 
196
204
  render(
197
205
  <QuantityInput
198
206
  {...defaultProps}
199
- $quantity={quantity$}
200
- $invalidQuantity={invalidQuantity$}
207
+ quantity="5"
208
+ onQuantityChange={onQuantityChange}
209
+ onInvalidQuantityChange={onInvalidQuantityChange}
201
210
  maxQuantity={maxQuantity}
202
211
  />,
203
212
  );
@@ -206,7 +215,7 @@ describe('QuantityInput', () => {
206
215
  fireEvent.change(input, { target: { value: '15' } });
207
216
 
208
217
  // Value should be capped at max
209
- expect(quantity$.get()).toBe('10');
210
- expect(invalidQuantity$.get()).toBe(false);
218
+ expect(onQuantityChange).toHaveBeenCalledWith('10');
219
+ expect(onInvalidQuantityChange).toHaveBeenCalledWith(false);
211
220
  });
212
221
  });