@whop/elements-react-native 0.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 (339) hide show
  1. package/README.md +179 -0
  2. package/android/build.gradle +64 -0
  3. package/android/consumer-rules.pro +3 -0
  4. package/android/gradle.properties +5 -0
  5. package/android/src/main/java/com/whop/elements/WhopAddressSuggestionsModule.kt +102 -0
  6. package/android/src/main/java/com/whop/elements/WhopAuthSessionModule.kt +126 -0
  7. package/android/src/main/java/com/whop/elements/WhopElementsPackage.kt +39 -0
  8. package/android/src/main/java/com/whop/elements/WhopPayButtonManager.kt +74 -0
  9. package/android/src/main/java/com/whop/elements/WhopPayButtonPressEvent.kt +17 -0
  10. package/android/src/main/java/com/whop/elements/WhopPayButtonView.kt +178 -0
  11. package/android/src/main/java/com/whop/elements/WhopPlatformPayModule.kt +212 -0
  12. package/assets/whop-wordmark-dark.png +0 -0
  13. package/assets/whop-wordmark-dark@2x.png +0 -0
  14. package/assets/whop-wordmark-dark@3x.png +0 -0
  15. package/assets/whop-wordmark-light.png +0 -0
  16. package/assets/whop-wordmark-light@2x.png +0 -0
  17. package/assets/whop-wordmark-light@3x.png +0 -0
  18. package/ios/Package.swift +59 -0
  19. package/ios/Sources/ElementsReactNative/WhopAddressSuggestionsImpl.swift +189 -0
  20. package/ios/Sources/ElementsReactNative/WhopAuthSessionImpl.swift +106 -0
  21. package/ios/Sources/ElementsReactNative/WhopPayButtonImpl.swift +89 -0
  22. package/ios/Sources/ElementsReactNative/WhopPlatformPayImpl.swift +181 -0
  23. package/ios/generated/WhopAddressSuggestionsModule.h +11 -0
  24. package/ios/generated/WhopAddressSuggestionsModule.mm +46 -0
  25. package/ios/generated/WhopAuthSessionModule.h +11 -0
  26. package/ios/generated/WhopAuthSessionModule.mm +45 -0
  27. package/ios/generated/WhopElementsShims.h +35 -0
  28. package/ios/generated/WhopPayButtonComponentView.h +12 -0
  29. package/ios/generated/WhopPayButtonComponentView.mm +82 -0
  30. package/ios/generated/WhopPlatformPayModule.h +11 -0
  31. package/ios/generated/WhopPlatformPayModule.mm +51 -0
  32. package/lib/module/api/client.js +139 -0
  33. package/lib/module/api/client.js.map +1 -0
  34. package/lib/module/api/client.test.js +137 -0
  35. package/lib/module/api/client.test.js.map +1 -0
  36. package/lib/module/api/types.js +2 -0
  37. package/lib/module/api/types.js.map +1 -0
  38. package/lib/module/controller/actions.js +148 -0
  39. package/lib/module/controller/actions.js.map +1 -0
  40. package/lib/module/controller/actions.test.js +102 -0
  41. package/lib/module/controller/actions.test.js.map +1 -0
  42. package/lib/module/controller/store.js +158 -0
  43. package/lib/module/controller/store.js.map +1 -0
  44. package/lib/module/core/address/country-data.js +1370 -0
  45. package/lib/module/core/address/country-data.js.map +1 -0
  46. package/lib/module/core/address/country-name.js +38 -0
  47. package/lib/module/core/address/country-name.js.map +1 -0
  48. package/lib/module/core/address/country-names.generated.js +249 -0
  49. package/lib/module/core/address/country-names.generated.js.map +1 -0
  50. package/lib/module/core/address/engine.js +245 -0
  51. package/lib/module/core/address/engine.js.map +1 -0
  52. package/lib/module/core/address/engine.test.js +216 -0
  53. package/lib/module/core/address/engine.test.js.map +1 -0
  54. package/lib/module/core/address/form-state.js +409 -0
  55. package/lib/module/core/address/form-state.js.map +1 -0
  56. package/lib/module/core/address/form-state.test.js +516 -0
  57. package/lib/module/core/address/form-state.test.js.map +1 -0
  58. package/lib/module/core/address/places.js +36 -0
  59. package/lib/module/core/address/places.js.map +1 -0
  60. package/lib/module/core/address/required-coverage.test.js +57 -0
  61. package/lib/module/core/address/required-coverage.test.js.map +1 -0
  62. package/lib/module/core/address/suggest.js +102 -0
  63. package/lib/module/core/address/suggest.js.map +1 -0
  64. package/lib/module/core/address/suggest.test.js +156 -0
  65. package/lib/module/core/address/suggest.test.js.map +1 -0
  66. package/lib/module/core/address/use-suggestions.js +33 -0
  67. package/lib/module/core/address/use-suggestions.js.map +1 -0
  68. package/lib/module/core/payments/address-change.js +91 -0
  69. package/lib/module/core/payments/address-change.js.map +1 -0
  70. package/lib/module/core/payments/billing-merge.js +62 -0
  71. package/lib/module/core/payments/billing-merge.js.map +1 -0
  72. package/lib/module/core/payments/browser-info.js +42 -0
  73. package/lib/module/core/payments/browser-info.js.map +1 -0
  74. package/lib/module/core/payments/bt.js +151 -0
  75. package/lib/module/core/payments/bt.js.map +1 -0
  76. package/lib/module/core/payments/bt.test.js +23 -0
  77. package/lib/module/core/payments/bt.test.js.map +1 -0
  78. package/lib/module/core/payments/currency.js +37 -0
  79. package/lib/module/core/payments/currency.js.map +1 -0
  80. package/lib/module/core/payments/detail.js +159 -0
  81. package/lib/module/core/payments/detail.js.map +1 -0
  82. package/lib/module/core/payments/detail.test.js +225 -0
  83. package/lib/module/core/payments/detail.test.js.map +1 -0
  84. package/lib/module/core/payments/errors.js +115 -0
  85. package/lib/module/core/payments/errors.js.map +1 -0
  86. package/lib/module/core/payments/mint.js +89 -0
  87. package/lib/module/core/payments/mint.js.map +1 -0
  88. package/lib/module/core/payments/plan.js +131 -0
  89. package/lib/module/core/payments/plan.js.map +1 -0
  90. package/lib/module/core/payments/refusals.js +17 -0
  91. package/lib/module/core/payments/refusals.js.map +1 -0
  92. package/lib/module/core/payments/secure-fields.js +87 -0
  93. package/lib/module/core/payments/secure-fields.js.map +1 -0
  94. package/lib/module/core/payments/tax-id-catalog.js +616 -0
  95. package/lib/module/core/payments/tax-id-catalog.js.map +1 -0
  96. package/lib/module/core/payments/wallet-contact.js +42 -0
  97. package/lib/module/core/payments/wallet-contact.js.map +1 -0
  98. package/lib/module/core/payments/wallet-contact.test.js +77 -0
  99. package/lib/module/core/payments/wallet-contact.test.js.map +1 -0
  100. package/lib/module/elements/address.js +467 -0
  101. package/lib/module/elements/address.js.map +1 -0
  102. package/lib/module/elements/branding.js +114 -0
  103. package/lib/module/elements/branding.js.map +1 -0
  104. package/lib/module/elements/card-fields/context.js +254 -0
  105. package/lib/module/elements/card-fields/context.js.map +1 -0
  106. package/lib/module/elements/card-fields/fields.js +309 -0
  107. package/lib/module/elements/card-fields/fields.js.map +1 -0
  108. package/lib/module/elements/card-fields/index.js +30 -0
  109. package/lib/module/elements/card-fields/index.js.map +1 -0
  110. package/lib/module/elements/card.js +107 -0
  111. package/lib/module/elements/card.js.map +1 -0
  112. package/lib/module/elements/email.js +84 -0
  113. package/lib/module/elements/email.js.map +1 -0
  114. package/lib/module/elements/payment/declared-fields.js +186 -0
  115. package/lib/module/elements/payment/declared-fields.js.map +1 -0
  116. package/lib/module/elements/payment/index.js +448 -0
  117. package/lib/module/elements/payment/index.js.map +1 -0
  118. package/lib/module/elements/payment/wallet.js +132 -0
  119. package/lib/module/elements/payment/wallet.js.map +1 -0
  120. package/lib/module/elements/tax-id.js +100 -0
  121. package/lib/module/elements/tax-id.js.map +1 -0
  122. package/lib/module/i18n/catalogs.js +103 -0
  123. package/lib/module/i18n/catalogs.js.map +1 -0
  124. package/lib/module/i18n/index.js +45 -0
  125. package/lib/module/i18n/index.js.map +1 -0
  126. package/lib/module/index.js +27 -0
  127. package/lib/module/index.js.map +1 -0
  128. package/lib/module/namespace.js +174 -0
  129. package/lib/module/namespace.js.map +1 -0
  130. package/lib/module/native/index.js +128 -0
  131. package/lib/module/native/index.js.map +1 -0
  132. package/lib/module/package.json +1 -0
  133. package/lib/module/provider.js +56 -0
  134. package/lib/module/provider.js.map +1 -0
  135. package/lib/module/specs/NativeWhopAddressSuggestions.js +6 -0
  136. package/lib/module/specs/NativeWhopAddressSuggestions.js.map +1 -0
  137. package/lib/module/specs/NativeWhopAuthSession.js +10 -0
  138. package/lib/module/specs/NativeWhopAuthSession.js.map +1 -0
  139. package/lib/module/specs/NativeWhopPlatformPay.js +10 -0
  140. package/lib/module/specs/NativeWhopPlatformPay.js.map +1 -0
  141. package/lib/module/specs/WhopPayButtonNativeComponent.ts +22 -0
  142. package/lib/module/theme/appearance.js +85 -0
  143. package/lib/module/theme/appearance.js.map +1 -0
  144. package/lib/module/theme/appearance.test.js +124 -0
  145. package/lib/module/theme/appearance.test.js.map +1 -0
  146. package/lib/module/theme/provider.js +25 -0
  147. package/lib/module/theme/provider.js.map +1 -0
  148. package/lib/module/theme/resolve.js +69 -0
  149. package/lib/module/theme/resolve.js.map +1 -0
  150. package/lib/module/theme/scales.generated.js +419 -0
  151. package/lib/module/theme/scales.generated.js.map +1 -0
  152. package/lib/module/ui/element-frame.js +83 -0
  153. package/lib/module/ui/element-frame.js.map +1 -0
  154. package/lib/module/ui/payment-method-icon.js +69 -0
  155. package/lib/module/ui/payment-method-icon.js.map +1 -0
  156. package/lib/module/ui/primitives.js +266 -0
  157. package/lib/module/ui/primitives.js.map +1 -0
  158. package/lib/module/ui/select.js +281 -0
  159. package/lib/module/ui/select.js.map +1 -0
  160. package/lib/module/ui/suggestions.js +71 -0
  161. package/lib/module/ui/suggestions.js.map +1 -0
  162. package/lib/module/ui/whop-logo.js +42 -0
  163. package/lib/module/ui/whop-logo.js.map +1 -0
  164. package/lib/typescript/package.json +1 -0
  165. package/lib/typescript/src/api/client.d.ts +87 -0
  166. package/lib/typescript/src/api/client.d.ts.map +1 -0
  167. package/lib/typescript/src/api/types.d.ts +175 -0
  168. package/lib/typescript/src/api/types.d.ts.map +1 -0
  169. package/lib/typescript/src/controller/actions.d.ts +42 -0
  170. package/lib/typescript/src/controller/actions.d.ts.map +1 -0
  171. package/lib/typescript/src/controller/store.d.ts +90 -0
  172. package/lib/typescript/src/controller/store.d.ts.map +1 -0
  173. package/lib/typescript/src/core/address/country-data.d.ts +4 -0
  174. package/lib/typescript/src/core/address/country-data.d.ts.map +1 -0
  175. package/lib/typescript/src/core/address/country-name.d.ts +2 -0
  176. package/lib/typescript/src/core/address/country-name.d.ts.map +1 -0
  177. package/lib/typescript/src/core/address/country-names.generated.d.ts +2 -0
  178. package/lib/typescript/src/core/address/country-names.generated.d.ts.map +1 -0
  179. package/lib/typescript/src/core/address/engine.d.ts +97 -0
  180. package/lib/typescript/src/core/address/engine.d.ts.map +1 -0
  181. package/lib/typescript/src/core/address/form-state.d.ts +144 -0
  182. package/lib/typescript/src/core/address/form-state.d.ts.map +1 -0
  183. package/lib/typescript/src/core/address/places.d.ts +23 -0
  184. package/lib/typescript/src/core/address/places.d.ts.map +1 -0
  185. package/lib/typescript/src/core/address/suggest.d.ts +47 -0
  186. package/lib/typescript/src/core/address/suggest.d.ts.map +1 -0
  187. package/lib/typescript/src/core/address/use-suggestions.d.ts +3 -0
  188. package/lib/typescript/src/core/address/use-suggestions.d.ts.map +1 -0
  189. package/lib/typescript/src/core/payments/address-change.d.ts +52 -0
  190. package/lib/typescript/src/core/payments/address-change.d.ts.map +1 -0
  191. package/lib/typescript/src/core/payments/billing-merge.d.ts +39 -0
  192. package/lib/typescript/src/core/payments/billing-merge.d.ts.map +1 -0
  193. package/lib/typescript/src/core/payments/browser-info.d.ts +12 -0
  194. package/lib/typescript/src/core/payments/browser-info.d.ts.map +1 -0
  195. package/lib/typescript/src/core/payments/bt.d.ts +55 -0
  196. package/lib/typescript/src/core/payments/bt.d.ts.map +1 -0
  197. package/lib/typescript/src/core/payments/currency.d.ts +7 -0
  198. package/lib/typescript/src/core/payments/currency.d.ts.map +1 -0
  199. package/lib/typescript/src/core/payments/detail.d.ts +53 -0
  200. package/lib/typescript/src/core/payments/detail.d.ts.map +1 -0
  201. package/lib/typescript/src/core/payments/errors.d.ts +62 -0
  202. package/lib/typescript/src/core/payments/errors.d.ts.map +1 -0
  203. package/lib/typescript/src/core/payments/mint.d.ts +74 -0
  204. package/lib/typescript/src/core/payments/mint.d.ts.map +1 -0
  205. package/lib/typescript/src/core/payments/plan.d.ts +69 -0
  206. package/lib/typescript/src/core/payments/plan.d.ts.map +1 -0
  207. package/lib/typescript/src/core/payments/refusals.d.ts +12 -0
  208. package/lib/typescript/src/core/payments/refusals.d.ts.map +1 -0
  209. package/lib/typescript/src/core/payments/secure-fields.d.ts +33 -0
  210. package/lib/typescript/src/core/payments/secure-fields.d.ts.map +1 -0
  211. package/lib/typescript/src/core/payments/tax-id-catalog.d.ts +481 -0
  212. package/lib/typescript/src/core/payments/tax-id-catalog.d.ts.map +1 -0
  213. package/lib/typescript/src/core/payments/wallet-contact.d.ts +40 -0
  214. package/lib/typescript/src/core/payments/wallet-contact.d.ts.map +1 -0
  215. package/lib/typescript/src/elements/address.d.ts +55 -0
  216. package/lib/typescript/src/elements/address.d.ts.map +1 -0
  217. package/lib/typescript/src/elements/branding.d.ts +18 -0
  218. package/lib/typescript/src/elements/branding.d.ts.map +1 -0
  219. package/lib/typescript/src/elements/card-fields/context.d.ts +67 -0
  220. package/lib/typescript/src/elements/card-fields/context.d.ts.map +1 -0
  221. package/lib/typescript/src/elements/card-fields/fields.d.ts +15 -0
  222. package/lib/typescript/src/elements/card-fields/fields.d.ts.map +1 -0
  223. package/lib/typescript/src/elements/card-fields/index.d.ts +21 -0
  224. package/lib/typescript/src/elements/card-fields/index.d.ts.map +1 -0
  225. package/lib/typescript/src/elements/card.d.ts +21 -0
  226. package/lib/typescript/src/elements/card.d.ts.map +1 -0
  227. package/lib/typescript/src/elements/email.d.ts +31 -0
  228. package/lib/typescript/src/elements/email.d.ts.map +1 -0
  229. package/lib/typescript/src/elements/payment/declared-fields.d.ts +43 -0
  230. package/lib/typescript/src/elements/payment/declared-fields.d.ts.map +1 -0
  231. package/lib/typescript/src/elements/payment/index.d.ts +37 -0
  232. package/lib/typescript/src/elements/payment/index.d.ts.map +1 -0
  233. package/lib/typescript/src/elements/payment/wallet.d.ts +39 -0
  234. package/lib/typescript/src/elements/payment/wallet.d.ts.map +1 -0
  235. package/lib/typescript/src/elements/tax-id.d.ts +41 -0
  236. package/lib/typescript/src/elements/tax-id.d.ts.map +1 -0
  237. package/lib/typescript/src/i18n/catalogs.d.ts +7 -0
  238. package/lib/typescript/src/i18n/catalogs.d.ts.map +1 -0
  239. package/lib/typescript/src/i18n/index.d.ts +17 -0
  240. package/lib/typescript/src/i18n/index.d.ts.map +1 -0
  241. package/lib/typescript/src/index.d.ts +42 -0
  242. package/lib/typescript/src/index.d.ts.map +1 -0
  243. package/lib/typescript/src/namespace.d.ts +36 -0
  244. package/lib/typescript/src/namespace.d.ts.map +1 -0
  245. package/lib/typescript/src/native/index.d.ts +62 -0
  246. package/lib/typescript/src/native/index.d.ts.map +1 -0
  247. package/lib/typescript/src/provider.d.ts +37 -0
  248. package/lib/typescript/src/provider.d.ts.map +1 -0
  249. package/lib/typescript/src/specs/NativeWhopAddressSuggestions.d.ts +13 -0
  250. package/lib/typescript/src/specs/NativeWhopAddressSuggestions.d.ts.map +1 -0
  251. package/lib/typescript/src/specs/NativeWhopAuthSession.d.ts +20 -0
  252. package/lib/typescript/src/specs/NativeWhopAuthSession.d.ts.map +1 -0
  253. package/lib/typescript/src/specs/NativeWhopPlatformPay.d.ts +24 -0
  254. package/lib/typescript/src/specs/NativeWhopPlatformPay.d.ts.map +1 -0
  255. package/lib/typescript/src/specs/WhopPayButtonNativeComponent.d.ts +21 -0
  256. package/lib/typescript/src/specs/WhopPayButtonNativeComponent.d.ts.map +1 -0
  257. package/lib/typescript/src/theme/appearance.d.ts +71 -0
  258. package/lib/typescript/src/theme/appearance.d.ts.map +1 -0
  259. package/lib/typescript/src/theme/provider.d.ts +11 -0
  260. package/lib/typescript/src/theme/provider.d.ts.map +1 -0
  261. package/lib/typescript/src/theme/resolve.d.ts +19 -0
  262. package/lib/typescript/src/theme/resolve.d.ts.map +1 -0
  263. package/lib/typescript/src/theme/scales.generated.d.ts +18 -0
  264. package/lib/typescript/src/theme/scales.generated.d.ts.map +1 -0
  265. package/lib/typescript/src/ui/element-frame.d.ts +32 -0
  266. package/lib/typescript/src/ui/element-frame.d.ts.map +1 -0
  267. package/lib/typescript/src/ui/payment-method-icon.d.ts +21 -0
  268. package/lib/typescript/src/ui/payment-method-icon.d.ts.map +1 -0
  269. package/lib/typescript/src/ui/primitives.d.ts +94 -0
  270. package/lib/typescript/src/ui/primitives.d.ts.map +1 -0
  271. package/lib/typescript/src/ui/select.d.ts +25 -0
  272. package/lib/typescript/src/ui/select.d.ts.map +1 -0
  273. package/lib/typescript/src/ui/suggestions.d.ts +15 -0
  274. package/lib/typescript/src/ui/suggestions.d.ts.map +1 -0
  275. package/lib/typescript/src/ui/whop-logo.d.ts +4 -0
  276. package/lib/typescript/src/ui/whop-logo.d.ts.map +1 -0
  277. package/package.json +121 -0
  278. package/scripts/check-swift.sh +27 -0
  279. package/scripts/codegen-shims.mjs +409 -0
  280. package/scripts/gen-country-names.mjs +58 -0
  281. package/scripts/gen-theme.mjs +124 -0
  282. package/scripts/gen-wordmark.mjs +68 -0
  283. package/scripts/mirror.mjs +112 -0
  284. package/src/api/client.ts +202 -0
  285. package/src/api/types.ts +166 -0
  286. package/src/controller/actions.ts +197 -0
  287. package/src/controller/store.ts +201 -0
  288. package/src/core/address/country-data.ts +927 -0
  289. package/src/core/address/country-name.ts +36 -0
  290. package/src/core/address/country-names.generated.ts +246 -0
  291. package/src/core/address/engine.ts +349 -0
  292. package/src/core/address/form-state.ts +479 -0
  293. package/src/core/address/places.ts +39 -0
  294. package/src/core/address/suggest.ts +153 -0
  295. package/src/core/address/use-suggestions.ts +37 -0
  296. package/src/core/payments/address-change.ts +121 -0
  297. package/src/core/payments/billing-merge.ts +91 -0
  298. package/src/core/payments/browser-info.ts +43 -0
  299. package/src/core/payments/bt.ts +176 -0
  300. package/src/core/payments/currency.ts +54 -0
  301. package/src/core/payments/detail.ts +204 -0
  302. package/src/core/payments/errors.ts +171 -0
  303. package/src/core/payments/mint.ts +130 -0
  304. package/src/core/payments/plan.ts +198 -0
  305. package/src/core/payments/refusals.ts +24 -0
  306. package/src/core/payments/secure-fields.ts +85 -0
  307. package/src/core/payments/tax-id-catalog.ts +320 -0
  308. package/src/core/payments/wallet-contact.ts +56 -0
  309. package/src/elements/address.tsx +570 -0
  310. package/src/elements/branding.tsx +87 -0
  311. package/src/elements/card-fields/context.tsx +310 -0
  312. package/src/elements/card-fields/fields.tsx +281 -0
  313. package/src/elements/card-fields/index.tsx +37 -0
  314. package/src/elements/card.tsx +101 -0
  315. package/src/elements/email.tsx +100 -0
  316. package/src/elements/payment/declared-fields.tsx +238 -0
  317. package/src/elements/payment/index.tsx +497 -0
  318. package/src/elements/payment/wallet.tsx +155 -0
  319. package/src/elements/tax-id.tsx +143 -0
  320. package/src/i18n/catalogs.ts +100 -0
  321. package/src/i18n/index.tsx +46 -0
  322. package/src/index.ts +68 -0
  323. package/src/namespace.tsx +231 -0
  324. package/src/native/index.ts +173 -0
  325. package/src/provider.tsx +76 -0
  326. package/src/specs/NativeWhopAddressSuggestions.ts +14 -0
  327. package/src/specs/NativeWhopAuthSession.ts +21 -0
  328. package/src/specs/NativeWhopPlatformPay.ts +25 -0
  329. package/src/specs/WhopPayButtonNativeComponent.ts +22 -0
  330. package/src/theme/appearance.ts +150 -0
  331. package/src/theme/provider.tsx +28 -0
  332. package/src/theme/resolve.ts +68 -0
  333. package/src/theme/scales.generated.ts +427 -0
  334. package/src/ui/element-frame.tsx +94 -0
  335. package/src/ui/payment-method-icon.tsx +55 -0
  336. package/src/ui/primitives.tsx +269 -0
  337. package/src/ui/select.tsx +255 -0
  338. package/src/ui/suggestions.tsx +69 -0
  339. package/src/ui/whop-logo.tsx +37 -0
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
+ import { TextElement, useBasisTheory } from '@basis-theory/react-native-elements';
5
+ import { fieldLabel, fieldMatches, methodTokenizerKey } from "../../core/payments/detail.js";
6
+ import { tokenizeSecureFields } from "../../core/payments/secure-fields.js";
7
+ import { useT } from "../../i18n/index.js";
8
+ import { alphaStep } from "../../theme/provider.js";
9
+ import { Field, FieldShell, Stack, useFieldStyles } from "../../ui/primitives.js";
10
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
+ /**
12
+ * A method's `required_fields`, rendered generically from what the matrix publishes.
13
+ *
14
+ * A `secure: true` field renders as a Basis Theory hosted text element, so the raw value never
15
+ * exists in this JavaScript. At collect time every secure instance is tokenized into ONE token
16
+ * intent keyed by field name, and the category payload carries `{ token_intent }` — the shape the
17
+ * web element produces and the backend already reads.
18
+ */
19
+ export function useDeclaredFields(entry, country) {
20
+ const fields = useMemo(() => entry?.required_fields ?? [], [entry]);
21
+ // A method's secure fields tokenize under ITS OWN config-block key, which is a different Basis
22
+ // Theory application from the card one — the card key cannot mint token intents at all.
23
+ //
24
+ // The client is NOT constructed here: most methods declare no secure field, and constructing
25
+ // Basis Theory with a missing key makes its SDK show a "Please enter a valid API key" toast to
26
+ // the buyer. `SecureTokenizer` below mounts only when a secure field and a key both exist, and
27
+ // hands the instance back through this ref.
28
+ const btRef = useRef(undefined);
29
+ const [values, setValues] = useState({});
30
+ const [showErrors, setShowErrors] = useState(false);
31
+ const [secureComplete, setSecureComplete] = useState({});
32
+ const secureRefs = useRef({});
33
+
34
+ // Declared fields belong to the METHOD, and this state is keyed by field NAME — so two methods
35
+ // that both declare `bank_account` shared everything: a value typed for one, and its secure
36
+ // completeness, carried into the other and reported it ready before the buyer touched it.
37
+ const entryKey = entry?.type;
38
+ useEffect(() => {
39
+ setValues({});
40
+ setShowErrors(false);
41
+ secureRefs.current = {};
42
+ }, [entryKey]);
43
+ const setValue = useCallback((name, value) => {
44
+ setValues(prev => prev[name] === value ? prev : {
45
+ ...prev,
46
+ [name]: value
47
+ });
48
+ }, []);
49
+ const errorFor = useCallback(field => {
50
+ if (field.secure) return undefined;
51
+ const value = values[field.name] ?? '';
52
+ if (!value.trim()) return 'required';
53
+ // `input_formats` is what a buyer may TYPE; `formats` is the stored electronic value. The
54
+ // typing tolerance wins where the matrix publishes it.
55
+ const patterns = field.input_formats ?? field.formats;
56
+ return fieldMatches(patterns, country, value) ? undefined : 'invalid';
57
+ }, [values, country]);
58
+ const complete = useMemo(() =>
59
+ // A MOUNTED tokenizer field is not a filled one. Keying off the ref meant completeness
60
+ // flipped true the moment the element attached and stayed true after the buyer cleared it,
61
+ // so the form reported itself ready to submit values that were never entered.
62
+ fields.every(field => field.secure ? secureComplete[`${entryKey ?? ''}:${field.name}`] === true : !errorFor(field)), [fields, errorFor, secureComplete, entryKey]);
63
+ const collect = useCallback(async () => {
64
+ const paymentMethod = {};
65
+ const billingExtra = {};
66
+ const secure = {};
67
+ for (const field of fields) {
68
+ if (field.secure) {
69
+ const instance = secureRefs.current[field.name];
70
+ if (instance) secure[field.name] = instance;
71
+ continue;
72
+ }
73
+ const value = (values[field.name] ?? '').trim();
74
+ if (field.kind === 'billing_details') billingExtra[field.name] = value;else paymentMethod[field.name] = value;
75
+ }
76
+ let secureTokenIntent;
77
+ if (Object.keys(secure).length > 0) {
78
+ const key = entry ? methodTokenizerKey(entry) : undefined;
79
+ if (!key) throw new Error('This payment method is missing its tokenizer key');
80
+ // The values live inside the hosted elements, so the SDK has to interpolate them. A raw
81
+ // REST post would serialize the element objects instead of what the buyer typed — that
82
+ // path exists only for the wallet sheets, whose payload really is plain data.
83
+ secureTokenIntent = await tokenizeSecureFields(btRef.current, secure, key);
84
+ }
85
+ return {
86
+ paymentMethod,
87
+ billingExtra,
88
+ secureTokenIntent
89
+ };
90
+ }, [fields, values, entry]);
91
+ return {
92
+ fields,
93
+ values,
94
+ setValue,
95
+ errorFor,
96
+ complete,
97
+ collect,
98
+ showErrors,
99
+ revealErrors: () => setShowErrors(true),
100
+ secureRefs,
101
+ tokenizerKey: fields.some(field => field.secure) && entry ? methodTokenizerKey(entry) : undefined,
102
+ btRef,
103
+ noteSecureComplete: (key, value) => setSecureComplete(previous => previous[key] === value ? previous : {
104
+ ...previous,
105
+ [key]: value
106
+ }),
107
+ secureKey: name => `${entryKey ?? ''}:${name}`
108
+ };
109
+ }
110
+ export function DeclaredFields({
111
+ state
112
+ }) {
113
+ const t = useT();
114
+ if (state.fields.length === 0) return null;
115
+ return /*#__PURE__*/_jsxs(Stack, {
116
+ children: [state.tokenizerKey ? /*#__PURE__*/_jsx(SecureTokenizer, {
117
+ publicKey: state.tokenizerKey,
118
+ btRef: state.btRef
119
+ }) : null, state.fields.map(field => {
120
+ const label = fieldLabel(field.name);
121
+ const code = state.showErrors ? state.errorFor(field) : undefined;
122
+ const error = code === 'required' ? t('Required') : code === 'invalid' ? t("That doesn't look right") : undefined;
123
+ if (field.secure) {
124
+ return /*#__PURE__*/_jsx(SecureField, {
125
+ field: field,
126
+ label: label,
127
+ state: state
128
+ }, field.name);
129
+ }
130
+ return /*#__PURE__*/_jsx(Field, {
131
+ label: label,
132
+ accessibilityLabel: label,
133
+ value: state.values[field.name] ?? '',
134
+ onChangeText: value => state.setValue(field.name, value),
135
+ placeholder: field.placeholder,
136
+ error: error,
137
+ autoCapitalize: "characters",
138
+ autoCorrect: false
139
+ }, field.name);
140
+ })]
141
+ });
142
+ }
143
+
144
+ /** Constructs the Basis Theory client for a method that actually declares a secure field. */
145
+ function SecureTokenizer({
146
+ publicKey,
147
+ btRef
148
+ }) {
149
+ const {
150
+ bt
151
+ } = useBasisTheory(publicKey);
152
+ btRef.current = bt;
153
+ return null;
154
+ }
155
+ function SecureField({
156
+ field,
157
+ label,
158
+ state
159
+ }) {
160
+ const s = useFieldStyles();
161
+ const [focused, setFocused] = useState(false);
162
+ const note = state.noteSecureComplete;
163
+ return /*#__PURE__*/_jsx(FieldShell, {
164
+ label: label,
165
+ focused: focused,
166
+ children: /*#__PURE__*/_jsx(TextElement, {
167
+ btRef: instance => {
168
+ state.secureRefs.current[field.name] = instance;
169
+ if (!instance) note(state.secureKey(field.name), false);
170
+ },
171
+ onChange: event => note(state.secureKey(field.name), event?.complete === true),
172
+ placeholder: field.placeholder,
173
+ placeholderTextColor: alphaStep(s.theme.gray, 10),
174
+ style: {
175
+ color: s.input.color,
176
+ fontSize: s.input.fontSize,
177
+ fontFamily: s.input.fontFamily,
178
+ height: s.theme.tokens.controlHeight - 2,
179
+ padding: 0
180
+ },
181
+ onFocus: () => setFocused(true),
182
+ onBlur: () => setFocused(false)
183
+ })
184
+ });
185
+ }
186
+ //# sourceMappingURL=declared-fields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useCallback","useEffect","useMemo","useRef","useState","TextElement","useBasisTheory","fieldLabel","fieldMatches","methodTokenizerKey","tokenizeSecureFields","useT","alphaStep","Field","FieldShell","Stack","useFieldStyles","jsx","_jsx","jsxs","_jsxs","useDeclaredFields","entry","country","fields","required_fields","btRef","undefined","values","setValues","showErrors","setShowErrors","secureComplete","setSecureComplete","secureRefs","entryKey","type","current","setValue","name","value","prev","errorFor","field","secure","trim","patterns","input_formats","formats","complete","every","collect","paymentMethod","billingExtra","instance","kind","secureTokenIntent","Object","keys","length","key","Error","revealErrors","tokenizerKey","some","noteSecureComplete","previous","secureKey","DeclaredFields","state","t","children","SecureTokenizer","publicKey","map","label","code","error","SecureField","accessibilityLabel","onChangeText","placeholder","autoCapitalize","autoCorrect","bt","s","focused","setFocused","note","onChange","event","placeholderTextColor","theme","gray","style","color","input","fontSize","fontFamily","height","tokens","controlHeight","padding","onFocus","onBlur"],"sourceRoot":"../../../../src","sources":["elements/payment/declared-fields.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,448 @@
1
+ "use strict";
2
+
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
+ import { Platform, Pressable, StyleSheet, Text, View } from 'react-native';
5
+ import { detailTemplate, formatMinorAmount, methodBillingCountries, orderRank, presentMethod } from "../../core/payments/detail.js";
6
+ import { PaymentsRefusalError } from "../../core/payments/refusals.js";
7
+ import { mergeBillingWithCollected } from "../../core/payments/billing-merge.js";
8
+ import { assertCardBilling, validateBillingEmail } from "../../core/payments/mint.js";
9
+ import { useLocale, useT } from "../../i18n/index.js";
10
+ import { usePaymentsState, usePaymentsStore } from "../../namespace.js";
11
+ import { WALLET_TYPE_FOR_PLATFORM, WhopPlatformPay } from "../../native/index.js";
12
+ import { alphaStep, step, useTheme } from "../../theme/provider.js";
13
+ import { ElementFrame } from "../../ui/element-frame.js";
14
+ import { ErrorFace, part, Skeleton, Stack } from "../../ui/primitives.js";
15
+ import { PaymentMethodIcon } from "../../ui/payment-method-icon.js";
16
+ import { CardElement } from "../card.js";
17
+ import { DeclaredFields, useDeclaredFields } from "./declared-fields.js";
18
+ import { mergeWalletContact } from "../../core/payments/wallet-contact.js";
19
+ import { collectWallet, useWalletAvailability, WalletPayButton, walletRequestFor } from "./wallet.js";
20
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
21
+ /**
22
+ * Shows the payment methods offered for this charge and collects the selected one's required
23
+ * fields.
24
+ *
25
+ * The offered set is the matrix filtered by the same eight `presentMethod` gates the web element
26
+ * applies, from the same inputs. The surface is declared `direct_checkout` because an app owns its
27
+ * own presentation the way a first-party document does — and unlike an iframe it can hand a
28
+ * full-page step to the system browser, so `full_page`-only methods stay in the list.
29
+ */
30
+ export function PaymentElement({
31
+ order,
32
+ style,
33
+ fallback,
34
+ onChange,
35
+ onReady,
36
+ onError
37
+ }) {
38
+ const t = useT();
39
+ const locale = useLocale();
40
+ const theme = useTheme();
41
+ const store = usePaymentsStore();
42
+ const charge = usePaymentsState(s => s.charge);
43
+ const accountId = usePaymentsState(s => s.accountId);
44
+ const addressLive = usePaymentsState(s => s.addressLive);
45
+ // Reactive, like addressLive beside it. Read through store.getSnapshot() inside the walletRequest
46
+ // memo this went stale: the store's identity never changes, so clearing an email that had been
47
+ // present left requiresEmail false and the sheet stopped collecting one.
48
+ const buyerEmail = usePaymentsState(s => s.buyerEmail);
49
+ const options = store.getOptions();
50
+ const [entries, setEntries] = useState(null);
51
+ const [failure, setFailure] = useState(null);
52
+ const [selectedType, setSelectedType] = useState(undefined);
53
+ const currency = charge.configured ? charge.currency : undefined;
54
+ const amount = charge.configured ? charge.amount : undefined;
55
+ useEffect(() => {
56
+ if (!accountId || !currency || amount === undefined) return;
57
+ let alive = true;
58
+ setEntries(null);
59
+ store.client.paymentMethodTypes.list({
60
+ account_id: accountId,
61
+ currency,
62
+ amount,
63
+ surface: store.surface
64
+ }).then(page => alive && setEntries(page.data)).catch(err => alive && setFailure({
65
+ message: err.message,
66
+ code: 'PAYMENT_METHODS_FAILED'
67
+ }));
68
+ return () => {
69
+ alive = false;
70
+ };
71
+ }, [accountId, currency, amount, store]);
72
+ const walletEntry = useMemo(() => entries?.find(entry => entry.type === WALLET_TYPE_FOR_PLATFORM), [entries]);
73
+ const walletAvailable = useWalletAvailability(walletEntry);
74
+ const availability = useMemo(() => {
75
+ if (walletAvailable === undefined) return undefined;
76
+ return Platform.OS === 'ios' ? {
77
+ applePay: walletAvailable
78
+ } : {
79
+ googlePay: walletAvailable
80
+ };
81
+ }, [walletAvailable]);
82
+
83
+ // Declared ahead of `offers`, which filters on it. A `const` read from a closure that runs during
84
+ // the same render is a temporal dead zone, not a hoist: this threw
85
+ // "Cannot access 'billingCountry' before initialization" and the element painted no tiles at all.
86
+ const billingCountry = usePaymentsState(s => s.addressCollected?.address?.country);
87
+ const offers = useMemo(() => {
88
+ if (!entries || !charge.configured) return [];
89
+ const filtered = entries.filter(entry => presentMethod(entry, charge.currency, charge.amount, charge.setupFutureUsage, availability, charge.paymentMethodConfiguration, store.surface, billingCountry));
90
+ const ranking = order ?? options.order ?? [];
91
+ return filtered.map((entry, index) => ({
92
+ entry,
93
+ index
94
+ })).sort((a, b) => orderRank(a.entry.type, ranking) - orderRank(b.entry.type, ranking) || a.index - b.index).map(({
95
+ entry
96
+ }) => entry);
97
+ }, [entries, charge, availability, order, options.order, store.surface, billingCountry]);
98
+ const selected = offers.find(entry => entry.type === selectedType);
99
+ const template = selected ? detailTemplate(selected) : undefined;
100
+ const declared = useDeclaredFields(selected, billingCountry);
101
+ const [cardComplete, setCardComplete] = useState(false);
102
+ const [walletCollected, setWalletCollected] = useState(null);
103
+ const [walletError, setWalletError] = useState(null);
104
+ const [walletPresenting, setWalletPresenting] = useState(false);
105
+ const isWallet = template === 'wallet_sheet';
106
+ const isCard = selected?.category === 'card';
107
+ const complete = Boolean(selected) && (isWallet ? Boolean(walletCollected) : isCard ? cardComplete && declared.complete : declared.complete);
108
+
109
+ // A wallet payload is bound to the sheet that produced it, and the sheet was priced. Clearing on
110
+ // the method alone left a token authorized for the OLD amount: `complete` stays true off that
111
+ // stale payload, so the button is disabled and the buyer cannot re-authorize, while confirm
112
+ // submits the old authorization against the new price.
113
+ const walletBinding = `${selectedType ?? ''}|${charge.currency}|${charge.amount}|${options.applePayMerchantId ?? ''}|${options.googlePayMerchantName ?? ''}`;
114
+ useEffect(() => {
115
+ setWalletCollected(null);
116
+ setWalletError(null);
117
+ }, [walletBinding]);
118
+
119
+ // The first offer is selected once the list settles, so a single-method checkout needs no tap.
120
+ // A re-priced charge re-filters the matrix, and the selected method can drop out of it. Left
121
+ // alone the selection points at a type no tile renders: nothing looks selected and confirm
122
+ // refuses. Fall back to the new first offer.
123
+ useEffect(() => {
124
+ if (offers.length === 0) return;
125
+ if (selectedType && offers.some(entry => entry.type === selectedType)) return;
126
+ setSelectedType(offers[0].type);
127
+ }, [offers, selectedType]);
128
+
129
+ // The entry's per-currency country list is the method's billing-country constraint, and "*"
130
+ // anywhere in it means unrestricted. A mounted address element intersects it with the
131
+ // integrator's own allowedCountries, so a method that only serves a few countries narrows the
132
+ // picker instead of letting the buyer choose one it will refuse.
133
+ const methodCountries = useMemo(() => charge.configured ? methodBillingCountries(selected, charge.currency) : null, [selected, charge]);
134
+ // The controller's mirror of the selection: the confirm dispatcher reads it, and a mounted
135
+ // address element narrows its country selector from it.
136
+ useEffect(() => {
137
+ store.patch({
138
+ selectedType,
139
+ selectedCategory: selected?.category,
140
+ selectedTemplate: template,
141
+ selectedComplete: complete,
142
+ methodCountries
143
+ });
144
+ }, [store, selectedType, selected?.category, template, complete, methodCountries]);
145
+
146
+ // Unmount only, so the mirror never outlives the surface that owns it: a still-mounted address
147
+ // element would otherwise keep narrowing its picker to a method the buyer can no longer see.
148
+ useEffect(() => () => store.patch({
149
+ selectedType: '',
150
+ selectedCategory: undefined,
151
+ selectedTemplate: undefined,
152
+ selectedComplete: false,
153
+ methodCountries: null
154
+ }), [store]);
155
+ const latestChange = useRef(onChange);
156
+ latestChange.current = onChange;
157
+ useEffect(() => {
158
+ latestChange.current?.({
159
+ complete,
160
+ type: selected?.type,
161
+ supportsBuyerFee: selected?.supports_buyer_fee,
162
+ method: selected ? {
163
+ type: selected.type,
164
+ category: selected.category,
165
+ template: detailTemplate(selected),
166
+ display_name: selected.display_name
167
+ } : undefined
168
+ });
169
+ }, [complete, selected]);
170
+ const walletRequest = useMemo(() => {
171
+ if (!selected || !isWallet || !charge.configured) return null;
172
+ return walletRequestFor(selected, {
173
+ currency: charge.currency,
174
+ amount: charge.amount,
175
+ merchantName: options.googlePayMerchantName ?? 'Whop',
176
+ applePayMerchantId: options.applePayMerchantId,
177
+ requiresBillingAddress: !addressLive,
178
+ requiresEmail: !buyerEmail
179
+ });
180
+ }, [selected, isWallet, charge, options, addressLive, buyerEmail]);
181
+ const collect = useCallback(async input => {
182
+ if (!selected) {
183
+ throw new PaymentsRefusalError('NO_COLLECTION_SURFACE', 'No payment method is selected');
184
+ }
185
+ if (isWallet) {
186
+ if (!walletCollected) {
187
+ throw new PaymentsRefusalError('WALLET_UNAVAILABLE', 'Tap the wallet button to authorize the payment before confirming');
188
+ }
189
+ // The sheet is asked for an email and a billing address exactly when no element is mounted
190
+ // to supply them, so its answers must be folded in BEFORE validation. Validating first
191
+ // rejected a buyer who had just typed their email into Apple Pay.
192
+ return {
193
+ paymentMethod: walletCollected.paymentMethod,
194
+ billingDetails: validateBillingEmail(mergeWalletContact(input?.billingDetails, walletCollected.contact))
195
+ };
196
+ }
197
+ const billingDetails = validateBillingEmail(input?.billingDetails);
198
+ if (!declared.complete) {
199
+ declared.revealErrors();
200
+ throw new PaymentsRefusalError('NO_COLLECTION_SURFACE', 'Complete the required fields for this method');
201
+ }
202
+ const values = await declared.collect();
203
+ if (isCard) {
204
+ // The address element supplies the billing NAME, and createConfirmationToken merges it
205
+ // only after this returns. Asserting against the seeded bag therefore rejected the
206
+ // default checkout — an AddressElement and a PaymentElement with no explicit
207
+ // billingDetails — for a name the form had already collected.
208
+ const settled = store.getSnapshot();
209
+ const withAddress = settled.addressLive ? mergeBillingWithCollected(billingDetails, settled.addressCollected) ?? billingDetails : billingDetails;
210
+ assertCardBilling(withAddress);
211
+ // The card tile mounts its own CardElement, which registers under `card`. Reaching it by
212
+ // kind is required: `liveSurface()` prefers `payment`, which is this very surface.
213
+ const cardSurface = store.surfaceOf('card');
214
+ if (!cardSurface) {
215
+ throw new PaymentsRefusalError('NO_COLLECTION_SURFACE', 'The card fields are not ready');
216
+ }
217
+ const collected = await cardSurface.collect({
218
+ billingDetails: withAddress
219
+ });
220
+ return {
221
+ paymentMethod: {
222
+ ...collected.paymentMethod,
223
+ ...values.paymentMethod
224
+ },
225
+ billingDetails: collected.billingDetails,
226
+ billingExtra: values.billingExtra
227
+ };
228
+ }
229
+ const categoryPayload = {
230
+ ...values.paymentMethod
231
+ };
232
+ if (values.secureTokenIntent) categoryPayload.token_intent = values.secureTokenIntent;
233
+ return {
234
+ paymentMethod: {
235
+ type: selected.type,
236
+ category: selected.category,
237
+ [selected.category]: categoryPayload
238
+ },
239
+ billingDetails,
240
+ billingExtra: values.billingExtra
241
+ };
242
+ }, [selected, isWallet, isCard, walletCollected, declared, store]);
243
+
244
+ /**
245
+ * The sheet's own verdict settles at tokenization, not at confirm.
246
+ *
247
+ * Holding it open until the server answers needs the deferred-conclusion rail the composed
248
+ * checkout arms; a standalone payment element has no such rail on the web either, and its
249
+ * confirm is server-side and unobservable from here. A refused confirm therefore surfaces in the
250
+ * app's own UI rather than in the sheet.
251
+ */
252
+ const presentWallet = useCallback(async () => {
253
+ if (!selected || !walletRequest || walletPresenting) return;
254
+ setWalletError(null);
255
+ setWalletPresenting(true);
256
+ try {
257
+ setWalletCollected(await collectWallet(selected, walletRequest));
258
+ WhopPlatformPay.complete(true);
259
+ } catch (err) {
260
+ WhopPlatformPay.complete(false);
261
+ const refused = err instanceof PaymentsRefusalError && err.code === 'WALLET_UNAVAILABLE';
262
+ // A dismissal is an outcome, not a failure.
263
+ if (!refused) setWalletError(err instanceof Error ? err.message : String(err));
264
+ } finally {
265
+ setWalletPresenting(false);
266
+ }
267
+ }, [selected, walletRequest, walletPresenting]);
268
+
269
+ // The payment element owns the selection, so it registers ahead of a bare card unit.
270
+ const latestCollect = useRef(collect);
271
+ latestCollect.current = collect;
272
+ useEffect(() => store.registerSurface({
273
+ kind: 'payment',
274
+ collect: input => latestCollect.current(input)
275
+ }), [store]);
276
+ const ready = entries !== null && (walletEntry === undefined || walletAvailable !== undefined);
277
+ return /*#__PURE__*/_jsx(ElementFrame, {
278
+ style: style,
279
+ fallback: fallback,
280
+ skeleton: /*#__PURE__*/_jsxs(Stack, {
281
+ children: [/*#__PURE__*/_jsx(Skeleton, {
282
+ height: 56
283
+ }), /*#__PURE__*/_jsx(Skeleton, {
284
+ height: 56
285
+ }), /*#__PURE__*/_jsx(Skeleton, {
286
+ height: 56
287
+ })]
288
+ }),
289
+ ready: ready,
290
+ error: failure,
291
+ onReady: onReady,
292
+ onError: onError,
293
+ children: offers.length === 0 && entries !== null ? /*#__PURE__*/_jsx(View, {
294
+ style: {
295
+ padding: theme.tokens.spacing * 4,
296
+ borderRadius: theme.tokens.radius,
297
+ backgroundColor: alphaStep(theme.gray, 2)
298
+ },
299
+ children: /*#__PURE__*/_jsx(Text, {
300
+ style: {
301
+ color: step(theme.gray, 11),
302
+ fontSize: theme.tokens.fontSize
303
+ },
304
+ children: t('No payment methods are available')
305
+ })
306
+ }) : /*#__PURE__*/_jsx(Stack, {
307
+ children: offers.map(entry => {
308
+ const active = entry.type === selectedType;
309
+ return /*#__PURE__*/_jsxs(View, {
310
+ children: [/*#__PURE__*/_jsx(MethodTile, {
311
+ entry: entry,
312
+ active: active,
313
+ amountLabel: charge.configured ? formatMinorAmount(charge.amount, charge.currency, locale) : undefined,
314
+ onPress: () => setSelectedType(entry.type)
315
+ }), active ? /*#__PURE__*/_jsxs(View, {
316
+ style: [styles.detail, part(theme, 'whop-PaymentMethodDetail')],
317
+ children: [isCard ? /*#__PURE__*/_jsx(CardElement, {
318
+ onChange: payload => setCardComplete(payload.complete)
319
+ }) : null, /*#__PURE__*/_jsx(DeclaredFields, {
320
+ state: declared
321
+ }), isWallet && walletRequest ? /*#__PURE__*/_jsxs(_Fragment, {
322
+ children: [/*#__PURE__*/_jsx(WalletPayButton, {
323
+ onPress: presentWallet,
324
+ disabled: walletPresenting || Boolean(walletCollected)
325
+ }), walletError ? /*#__PURE__*/_jsx(ErrorFace, {
326
+ message: walletError
327
+ }) : null]
328
+ }) : null]
329
+ }) : null]
330
+ }, entry.type);
331
+ })
332
+ })
333
+ });
334
+ }
335
+ function MethodTile({
336
+ entry,
337
+ active,
338
+ amountLabel,
339
+ onPress
340
+ }) {
341
+ const theme = useTheme();
342
+ return /*#__PURE__*/_jsxs(Pressable, {
343
+ accessibilityRole: "radio",
344
+ accessibilityState: {
345
+ selected: active
346
+ },
347
+ accessibilityLabel: entry.display_name,
348
+ onPress: onPress,
349
+ style: ({
350
+ pressed
351
+ }) => [styles.tile, {
352
+ minHeight: theme.tokens.controlHeight + 12,
353
+ borderRadius: theme.tokens.radius,
354
+ borderWidth: theme.tokens.borderWidth,
355
+ borderColor: active ? step(theme.accent, 8) : alphaStep(theme.gray, 6),
356
+ backgroundColor: pressed ? alphaStep(theme.gray, 2) : step(theme.gray, 1),
357
+ paddingHorizontal: theme.tokens.spacing * 3
358
+ }, part(theme, 'whop-PaymentMethodTile'), active ? part(theme, 'whop-PaymentMethodRowSelected') : null],
359
+ children: [/*#__PURE__*/_jsx(View, {
360
+ style: [styles.radio, {
361
+ borderColor: active ? step(theme.accent, 9) : alphaStep(theme.gray, 7)
362
+ }],
363
+ children: active ? /*#__PURE__*/_jsx(View, {
364
+ style: [styles.dot, {
365
+ backgroundColor: step(theme.accent, 9)
366
+ }]
367
+ }) : null
368
+ }), /*#__PURE__*/_jsx(PaymentMethodIcon, {
369
+ icons: entry.icons,
370
+ size: 20
371
+ }), /*#__PURE__*/_jsx(Text, {
372
+ numberOfLines: 1,
373
+ style: [{
374
+ flexShrink: 1,
375
+ fontSize: theme.tokens.fontSize,
376
+ fontFamily: theme.tokens.fontFamily,
377
+ color: step(theme.gray, 12)
378
+ }, part(theme, 'whop-MethodTileLabel')],
379
+ children: entry.display_name
380
+ }), /*#__PURE__*/_jsx(View, {
381
+ style: styles.spacer
382
+ }), entry.category === 'card' && !active ? /*#__PURE__*/_jsx(BrandStrip, {
383
+ networks: entry.card?.networks
384
+ }) : null, amountLabel ? /*#__PURE__*/_jsx(Text, {
385
+ style: {
386
+ fontSize: theme.tokens.labelFontSize,
387
+ color: step(theme.gray, 11)
388
+ },
389
+ children: amountLabel
390
+ }) : null]
391
+ });
392
+ }
393
+
394
+ /** The card row's accepted-network art. API art only: an entry without networks renders nothing,
395
+ * the same rule the card fields follow. Tiles overlap left-under-right with the first on top,
396
+ * which is the web strip's stacking without its mask moat (React Native has no mask). */
397
+ function BrandStrip({
398
+ networks
399
+ }) {
400
+ const strip = (networks ?? []).slice(0, BRAND_STRIP_TILES);
401
+ if (strip.length === 0) return null;
402
+ return /*#__PURE__*/_jsx(View, {
403
+ style: styles.row,
404
+ children: strip.map((network, index) => /*#__PURE__*/_jsx(View, {
405
+ style: {
406
+ marginLeft: index > 0 ? -8 : 0,
407
+ zIndex: strip.length - index
408
+ },
409
+ children: /*#__PURE__*/_jsx(PaymentMethodIcon, {
410
+ icons: network.icons,
411
+ size: 19
412
+ })
413
+ }, network.brand))
414
+ });
415
+ }
416
+ const BRAND_STRIP_TILES = 4;
417
+ const styles = StyleSheet.create({
418
+ tile: {
419
+ flexDirection: 'row',
420
+ alignItems: 'center',
421
+ gap: 12
422
+ },
423
+ row: {
424
+ flexDirection: 'row',
425
+ alignItems: 'center'
426
+ },
427
+ spacer: {
428
+ flex: 1
429
+ },
430
+ radio: {
431
+ width: 18,
432
+ height: 18,
433
+ borderRadius: 9,
434
+ borderWidth: 1.5,
435
+ alignItems: 'center',
436
+ justifyContent: 'center'
437
+ },
438
+ dot: {
439
+ width: 8,
440
+ height: 8,
441
+ borderRadius: 4
442
+ },
443
+ detail: {
444
+ paddingTop: 12,
445
+ gap: 12
446
+ }
447
+ });
448
+ //# sourceMappingURL=index.js.map