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.
- package/README.md +115 -24
- package/dist/index.d.mts +8195 -282
- package/dist/index.d.ts +8195 -282
- package/dist/index.js +32346 -7001
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +32586 -7128
- package/dist/index.mjs.map +1 -1
- package/package.json +23 -11
- package/scripts/build-seat-map.mjs +31 -0
- package/scripts/seat-map-entry.jsx +22 -0
- package/scripts/verify-discussion-support.cjs +131 -0
- package/src/CardInput.tsx +64 -3
- package/src/EmbeddedCheckout.tsx +140 -38
- package/src/auth/AuthModal.tsx +186 -9
- package/src/auth/EmailCodeForm.tsx +91 -0
- package/src/auth/RegisterForm.tsx +91 -5
- package/src/auth/TwoFactorForm.tsx +74 -0
- package/src/auth/index.ts +4 -0
- package/src/configure.ts +19 -14
- package/src/confirmer.ts +112 -20
- package/src/generated/seatMapWidget.ts +3 -0
- package/src/index.tsx +1 -1
- package/src/sections/Accommodation.tsx +57 -0
- package/src/sections/AccountDeletion.tsx +347 -0
- package/src/sections/AccountEmailEnrichment.tsx +122 -0
- package/src/sections/AccountInformation.tsx +139 -0
- package/src/sections/AccountPaymentPlan.tsx +105 -0
- package/src/sections/AccountRewards.tsx +108 -0
- package/src/sections/AddOns.tsx +99 -148
- package/src/sections/BillingInfo.tsx +80 -78
- package/src/sections/Bundles.tsx +467 -0
- package/src/sections/EventDiscussionView.tsx +655 -0
- package/src/sections/NotificationPreferences.tsx +244 -0
- package/src/sections/OrderSummary.tsx +29 -2
- package/src/sections/Passes.tsx +177 -0
- package/src/sections/Payment.tsx +170 -53
- package/src/sections/PhoneAuthentication.tsx +371 -0
- package/src/sections/PostReaction.tsx +122 -0
- package/src/sections/ProfileSettings.tsx +446 -0
- package/src/sections/Rewards.tsx +320 -0
- package/src/sections/SeatMap.tsx +225 -0
- package/src/sections/SeatsIoMap.tsx +110 -0
- package/src/sections/Streaming.tsx +278 -0
- package/src/sections/TicketChange.tsx +379 -0
- package/src/sections/TicketGift.tsx +206 -0
- package/src/sections/TicketRefund.tsx +104 -0
- package/src/sections/Tickets.tsx +289 -208
- package/src/sections/Trips.tsx +87 -0
- package/src/sections/WaiverSigning.tsx +429 -0
- package/src/sections/billing/PhoneIdentity.tsx +169 -0
- package/src/sections/billing/TicketHoldersCard.tsx +4 -0
- package/src/sections/discussion/CommentImages.tsx +366 -0
- package/src/sections/discussion/SwipeReply.tsx +88 -0
- package/src/sections/index.ts +46 -0
- package/src/sections/rewards/RewardsLadder.tsx +167 -0
- package/src/sections/rewards/RewardsTree.tsx +117 -0
- package/src/storage.ts +8 -9
- package/src/ui/CheckoutProvider.tsx +51 -15
- package/src/ui/CustomFields.tsx +48 -12
- package/src/ui/Field.tsx +21 -3
- package/src/ui/Frozen.tsx +22 -0
- package/src/ui/InstallmentPicker.tsx +15 -18
- package/src/ui/PaymentMethods.tsx +6 -3
- package/src/ui/ProviderPages.tsx +214 -0
- package/src/ui/QuantitySelect.tsx +28 -3
- package/src/ui/Select.tsx +4 -1
- package/src/ui/SignaturePad.tsx +218 -0
- package/src/ui/index.ts +3 -0
- package/src/ui/primitives.tsx +13 -2
- package/src/ui/useAccountT.ts +16 -0
- package/src/useCheckout.ts +3 -1
package/README.md
CHANGED
|
@@ -4,26 +4,40 @@ The TicketFairy checkout for React Native. Drop in one component and you have
|
|
|
4
4
|
ticket selection, add-ons, buyer details, payment, ID verification, and the
|
|
5
5
|
receipt — or compose the sections yourself.
|
|
6
6
|
|
|
7
|
-
Same API as [`tf-checkout-react`](
|
|
7
|
+
Same API as [`tf-checkout-react`](https://github.com/theticketfairy/tf-shared-libraries/blob/main/packages/tf-checkout-react/README.md); the flow,
|
|
8
8
|
validation, and gating rules are literally the same code.
|
|
9
9
|
|
|
10
|
+
The 2.x source is maintained in [`tf-shared-libraries/packages/tf-checkout-react-native`](https://github.com/theticketfairy/tf-shared-libraries/tree/main/packages/tf-checkout-react-native).
|
|
11
|
+
The core is private and bundled into both platform packages. Use React 18+ and
|
|
12
|
+
React Query 5 on web; the native requirements below reflect its supported build.
|
|
13
|
+
Never put a confidential OAuth client secret in browser or mobile code. Public
|
|
14
|
+
checkout integrations use registered SDK client IDs and owned buyer sessions.
|
|
15
|
+
|
|
10
16
|
## Install
|
|
11
17
|
|
|
18
|
+
The 2.0 line is currently a prerelease. Install `@beta` explicitly; the unqualified
|
|
19
|
+
npm package still resolves to stable 1.x until the 2.0 release gates pass. Pin the
|
|
20
|
+
verified exact version in a production app. The current matching pair is
|
|
21
|
+
`2.0.0-beta.9`; see its [registry acceptance record](https://github.com/theticketfairy/tf-shared-libraries/blob/main/docs/releases/2.0.0-beta.9.registry.json).
|
|
22
|
+
The [app integration contract](https://github.com/theticketfairy/tf-shared-libraries/blob/main/docs/integration/app-sdk.md)
|
|
23
|
+
records the shared APIs and remaining deployment/provider acceptance gates.
|
|
24
|
+
|
|
12
25
|
```bash
|
|
13
|
-
npx expo install tf-checkout-react-native \
|
|
26
|
+
npx expo install tf-checkout-react-native@beta \
|
|
14
27
|
@tanstack/react-query \
|
|
15
28
|
@stripe/stripe-react-native \
|
|
16
|
-
react-native-mmkv \
|
|
17
|
-
@react-native-clipboard/clipboard
|
|
29
|
+
react-native-mmkv@3 \
|
|
30
|
+
@react-native-clipboard/clipboard \
|
|
31
|
+
react-native-webview
|
|
18
32
|
```
|
|
19
33
|
|
|
20
34
|
Bare React Native:
|
|
21
35
|
|
|
22
36
|
```bash
|
|
23
|
-
npm install tf-checkout-react-native @tanstack/react-query @stripe/stripe-react-native react-native-mmkv @react-native-clipboard/clipboard
|
|
37
|
+
npm install tf-checkout-react-native@beta @tanstack/react-query @stripe/stripe-react-native react-native-mmkv@3 @react-native-clipboard/clipboard react-native-webview
|
|
24
38
|
```
|
|
25
39
|
|
|
26
|
-
|
|
40
|
+
These are **peer dependencies** on purpose. React contexts and native
|
|
27
41
|
modules must exist exactly once in an app — a second copy of react-query means
|
|
28
42
|
your `<QueryClientProvider>` is invisible to our hooks, and a second Stripe
|
|
29
43
|
means a duplicate pod. As peers there is one copy and no Metro aliasing is ever
|
|
@@ -35,7 +49,7 @@ Everything else — the SDK core, the flow, the UI — ships inside the package.
|
|
|
35
49
|
|
|
36
50
|
- React Native `0.81+` with the New Architecture enabled (required by
|
|
37
51
|
`react-native-mmkv` 3.x)
|
|
38
|
-
- React `19.1+`, Node `20.
|
|
52
|
+
- React `19.1+`, Node `20.19.4+`
|
|
39
53
|
- iOS 15.1+ · Android API 24+ (Stripe SDK minimums)
|
|
40
54
|
- A development build. **Expo Go will not work** — this package uses native
|
|
41
55
|
modules.
|
|
@@ -62,7 +76,7 @@ npx expo run:ios
|
|
|
62
76
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
63
77
|
import { configureCheckout, EmbeddedCheckout } from 'tf-checkout-react-native'
|
|
64
78
|
|
|
65
|
-
configureCheckout({ env: 'PROD', clientId: '
|
|
79
|
+
configureCheckout({ env: 'PROD', clientId: 'PUBLIC_SDK_CLIENT_ID', clientSecret: '', cookieAuth: true })
|
|
66
80
|
|
|
67
81
|
const queryClient = new QueryClient()
|
|
68
82
|
|
|
@@ -75,24 +89,23 @@ export default function App() {
|
|
|
75
89
|
}
|
|
76
90
|
```
|
|
77
91
|
|
|
78
|
-
`configureCheckout` runs once at app start
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
### Why native defaults to cookie auth
|
|
92
|
+
`configureCheckout` runs once at app start and defaults SDK-owned storage to
|
|
93
|
+
MMKV. Storage survives a relaunch; the backend still validates the restored
|
|
94
|
+
session.
|
|
82
95
|
|
|
83
|
-
|
|
84
|
-
cart lives in the backend session, and a bearer request without a guest header
|
|
85
|
-
gets moved onto a synthetic empty session — so a buyer who reserves tickets and
|
|
86
|
-
then signs in mid-checkout would lose the cart to "The cart is expired". On the
|
|
87
|
-
cookie flow no bearer is minted, the session holding the cart stays put, and the
|
|
88
|
-
rotating `X-TF-ECOMMERCE` ticket is persisted to MMKV.
|
|
96
|
+
### Checkout sessions and account scope
|
|
89
97
|
|
|
90
|
-
|
|
98
|
+
The native wrapper defaults `cookieAuth` to true and disables ambient native
|
|
99
|
+
cookie handling. Owned credentials use the SDK's header-backed session storage.
|
|
100
|
+
Public checkout sign-in preserves the event-bound guest carrier and keeps its
|
|
101
|
+
buyer credential server-side; it does not return a full-account ticket or grant
|
|
102
|
+
private account access. First-party full-account flows explicitly use
|
|
103
|
+
`accountAuth: true`; see the shared identity contract below.
|
|
91
104
|
|
|
92
105
|
### Environments
|
|
93
106
|
|
|
94
107
|
```ts
|
|
95
|
-
configureCheckout({ env: 'STAG', clientId, clientSecret })
|
|
108
|
+
configureCheckout({ env: 'STAG', clientId: 'PUBLIC_SDK_CLIENT_ID', clientSecret: '', cookieAuth: true })
|
|
96
109
|
```
|
|
97
110
|
|
|
98
111
|
`PROD` → `www.ticketfairy.com`, `STAG` → `test.ticketfairy.com`, `DEV` →
|
|
@@ -190,13 +203,81 @@ const order = await checkout.placeOrder('card')
|
|
|
190
203
|
`placeOrder` is retry-safe: one order, one charge, however many times the button
|
|
191
204
|
is pressed.
|
|
192
205
|
|
|
206
|
+
### Starting a new checkout
|
|
207
|
+
|
|
208
|
+
`reset()` discards the cart. It returns nothing, so
|
|
209
|
+
`useEffect(() => checkout.reset(), [eventId])` works as it always has. Before
|
|
210
|
+
any money moves it resets at once. While a payment is going through, it waits
|
|
211
|
+
for the payment to finish, so the payment never lands in a new cart. An order
|
|
212
|
+
that is not confirmed yet is kept when it is charged, or when a payment step
|
|
213
|
+
failed without an answer that nothing was charged (a network error, a
|
|
214
|
+
timeout, or a Stripe error that is not a decline or a cancel). A Razorpay or
|
|
215
|
+
redirect payment page the buyer closes is kept only when a check of the order
|
|
216
|
+
fails or finds a payment; otherwise it is a cancel. Pressing Pay again then
|
|
217
|
+
finishes the order, or pays as usual when nothing was paid. A server refusal
|
|
218
|
+
of the order, such as an expired reservation, releases it.
|
|
219
|
+
|
|
220
|
+
To know which happened, await `resetWhenSettled()` instead. It resolves `true`
|
|
221
|
+
once the checkout is reset, or `false` when it kept the order. In that case,
|
|
222
|
+
show the buyer `PAID_ORDER_PENDING_MESSAGE`. While it waits for a payment
|
|
223
|
+
(`status === 'placing'`), tell the buyer, for example "Finishing your
|
|
224
|
+
payment…":
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
if (checkout.status === 'placing') setNotice('Finishing your payment…')
|
|
228
|
+
if (!(await checkout.resetWhenSettled())) setNotice(PAID_ORDER_PENDING_MESSAGE)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
A custom `providerPage` must resolve `'dismiss'` when it closes or unmounts, and
|
|
232
|
+
any other custom port must settle then too, or `resetWhenSettled()` waits for it.
|
|
233
|
+
|
|
234
|
+
A custom confirmer marks a decline or cancel by rejecting with
|
|
235
|
+
`paymentProviderError(message, 'declined' | 'cancelled')`. Any other rejection
|
|
236
|
+
counts as a payment that may have gone through, so the order is kept.
|
|
237
|
+
|
|
193
238
|
The full SDK is re-exported from this package — `ttf`, `api`, `hooks`, `dtos`,
|
|
194
|
-
`logic`, and the engine. See the [SDK reference](
|
|
239
|
+
`logic`, and the engine. See the [SDK reference](https://github.com/theticketfairy/tf-shared-libraries/blob/main/packages/tf-checkout-shared/README.md).
|
|
240
|
+
|
|
241
|
+
## Rewards
|
|
242
|
+
|
|
243
|
+
The native analogue of the web Rewards section: standing, the referral tree,
|
|
244
|
+
the prize ladder, packs, the share card, and one share button.
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
import { Confirmation, Rewards } from 'tf-checkout-react-native'
|
|
248
|
+
;<Confirmation>
|
|
249
|
+
<Rewards orderHash={orderHash} />
|
|
250
|
+
</Confirmation>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
When `<EmbeddedCheckout/>` renders the receipt itself, pass the block through
|
|
254
|
+
`confirmationChildren`:
|
|
255
|
+
|
|
256
|
+
```tsx
|
|
257
|
+
<EmbeddedCheckout eventId={eventId} confirmationChildren={<MyRewards />} />
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Native adaptations, and why:
|
|
261
|
+
|
|
262
|
+
- **No SVG.** The tree is positioned `View`s, from the same shared layout the
|
|
263
|
+
web SVG uses. Adding `react-native-svg` would be a new native peer for every
|
|
264
|
+
customer app; a dot-and-line picture does not need one.
|
|
265
|
+
- **One share button.** Per-channel buttons collapse into `Share.share()` — the
|
|
266
|
+
OS sheet already lists every installed app, which is what the web's share
|
|
267
|
+
sheet channel reaches for through the browser.
|
|
268
|
+
- **Copy comes in as props**, this package's idiom. `translate`, or `locale` and
|
|
269
|
+
`messages` for the built-in `rewards.*` catalogue.
|
|
270
|
+
|
|
271
|
+
## Seat maps
|
|
272
|
+
|
|
273
|
+
`SeatMap` uses the existing WebView peer to render internal charts or the event's
|
|
274
|
+
Seats.io chart, with the shared core owning selection, holds and reservations.
|
|
275
|
+
It requires the matching backend seating/session contracts. Provider-backed hold
|
|
276
|
+
and deployed-cart acceptance remain separate checks; see the
|
|
277
|
+
[seating contract and evidence](https://github.com/theticketfairy/tf-shared-libraries/blob/main/docs/integration/app-sdk.md#seat-chart-and-ticket-refund-checkpoint--25-october-2026).
|
|
195
278
|
|
|
196
279
|
## Known gaps vs web
|
|
197
280
|
|
|
198
|
-
- **Seat maps** — the seat-picker view is a placeholder until the native picker
|
|
199
|
-
(WebView + seats.io) lands. Non-seated events are unaffected.
|
|
200
281
|
- **Smooth scroll** — no `scrollIntoView` equivalent, so `autoScroll` has no
|
|
201
282
|
native counterpart.
|
|
202
283
|
|
|
@@ -226,4 +307,14 @@ nothing of the sort.
|
|
|
226
307
|
|
|
227
308
|
---
|
|
228
309
|
|
|
229
|
-
Part of the [TicketFairy checkout monorepo](
|
|
310
|
+
Part of the [TicketFairy checkout monorepo](https://github.com/theticketfairy/tf-shared-libraries/blob/main/README.md).
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
Public checkout sign-in uses event-scoped server-only buyer binding, without a bundled
|
|
314
|
+
client secret. The checkout's auth modal supplies the event automatically; standalone
|
|
315
|
+
`AuthModal` callers pass `checkoutEventId` and can receive the narrow
|
|
316
|
+
`onCheckoutAuthenticated(CheckoutBuyerProfile)` callback. Password/signup/email/phone
|
|
317
|
+
proofs still complete required two-factor verification. These credentials cannot read
|
|
318
|
+
private account preferences or tickets. See the [shared identity contract](https://github.com/theticketfairy/tf-shared-libraries/blob/main/packages/tf-checkout-shared/README.md) for
|
|
319
|
+
scope, retry, logout and configuration ownership. Existing confidential OAuth clients
|
|
320
|
+
are trusted-server integrations; never distribute their secrets in browser/native code.
|