tf-checkout-react-native 2.0.0-beta.0 → 2.0.0-beta.11

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 (71) hide show
  1. package/README.md +115 -24
  2. package/dist/index.d.mts +8195 -282
  3. package/dist/index.d.ts +8195 -282
  4. package/dist/index.js +32346 -7001
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +32586 -7128
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +23 -11
  9. package/scripts/build-seat-map.mjs +31 -0
  10. package/scripts/seat-map-entry.jsx +22 -0
  11. package/scripts/verify-discussion-support.cjs +131 -0
  12. package/src/CardInput.tsx +64 -3
  13. package/src/EmbeddedCheckout.tsx +140 -38
  14. package/src/auth/AuthModal.tsx +186 -9
  15. package/src/auth/EmailCodeForm.tsx +91 -0
  16. package/src/auth/RegisterForm.tsx +91 -5
  17. package/src/auth/TwoFactorForm.tsx +74 -0
  18. package/src/auth/index.ts +4 -0
  19. package/src/configure.ts +19 -14
  20. package/src/confirmer.ts +112 -20
  21. package/src/generated/seatMapWidget.ts +3 -0
  22. package/src/index.tsx +1 -1
  23. package/src/sections/Accommodation.tsx +57 -0
  24. package/src/sections/AccountDeletion.tsx +347 -0
  25. package/src/sections/AccountEmailEnrichment.tsx +122 -0
  26. package/src/sections/AccountInformation.tsx +139 -0
  27. package/src/sections/AccountPaymentPlan.tsx +105 -0
  28. package/src/sections/AccountRewards.tsx +108 -0
  29. package/src/sections/AddOns.tsx +99 -148
  30. package/src/sections/BillingInfo.tsx +80 -78
  31. package/src/sections/Bundles.tsx +467 -0
  32. package/src/sections/EventDiscussionView.tsx +655 -0
  33. package/src/sections/NotificationPreferences.tsx +244 -0
  34. package/src/sections/OrderSummary.tsx +29 -2
  35. package/src/sections/Passes.tsx +177 -0
  36. package/src/sections/Payment.tsx +170 -53
  37. package/src/sections/PhoneAuthentication.tsx +371 -0
  38. package/src/sections/PostReaction.tsx +122 -0
  39. package/src/sections/ProfileSettings.tsx +446 -0
  40. package/src/sections/Rewards.tsx +320 -0
  41. package/src/sections/SeatMap.tsx +225 -0
  42. package/src/sections/SeatsIoMap.tsx +110 -0
  43. package/src/sections/Streaming.tsx +278 -0
  44. package/src/sections/TicketChange.tsx +379 -0
  45. package/src/sections/TicketGift.tsx +206 -0
  46. package/src/sections/TicketRefund.tsx +104 -0
  47. package/src/sections/Tickets.tsx +289 -208
  48. package/src/sections/Trips.tsx +87 -0
  49. package/src/sections/WaiverSigning.tsx +429 -0
  50. package/src/sections/billing/PhoneIdentity.tsx +169 -0
  51. package/src/sections/billing/TicketHoldersCard.tsx +4 -0
  52. package/src/sections/discussion/CommentImages.tsx +366 -0
  53. package/src/sections/discussion/SwipeReply.tsx +88 -0
  54. package/src/sections/index.ts +46 -0
  55. package/src/sections/rewards/RewardsLadder.tsx +167 -0
  56. package/src/sections/rewards/RewardsTree.tsx +117 -0
  57. package/src/storage.ts +8 -9
  58. package/src/ui/CheckoutProvider.tsx +51 -15
  59. package/src/ui/CustomFields.tsx +48 -12
  60. package/src/ui/Field.tsx +21 -3
  61. package/src/ui/Frozen.tsx +22 -0
  62. package/src/ui/InstallmentPicker.tsx +15 -18
  63. package/src/ui/PaymentMethods.tsx +6 -3
  64. package/src/ui/ProviderPages.tsx +214 -0
  65. package/src/ui/QuantitySelect.tsx +28 -3
  66. package/src/ui/Select.tsx +4 -1
  67. package/src/ui/SignaturePad.tsx +218 -0
  68. package/src/ui/index.ts +3 -0
  69. package/src/ui/primitives.tsx +13 -2
  70. package/src/ui/useAccountT.ts +16 -0
  71. package/src/useCheckout.ts +3 -1
package/src/confirmer.ts CHANGED
@@ -10,11 +10,8 @@
10
10
  * flows from the mounted `<CardInput/>` (`<CardField/>`) into `confirmPayment`
11
11
  * natively — there is no element to register the way web does.
12
12
  *
