@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,106 @@
1
+ import AuthenticationServices
2
+ import UIKit
3
+
4
+ /// The redirect and 3DS surface.
5
+ ///
6
+ /// `ASWebAuthenticationSession` runs the page in a separate process the host app can neither read
7
+ /// nor script, which is why it is the only acceptable answer here: a `WKWebView` showing a PSP's
8
+ /// 3DS challenge would put the issuer's page inside the app's own trust boundary.
9
+ /// `@unchecked Sendable` with a real invariant, not a silencer: React Native may call a Turbo
10
+ /// module off the main thread, so every method here hops to the main queue and the session state
11
+ /// below is read and written only from there — the completion handler included, since
12
+ /// `ASWebAuthenticationSession` does not document which queue it calls back on.
13
+ @objc(WhopAuthSessionImpl)
14
+ public final class WhopAuthSessionImpl: NSObject, @unchecked Sendable {
15
+ private var session: ASWebAuthenticationSession?
16
+ private var anchorProvider: AnchorProvider?
17
+ /// Bumped by every present(). A completion carries the value it was started with, so a late
18
+ /// one can tell whether the state it is about to clear is still its own.
19
+ private var generation = 0
20
+
21
+ @objc public func isAvailable() -> Bool {
22
+ true
23
+ }
24
+
25
+ @objc public func present(
26
+ _ url: String,
27
+ callbackScheme: String?,
28
+ prefersEphemeral: Bool,
29
+ resolve: @escaping @Sendable (Any?) -> Void,
30
+ reject: @escaping @Sendable (String, String) -> Void
31
+ ) {
32
+ guard let target = URL(string: url), target.scheme?.lowercased() == "https" else {
33
+ reject("INVALID_URL", "whop elements: an https URL is required")
34
+ return
35
+ }
36
+
37
+ DispatchQueue.main.async { [weak self] in
38
+ guard let self else { return }
39
+ self.cancel()
40
+ self.generation &+= 1
41
+ let generation = self.generation
42
+
43
+ let session = ASWebAuthenticationSession(
44
+ url: target,
45
+ callbackURLScheme: callbackScheme
46
+ ) { callbackURL, error in
47
+ // Settling and clearing on the main queue keeps this off a race with a concurrent
48
+ // dismiss(), which is the whole basis of the @unchecked Sendable claim above.
49
+ DispatchQueue.main.async { [weak self] in
50
+ // Clear ONLY if this presentation is still the current one. A completion can
51
+ // land after a later present() has already started a new session, and nilling
52
+ // then would drop the live one: dismiss() could no longer cancel the visible
53
+ // browser. Settling is unconditional, because this promise is this
54
+ // presentation's however stale the presentation is.
55
+ if self?.generation == generation {
56
+ self?.session = nil
57
+ self?.anchorProvider = nil
58
+ }
59
+ if let error = error as? ASWebAuthenticationSessionError,
60
+ error.code == .canceledLogin
61
+ {
62
+ // A dismissal is an outcome, not a failure — handleNextAction's poll is the authority.
63
+ resolve(nil)
64
+ return
65
+ }
66
+ if let error {
67
+ reject("AUTH_SESSION_FAILED", error.localizedDescription)
68
+ return
69
+ }
70
+ resolve(callbackURL?.absoluteString)
71
+ }
72
+ }
73
+
74
+ let provider = AnchorProvider()
75
+ self.anchorProvider = provider
76
+ session.presentationContextProvider = provider
77
+ session.prefersEphemeralWebBrowserSession = prefersEphemeral
78
+
79
+ guard session.start() else {
80
+ self.session = nil
81
+ self.anchorProvider = nil
82
+ reject("AUTH_SESSION_FAILED", "whop elements: the system browser could not be presented")
83
+ return
84
+ }
85
+ self.session = session
86
+ }
87
+ }
88
+
89
+ @objc public func dismiss() {
90
+ DispatchQueue.main.async { [weak self] in self?.cancel() }
91
+ }
92
+
93
+ private func cancel() {
94
+ session?.cancel()
95
+ session = nil
96
+ anchorProvider = nil
97
+ }
98
+ }
99
+
100
+ private final class AnchorProvider: NSObject, ASWebAuthenticationPresentationContextProviding {
101
+ func presentationAnchor(for _: ASWebAuthenticationSession) -> ASPresentationAnchor {
102
+ let scenes = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }
103
+ let active = scenes.first { $0.activationState == .foregroundActive } ?? scenes.first
104
+ return active?.windows.first { $0.isKeyWindow } ?? active?.windows.first ?? ASPresentationAnchor()
105
+ }
106
+ }
@@ -0,0 +1,89 @@
1
+ import PassKit
2
+ import UIKit
3
+
4
+ /// `PKPaymentButton` itself. Apple's Human Interface Guidelines require the system control rather
5
+ /// than a drawn imitation, which is the whole reason this element is a native view.
6
+ @objc(WhopPayButtonImpl)
7
+ public final class WhopPayButtonImpl: UIView {
8
+ @objc public var onPayPress: (() -> Void)?
9
+
10
+ private var variant: PKPaymentButtonType = .plain
11
+ private var style: PKPaymentButtonStyle = .automatic
12
+ private var radius: CGFloat = 8
13
+ private var isDisabled = false
14
+ private var button: PKPaymentButton?
15
+
16
+ @objc override public init(frame: CGRect) {
17
+ super.init(frame: frame)
18
+ rebuild()
19
+ }
20
+
21
+ @available(*, unavailable)
22
+ required init?(coder _: NSCoder) {
23
+ fatalError("init(coder:) is unavailable")
24
+ }
25
+
26
+ override public func layoutSubviews() {
27
+ super.layoutSubviews()
28
+ button?.frame = bounds
29
+ }
30
+
31
+ override public var intrinsicContentSize: CGSize {
32
+ CGSize(width: UIView.noIntrinsicMetric, height: 48)
33
+ }
34
+
35
+ @objc public func setVariant(_ value: String) {
36
+ let next: PKPaymentButtonType
37
+ switch value {
38
+ case "buy": next = .buy
39
+ case "checkout": next = .checkout
40
+ case "book": next = .book
41
+ case "subscribe": next = .subscribe
42
+ case "order": next = .order
43
+ // PassKit has no `.pay`; the verb-less Apple Pay mark is `.plain`.
44
+ default: next = .plain
45
+ }
46
+ guard next != variant else { return }
47
+ variant = next
48
+ rebuild()
49
+ }
50
+
51
+ @objc public func setButtonAppearance(_ value: String) {
52
+ let next: PKPaymentButtonStyle
53
+ switch value {
54
+ case "light": next = .white
55
+ case "dark": next = .black
56
+ default: next = .automatic
57
+ }
58
+ guard next != style else { return }
59
+ style = next
60
+ rebuild()
61
+ }
62
+
63
+ @objc public func setCornerRadius(_ value: Double) {
64
+ radius = CGFloat(value)
65
+ button?.cornerRadius = radius
66
+ }
67
+
68
+ @objc public func setDisabled(_ value: Bool) {
69
+ isDisabled = value
70
+ button?.isEnabled = !value
71
+ alpha = value ? 0.5 : 1
72
+ }
73
+
74
+ /// PKPaymentButton takes its type and style at init only, so a prop change is a fresh button.
75
+ private func rebuild() {
76
+ button?.removeFromSuperview()
77
+ let next = PKPaymentButton(paymentButtonType: variant, paymentButtonStyle: style)
78
+ next.cornerRadius = radius
79
+ next.isEnabled = !isDisabled
80
+ next.addTarget(self, action: #selector(handlePress), for: .touchUpInside)
81
+ next.frame = bounds
82
+ addSubview(next)
83
+ button = next
84
+ }
85
+
86
+ @objc private func handlePress() {
87
+ onPayPress?()
88
+ }
89
+ }
@@ -0,0 +1,181 @@
1
+ import Contacts
2
+ import Foundation
3
+ import PassKit
4
+
5
+ /// Apple Pay, through PassKit.
6
+ ///
7
+ /// The web element runs a merchant-validation round trip against whop.com and refuses to render a
8
+ /// button whose sheet is doomed, because a browser must prove the origin. PassKit replaces all of
9
+ /// that with the app's own merchant identifier and on-device certificate, so none of those gates
10
+ /// exist here. What crosses back is `PKPaymentToken.paymentData` — the same bytes the web path
11
+ /// posts to Basis Theory as a token intent.
12
+ /// `@unchecked Sendable` with a real invariant, not a silencer: React Native may call a Turbo
13
+ /// module off the main thread, so every method here hops to the main queue and all mutable state
14
+ /// below is read and written only from there. PassKit's own delegate callbacks arrive on the main
15
+ /// thread too, so the invariant holds end to end.
16
+ @objc(WhopPlatformPayImpl)
17
+ public final class WhopPlatformPayImpl: NSObject, @unchecked Sendable {
18
+ private var controller: PKPaymentAuthorizationController?
19
+ private var pendingResolve: (@Sendable (Any?) -> Void)?
20
+ private var completion: ((PKPaymentAuthorizationResult) -> Void)?
21
+
22
+ @objc public func capability() -> String {
23
+ PKPaymentAuthorizationController.canMakePayments() ? "apple" : "none"
24
+ }
25
+
26
+ @objc public func canPay(
27
+ _ configJson: String,
28
+ resolve: @escaping @Sendable (Any?) -> Void,
29
+ reject: @escaping @Sendable (String, String) -> Void
30
+ ) {
31
+ guard let config: SheetConfig = decode(configJson) else {
32
+ reject("INVALID_CONFIG", "whop elements: could not decode the wallet config")
33
+ return
34
+ }
35
+ let networks = config.networks.compactMap(Self.network(from:))
36
+ resolve(PKPaymentAuthorizationController.canMakePayments(usingNetworks: networks))
37
+ }
38
+
39
+ @objc public func present(
40
+ _ requestJson: String,
41
+ resolve: @escaping @Sendable (Any?) -> Void,
42
+ reject: @escaping @Sendable (String, String) -> Void
43
+ ) {
44
+ guard let request: SheetRequest = decode(requestJson) else {
45
+ reject("INVALID_REQUEST", "whop elements: could not decode the wallet request")
46
+ return
47
+ }
48
+
49
+ let payment = PKPaymentRequest()
50
+ payment.merchantIdentifier = request.merchantIdentifier
51
+ payment.countryCode = request.countryCode
52
+ payment.currencyCode = request.currencyCode.uppercased()
53
+ payment.merchantCapabilities = .threeDSecure
54
+ payment.supportedNetworks = request.networks.compactMap(Self.network(from:))
55
+ payment.requiredBillingContactFields = request.requiresBillingAddress ? [.postalAddress, .name] : [.name]
56
+ if request.requiresEmail { payment.requiredShippingContactFields = [.emailAddress] }
57
+ payment.paymentSummaryItems = request.lineItems.map {
58
+ PKPaymentSummaryItem(label: $0.label, amount: NSDecimalNumber(string: $0.amount))
59
+ }
60
+
61
+ DispatchQueue.main.async { [weak self] in
62
+ guard let self else { return }
63
+ let controller = PKPaymentAuthorizationController(paymentRequest: payment)
64
+ controller.delegate = self
65
+ self.controller = controller
66
+ self.pendingResolve = resolve
67
+ controller.present { presented in
68
+ guard !presented else { return }
69
+ self.pendingResolve = nil
70
+ self.controller = nil
71
+ reject("SHEET_UNAVAILABLE", "whop elements: the Apple Pay sheet could not be presented")
72
+ }
73
+ }
74
+ }
75
+
76
+ /// The sheet's verdict follows the CONFIRM outcome, not the tokenization — a refused confirm has
77
+ /// to land in-sheet as a failure rather than after a checkmark.
78
+ @objc public func complete(_ success: Bool) {
79
+ DispatchQueue.main.async { [weak self] in
80
+ guard let self, let completion = self.completion else { return }
81
+ self.completion = nil
82
+ completion(PKPaymentAuthorizationResult(status: success ? .success : .failure, errors: nil))
83
+ }
84
+ }
85
+
86
+ private func decode<T: Decodable>(_ json: String) -> T? {
87
+ guard let data = json.data(using: .utf8) else { return nil }
88
+ return try? JSONDecoder().decode(T.self, from: data)
89
+ }
90
+
91
+ private static func network(from raw: String) -> PKPaymentNetwork? {
92
+ switch raw.lowercased() {
93
+ case "visa": return .visa
94
+ case "mastercard", "master-card": return .masterCard
95
+ case "amex", "american-express": return .amex
96
+ case "discover": return .discover
97
+ case "jcb": return .JCB
98
+ case "maestro": return .maestro
99
+ case "elo": return .elo
100
+ case "mir": return .mir
101
+ case "cartes-bancaires", "cartesbancaires": return .cartesBancaires
102
+ default: return nil
103
+ }
104
+ }
105
+ }
106
+
107
+ extension WhopPlatformPayImpl: PKPaymentAuthorizationControllerDelegate {
108
+ public func paymentAuthorizationController(
109
+ _: PKPaymentAuthorizationController,
110
+ didAuthorizePayment payment: PKPayment,
111
+ handler: @escaping (PKPaymentAuthorizationResult) -> Void
112
+ ) {
113
+ completion = handler
114
+ let resolve = pendingResolve
115
+ pendingResolve = nil
116
+ resolve?(Self.envelope(for: payment))
117
+ }
118
+
119
+ /// The token PLUS the contact fields the sheet collected.
120
+ ///
121
+ /// Apple gathers these only because `present` asked for them, and it asks precisely when no
122
+ /// email or address element is mounted — so they are the only copy that exists. Returning bare
123
+ /// `paymentData` discarded them, and the mint then refused a buyer who had just typed their
124
+ /// email into the sheet.
125
+ private static func envelope(for payment: PKPayment) -> String {
126
+ let raw = String(data: payment.token.paymentData, encoding: .utf8)
127
+ var bag: [String: Any] = [:]
128
+ if let raw { bag["paymentData"] = raw }
129
+ if let email = payment.shippingContact?.emailAddress ?? payment.billingContact?.emailAddress {
130
+ bag["email"] = email
131
+ }
132
+ if let components = payment.billingContact?.name {
133
+ let name = PersonNameComponentsFormatter.localizedString(from: components, style: .default)
134
+ if !name.isEmpty { bag["name"] = name }
135
+ }
136
+ if let postal = payment.billingContact?.postalAddress {
137
+ var address: [String: String] = [:]
138
+ // CNPostalAddress.street is the whole street block, newline separated.
139
+ let street = postal.street.split(separator: "\n").map(String.init)
140
+ if let line1 = street.first, !line1.isEmpty { address["line1"] = line1 }
141
+ if street.count > 1 { address["line2"] = street.dropFirst().joined(separator: " ") }
142
+ if !postal.city.isEmpty { address["city"] = postal.city }
143
+ if !postal.state.isEmpty { address["state"] = postal.state }
144
+ if !postal.postalCode.isEmpty { address["postal_code"] = postal.postalCode }
145
+ if !postal.isoCountryCode.isEmpty { address["country"] = postal.isoCountryCode.uppercased() }
146
+ if !address.isEmpty { bag["address"] = address }
147
+ }
148
+ guard let data = try? JSONSerialization.data(withJSONObject: bag),
149
+ let json = String(data: data, encoding: .utf8)
150
+ else { return raw ?? "" }
151
+ return json
152
+ }
153
+
154
+ public func paymentAuthorizationControllerDidFinish(_ controller: PKPaymentAuthorizationController) {
155
+ controller.dismiss(completion: nil)
156
+ self.controller = nil
157
+ // Dismissed before authorizing: settle the promise so the JS side is never left hanging.
158
+ let resolve = pendingResolve
159
+ pendingResolve = nil
160
+ resolve?(nil)
161
+ }
162
+ }
163
+
164
+ private struct SheetConfig: Decodable {
165
+ let networks: [String]
166
+ }
167
+
168
+ private struct SheetRequest: Decodable {
169
+ struct LineItem: Decodable {
170
+ let label: String
171
+ let amount: String
172
+ }
173
+
174
+ let merchantIdentifier: String
175
+ let countryCode: String
176
+ let currencyCode: String
177
+ let networks: [String]
178
+ let lineItems: [LineItem]
179
+ let requiresBillingAddress: Bool
180
+ let requiresEmail: Bool
181
+ }
@@ -0,0 +1,11 @@
1
+ // GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
2
+ // Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
3
+
4
+ #import <WhopElementsSpec/WhopElementsSpec.h>
5
+
6
+ NS_ASSUME_NONNULL_BEGIN
7
+
8
+ @interface WhopAddressSuggestionsModule : NSObject <NativeWhopAddressSuggestionsSpec>
9
+ @end
10
+
11
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,46 @@
1
+ // GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
2
+ // Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
3
+
4
+ #import "WhopAddressSuggestionsModule.h"
5
+ #import "WhopElementsShims.h"
6
+
7
+ @implementation WhopAddressSuggestionsModule {
8
+ WhopAddressSuggestionsImpl *_impl;
9
+ }
10
+
11
+ // The JS name, explicitly: bare RCT_EXPORT_MODULE() registers under the CLASS name
12
+ // ("WhopAddressSuggestionsModule"), and TurboModuleRegistry then cannot find "WhopAddressSuggestions".
13
+ RCT_EXPORT_MODULE(WhopAddressSuggestions)
14
+
15
+ - (instancetype)init
16
+ {
17
+ if (self = [super init]) {
18
+ _impl = [WhopAddressSuggestionsImpl new];
19
+ }
20
+ return self;
21
+ }
22
+
23
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
24
+ (const facebook::react::ObjCTurboModule::InitParams &)params
25
+ {
26
+ return std::make_shared<facebook::react::NativeWhopAddressSuggestionsSpecJSI>(params);
27
+ }
28
+
29
+ - (NSNumber *)isAvailable
30
+ {
31
+ return @([_impl isAvailable]);
32
+ }
33
+
34
+ - (void)suggest:(NSString *)query resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
35
+ {
36
+ [_impl suggest:query resolve:^(id _Nullable value) { resolve(value); }
37
+ reject:^(NSString *code, NSString *message) { reject(code, message, nil); }];
38
+ }
39
+
40
+ - (void)details:(NSString *)suggestionId resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
41
+ {
42
+ [_impl details:suggestionId resolve:^(id _Nullable value) { resolve(value); }
43
+ reject:^(NSString *code, NSString *message) { reject(code, message, nil); }];
44
+ }
45
+
46
+ @end
@@ -0,0 +1,11 @@
1
+ // GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
2
+ // Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
3
+
4
+ #import <WhopElementsSpec/WhopElementsSpec.h>
5
+
6
+ NS_ASSUME_NONNULL_BEGIN
7
+
8
+ @interface WhopAuthSessionModule : NSObject <NativeWhopAuthSessionSpec>
9
+ @end
10
+
11
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,45 @@
1
+ // GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
2
+ // Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
3
+
4
+ #import "WhopAuthSessionModule.h"
5
+ #import "WhopElementsShims.h"
6
+
7
+ @implementation WhopAuthSessionModule {
8
+ WhopAuthSessionImpl *_impl;
9
+ }
10
+
11
+ // The JS name, explicitly: bare RCT_EXPORT_MODULE() registers under the CLASS name
12
+ // ("WhopAuthSessionModule"), and TurboModuleRegistry then cannot find "WhopAuthSession".
13
+ RCT_EXPORT_MODULE(WhopAuthSession)
14
+
15
+ - (instancetype)init
16
+ {
17
+ if (self = [super init]) {
18
+ _impl = [WhopAuthSessionImpl new];
19
+ }
20
+ return self;
21
+ }
22
+
23
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
24
+ (const facebook::react::ObjCTurboModule::InitParams &)params
25
+ {
26
+ return std::make_shared<facebook::react::NativeWhopAuthSessionSpecJSI>(params);
27
+ }
28
+
29
+ - (NSNumber *)isAvailable
30
+ {
31
+ return @([_impl isAvailable]);
32
+ }
33
+
34
+ - (void)present:(NSString *)url callbackScheme:(NSString * _Nullable)callbackScheme prefersEphemeral:(BOOL)prefersEphemeral resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
35
+ {
36
+ [_impl present:url callbackScheme:callbackScheme prefersEphemeral:prefersEphemeral resolve:^(id _Nullable value) { resolve(value); }
37
+ reject:^(NSString *code, NSString *message) { reject(code, message, nil); }];
38
+ }
39
+
40
+ - (void)dismiss
41
+ {
42
+ [_impl dismiss];
43
+ }
44
+
45
+ @end
@@ -0,0 +1,35 @@
1
+ // GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
2
+ // Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
3
+
4
+ #import <UIKit/UIKit.h>
5
+
6
+ NS_ASSUME_NONNULL_BEGIN
7
+
8
+ @interface WhopPayButtonImpl : UIView
9
+ @property (nonatomic, copy, nullable) void (^onPayPress)(void);
10
+ - (void)setVariant:(NSString * _Nonnull)value;
11
+ - (void)setButtonAppearance:(NSString * _Nonnull)value;
12
+ - (void)setCornerRadius:(double)value;
13
+ - (void)setDisabled:(BOOL)value;
14
+ @end
15
+
16
+ @interface WhopAddressSuggestionsImpl : NSObject
17
+ - (BOOL)isAvailable;
18
+ - (void)suggest:(NSString *)query resolve:(void (^ _Nonnull)(id _Nullable))resolve reject:(void (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull))reject;
19
+ - (void)details:(NSString *)suggestionId resolve:(void (^ _Nonnull)(id _Nullable))resolve reject:(void (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull))reject;
20
+ @end
21
+
22
+ @interface WhopAuthSessionImpl : NSObject
23
+ - (BOOL)isAvailable;
24
+ - (void)present:(NSString *)url callbackScheme:(NSString * _Nullable)callbackScheme prefersEphemeral:(BOOL)prefersEphemeral resolve:(void (^ _Nonnull)(id _Nullable))resolve reject:(void (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull))reject;
25
+ - (void)dismiss;
26
+ @end
27
+
28
+ @interface WhopPlatformPayImpl : NSObject
29
+ - (NSString * _Nonnull)capability;
30
+ - (void)canPay:(NSString *)configJson resolve:(void (^ _Nonnull)(id _Nullable))resolve reject:(void (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull))reject;
31
+ - (void)present:(NSString *)requestJson resolve:(void (^ _Nonnull)(id _Nullable))resolve reject:(void (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull))reject;
32
+ - (void)complete:(BOOL)success;
33
+ @end
34
+
35
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,12 @@
1
+ // GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
2
+ // Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
3
+
4
+ #import <React/RCTViewComponentView.h>
5
+ #import <UIKit/UIKit.h>
6
+
7
+ NS_ASSUME_NONNULL_BEGIN
8
+
9
+ @interface WhopPayButtonComponentView : RCTViewComponentView
10
+ @end
11
+
12
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,82 @@
1
+ // GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
2
+ // Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
3
+
4
+ #import "WhopPayButtonComponentView.h"
5
+ #import "WhopElementsShims.h"
6
+
7
+ #import <React/RCTConversions.h>
8
+ #import <React/RCTFabricComponentsPlugins.h>
9
+
10
+ #import <react/renderer/components/WhopElementsSpec/ComponentDescriptors.h>
11
+ #import <react/renderer/components/WhopElementsSpec/EventEmitters.h>
12
+ #import <react/renderer/components/WhopElementsSpec/Props.h>
13
+ #import <react/renderer/components/WhopElementsSpec/RCTComponentViewHelpers.h>
14
+
15
+ using namespace facebook::react;
16
+
17
+ static NSString *WhopPayButtonVariantToString(WhopPayButtonVariant value)
18
+ {
19
+ return RCTNSStringFromString(toString(value));
20
+ }
21
+
22
+ static NSString *WhopPayButtonButtonAppearanceToString(WhopPayButtonButtonAppearance value)
23
+ {
24
+ return RCTNSStringFromString(toString(value));
25
+ }
26
+
27
+ @interface WhopPayButtonComponentView () <RCTWhopPayButtonViewProtocol>
28
+ @end
29
+
30
+ @implementation WhopPayButtonComponentView {
31
+ WhopPayButtonImpl *_impl;
32
+ }
33
+
34
+ + (ComponentDescriptorProvider)componentDescriptorProvider
35
+ {
36
+ return concreteComponentDescriptorProvider<WhopPayButtonComponentDescriptor>();
37
+ }
38
+
39
+ - (instancetype)initWithFrame:(CGRect)frame
40
+ {
41
+ if (self = [super initWithFrame:frame]) {
42
+ static const auto defaultProps = std::make_shared<const WhopPayButtonProps>();
43
+ _props = defaultProps;
44
+ _impl = [[WhopPayButtonImpl alloc] initWithFrame:frame];
45
+ __weak __typeof(self) weakSelf = self;
46
+ _impl.onPayPress = ^{
47
+ __strong __typeof(weakSelf) strongSelf = weakSelf;
48
+ if (!strongSelf || !strongSelf->_eventEmitter) { return; }
49
+ std::static_pointer_cast<const WhopPayButtonEventEmitter>(strongSelf->_eventEmitter)->onPayPress({});
50
+ };
51
+ self.contentView = _impl;
52
+ }
53
+ return self;
54
+ }
55
+
56
+ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
57
+ {
58
+ const auto &oldViewProps = *std::static_pointer_cast<WhopPayButtonProps const>(_props);
59
+ const auto &newViewProps = *std::static_pointer_cast<WhopPayButtonProps const>(props);
60
+
61
+ if (oldViewProps.variant != newViewProps.variant) {
62
+ [_impl setVariant:WhopPayButtonVariantToString(newViewProps.variant)];
63
+ }
64
+ if (oldViewProps.buttonAppearance != newViewProps.buttonAppearance) {
65
+ [_impl setButtonAppearance:WhopPayButtonButtonAppearanceToString(newViewProps.buttonAppearance)];
66
+ }
67
+ if (oldViewProps.cornerRadius != newViewProps.cornerRadius) {
68
+ [_impl setCornerRadius:newViewProps.cornerRadius];
69
+ }
70
+ if (oldViewProps.disabled != newViewProps.disabled) {
71
+ [_impl setDisabled:newViewProps.disabled];
72
+ }
73
+
74
+ [super updateProps:props oldProps:oldProps];
75
+ }
76
+
77
+ @end
78
+
79
+ Class<RCTComponentViewProtocol> WhopPayButtonCls(void)
80
+ {
81
+ return WhopPayButtonComponentView.class;
82
+ }
@@ -0,0 +1,11 @@
1
+ // GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
2
+ // Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
3
+
4
+ #import <WhopElementsSpec/WhopElementsSpec.h>
5
+
6
+ NS_ASSUME_NONNULL_BEGIN
7
+
8
+ @interface WhopPlatformPayModule : NSObject <NativeWhopPlatformPaySpec>
9
+ @end
10
+
11
+ NS_ASSUME_NONNULL_END