13
- * Deferred (optional ports, left unimplemented — the engine falls back to a
14
- * typed "unsupported gateway" for them): WebView-based rails — Razorpay / PayPal
15
- * / Stripe redirect methods (`providerPage`, `createRedirectPaymentMethod`) and
16
- * Xendit tokenization (`tokenizeXenditCard`). They need `react-native-webview`,
17
- * which this package injects rather than depends on; wiring them is a follow-up.
13
+ * CheckoutProvider owns provider-page windows for PayPal, Razorpay, Xendit and
14
+ * Stripe redirect rails. Imperative hosts supply their own providerPage port.
18
15
  */
19
16
  import { Linking } from 'react-native'
20
17
  import {
@@ -29,10 +26,14 @@ import {
29
26
  type BillingDetails,
30
27
  } from '@stripe/stripe-react-native'
31
28
 
32
- import type {
33
- CheckoutBilling,
34
- CheckoutPorts,
35
- PaymentConfirmer,
29
+ import {
30
+ nativeStripeErrorOutcome,
31
+ confirmedStripeIntentStatus,
32
+ paymentProviderError,
33
+ type CheckoutBilling,
34
+ type CheckoutPorts,
35
+ type NativeStripeErrorLike,
36
+ type PaymentConfirmer,
36
37
  } from 'tf-checkout-shared'
37
38
 
38
39
  /** `CheckoutBilling` → the native SDK's `BillingDetails`. Mirrors the web
@@ -55,6 +56,18 @@ const toBillingDetails = (billing: CheckoutBilling): BillingDetails => ({
55
56
  const failed = (message: string | undefined, fallback: string): Error =>
56
57
  new Error(message || fallback)
57
58
 
59
+ /** A stripe-react-native error as the error the engine classifies: only an
60
+ * explicit decline or cancel lets the checkout reset
61
+ * (`nativeStripeErrorOutcome`). */
62
+ const stripeFailure = (
63
+ error: NativeStripeErrorLike & { message?: string },
64
+ fallback: string
65
+ ): Error =>
66
+ paymentProviderError(error.message || fallback, nativeStripeErrorOutcome(error), {
67
+ type: error.type,
68
+ code: error.stripeErrorCode ?? error.code,
69
+ })
70
+
58
71
  /**
59
72
  * The confirmer every `useCheckout`/`<CardInput/>` binds to. `init()` is
60
73
  * idempotent per key so an event on a connected Stripe account re-initializes
@@ -62,6 +75,8 @@ const failed = (message: string | undefined, fallback: string): Error =>
62
75
  */
63
76
  export const createRnStripeConfirmer = (): PaymentConfirmer => {
64
77
  let initKey: string | null = null
78
+ let accountKey: string | null = null
79
+ const listeners = new Set<() => void>()
65
80
 
66
81
  return {
67
82
  init: async ({ publishableKey, accountId, merchantIdentifier, urlScheme }) => {
@@ -74,6 +89,18 @@ export const createRnStripeConfirmer = (): PaymentConfirmer => {
74
89
  ...(urlScheme ? { urlScheme } : {}),
75
90
  })
76
91
  initKey = key
92
+ accountKey = `${publishableKey}:${accountId ?? ''}`
93
+ listeners.forEach((listener) => listener())
94
+ },
95
+
96
+ // `publishableKey:accountId`, the shape `bundleConfirmerKey` expects.
97
+ currentKey: () => accountKey,
98
+
99
+ subscribe: (listener) => {
100
+ listeners.add(listener)
101
+ return () => {
102
+ listeners.delete(listener)
103
+ }
77
104
  },
78
105
 
79
106
  // Native statuses are already the port's PascalCase vocabulary — no normalize.
@@ -87,8 +114,8 @@ export const createRnStripeConfirmer = (): PaymentConfirmer => {
87
114
  paymentMethodType: 'Card',
88
115
  paymentMethodData: { billingDetails: toBillingDetails(billing) },
89
116
  })
90
- if (error) throw failed(error.message, 'Payment failed.')
91
- return paymentIntent?.status
117
+ if (error) throw stripeFailure(error, 'Payment failed.')
118
+ return confirmedStripeIntentStatus(paymentIntent)
92
119
  },
93
120
 
94
121
  confirmApplePay: async (clientSecret, total, currencyCode, merchant) => {
@@ -105,8 +132,8 @@ export const createRnStripeConfirmer = (): PaymentConfirmer => {
105
132
  ],
106
133
  },
107
134
  })
108
- if (error) throw failed(error.message, 'Apple Pay failed.')
109
- return paymentIntent?.status
135
+ if (error) throw stripeFailure(error, 'Apple Pay failed.')
136
+ return confirmedStripeIntentStatus(paymentIntent)
110
137
  },
111
138
 
112
139
  confirmGooglePay: async (clientSecret, total, currencyCode, merchant) => {
@@ -118,8 +145,8 @@ export const createRnStripeConfirmer = (): PaymentConfirmer => {
118
145
  merchantName: merchant.merchantName ?? 'Order',
119
146
  },
120
147
  })
121
- if (error) throw failed(error.message, 'Google Pay failed.')
122
- return paymentIntent?.status
148
+ if (error) throw stripeFailure(error, 'Google Pay failed.')
149
+ return confirmedStripeIntentStatus(paymentIntent)
123
150
  },
124
151
  }
125
152
  }
@@ -130,9 +157,9 @@ export const createRnStripeConfirmer = (): PaymentConfirmer => {
130
157
  * `Linking`. WebView rails are intentionally absent (see file header).
131
158
  */
132
159
  export const createRnPorts = (): Omit<CheckoutPorts, 'confirmer'> => ({
133
- openUrl: (url: string) => {
134
- void Linking.openURL(url)
135
- },
160
+ // The promise is handed back: a URL the device cannot open rejects, and the
161
+ // caller shows its failure (for example "We could not open the payment page").
162
+ openUrl: (url: string) => Linking.openURL(url).then(() => undefined),
136
163
 
137
164
  createCardPaymentMethod: async (billing) => {
138
165
  const { paymentMethod, error } = await createPaymentMethod({
@@ -143,9 +170,74 @@ export const createRnPorts = (): Omit<CheckoutPorts, 'confirmer'> => ({
143
170
  return paymentMethod.id
144
171
  },
145
172
 
173
+ createRedirectPaymentMethod: async (methodType, billing) => {
174
+ const details = toBillingDetails(billing)
175
+ const result = await (() => {
176
+ switch (methodType) {
177
+ case 'klarna':
178
+ return createPaymentMethod({
179
+ paymentMethodType: 'Klarna',
180
+ paymentMethodData: { billingDetails: details },
181
+ })
182
+ case 'afterpay_clearpay':
183
+ return createPaymentMethod({
184
+ paymentMethodType: 'AfterpayClearpay',
185
+ paymentMethodData: { billingDetails: details, shippingDetails: details },
186
+ })
187
+ case 'affirm':
188
+ return createPaymentMethod({
189
+ paymentMethodType: 'Affirm',
190
+ paymentMethodData: { billingDetails: details },
191
+ })
192
+ case 'ideal':
193
+ return createPaymentMethod({
194
+ paymentMethodType: 'Ideal',
195
+ paymentMethodData: { billingDetails: details },
196
+ })
197
+ case 'bancontact':
198
+ return createPaymentMethod({
199
+ paymentMethodType: 'Bancontact',
200
+ paymentMethodData: { billingDetails: details },
201
+ })
202
+ case 'eps':
203
+ return createPaymentMethod({
204
+ paymentMethodType: 'Eps',
205
+ paymentMethodData: { billingDetails: details },
206
+ })
207
+ case 'p24':
208
+ return createPaymentMethod({
209
+ paymentMethodType: 'P24',
210
+ paymentMethodData: { billingDetails: details },
211
+ })
212
+ case 'alipay':
213
+ return createPaymentMethod({ paymentMethodType: 'Alipay' })
214
+ case 'grabpay':
215
+ return createPaymentMethod({
216
+ paymentMethodType: 'GrabPay',
217
+ paymentMethodData: { billingDetails: details },
218
+ })
219
+ case 'cashapp':
220
+ return createPaymentMethod({
221
+ paymentMethodType: 'CashApp',
222
+ paymentMethodData: { billingDetails: details },
223
+ })
224
+ case 'paypal':
225
+ return createPaymentMethod({
226
+ paymentMethodType: 'PayPal',
227
+ paymentMethodData: { billingDetails: details },
228
+ })
229
+ default:
230
+ throw new Error('This payment method is not available on this device.')
231
+ }
232
+ })()
233
+ if (result.error || !result.paymentMethod?.id)
234
+ throw failed(result.error?.message, 'Unable to start this payment method.')
235
+ return result.paymentMethod.id
236
+ },
237
+
146
238
  handleNextAction: async (clientSecret) => {
147
239
  const { error } = await handleNextAction(clientSecret)
148
- if (error) throw failed(error.message, 'Payment failed')
240
+ if (error) throw stripeFailure(error, 'Payment failed')
149
241
  },
150
242
 
151
243
  confirmOxxo: async (clientSecret, billing) => {
@@ -175,6 +267,6 @@ export const createRnPorts = (): Omit<CheckoutPorts, 'confirmer'> => ({
175
267
  paymentMethodType: 'Card',
176
268
  paymentMethodData: { paymentMethodId },
177
269
  })
178
- if (error) throw failed(error.message, 'Payment failed')
270
+ if (error) throw stripeFailure(error, 'Payment failed')
179
271
  },
180
272
  })